OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::GUI::Sidebar Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/GUI/Plater.hpp>

Inheritance diagram for Slic3r::GUI::Sidebar:
Collaboration diagram for Slic3r::GUI::Sidebar:

Classes

struct  priv

Public Types

enum  DockingState { None , Left , Right }

Public Member Functions

 Sidebar (Plater *parent)
 Sidebar (Sidebar &&)=delete
 Sidebar (const Sidebar &)=delete
Sidebar & operator= (Sidebar &&)=delete
Sidebar & operator= (const Sidebar &)=delete
 ~Sidebar ()
void on_enter_image_printer_bed (wxMouseEvent &evt)
void on_leave_image_printer_bed (wxMouseEvent &evt)
void on_change_color_mode (bool is_dark)
void create_printer_preset ()
void init_filament_combo (PlaterPresetComboBox **combo, const int filament_idx)
void remove_unused_filament_combos (const size_t current_extruder_count)
void update_all_preset_comboboxes ()
void update_presets (Slic3r::Preset::Type preset_type)
const std::vector< BedType > & get_cur_combox_bed_types ()
void update_presets_from_to (Slic3r::Preset::Type preset_type, std::string from, std::string to)
BedType get_cur_select_bed_type ()
std::string get_cur_select_bed_image ()
void set_bed_type_accord_combox (BedType bed_type)
bool reset_bed_type_combox_choices (bool is_sidebar_init=false)
void change_top_border_for_mode_sizer (bool increase_border)
void update_filaments_area_height ()
void update_filaments_counter (bool force_layout=false)
void msw_rescale ()
void sys_color_changed ()
void search ()
void jump_to_option (size_t selected)
void jump_to_option (const std::string &opt_key, Preset::Type type, const std::wstring &category)
void on_filament_count_change (size_t num_filaments)
void on_filaments_delete (size_t filament_id)
void add_filament ()
void delete_filament (size_t filament_id=size_t(-1), int replace_filament_id=-1)
void change_filament (size_t from_id, size_t to_id)
void edit_filament ()
void add_custom_filament (wxColour new_col, const std::string &preset_name=std::string(), bool skip_preset_validation=false)
bool is_new_project_in_gcode3mf ()
void on_bed_type_change (BedType bed_type)
void load_ams_list (MachineObject *obj)
std::map< int, DynamicPrintConfig > build_filament_ams_list (MachineObject *obj)
void sync_ams_list (bool is_from_big_sync_btn=false)
bool sync_extruder_list ()
bool is_fila_switch_ready ()
void reset_fila_switch ()
bool need_auto_sync_extruder_list_after_connect_priner (const MachineObject *obj)
void update_sync_status (const MachineObject *obj)
int get_sidebar_pos_right_x ()
void on_size (SimpleEvent &e)
void on_full_screen (IntEvent &)
void get_big_btn_sync_pos_size (wxPoint &pt, wxSize &size)
void get_small_btn_sync_pos_size (wxPoint &pt, wxSize &size)
void show_SEMM_buttons ()
void enable_purge_mode_btn (bool enable)
void set_extruder_nozzle_count (int extruder_id, int nozzle_count)
void enable_nozzle_count_edit (bool enable)
void update_dynamic_filament_list ()
PlaterPresetComboBox * printer_combox ()
ObjectList * obj_list ()
ObjectSettings * obj_settings ()
ObjectLayers * obj_layers ()
wxPanel * scrolled_panel ()
wxPanel * print_panel ()
wxPanel * filament_panel ()
ConfigOptionsGroup * og_freq_chng_params (const bool is_fff)
wxButton * get_wiping_dialog_button ()
void set_flushing_volume_warning (const bool flushing_volume_modify)
void enable_buttons (bool enable)
void set_btn_label (const ActionButtonType btn_type, const wxString &label) const
bool show_reslice (bool show) const
bool show_export (bool show) const
bool show_send (bool show) const
bool show_eject (bool show) const
bool show_export_removable (bool show) const
bool get_eject_shown () const
bool is_multifilament ()
void deal_btn_sync ()
void pop_sync_nozzle_and_ams_dialog ()
void pop_finsish_sync_ams_dialog ()
void update_mode ()
bool is_collapsed ()
void collapse (bool collapse)
void update_searcher ()
void update_ui_from_settings ()
bool show_object_list (bool show) const
void finish_param_edit ()
void auto_calc_flushing_volumes (const int filament_idx=-1, const int extruder_id=-1)
 Automatically calculates flushing volumes.
void jump_to_object (ObjectDataViewModelNode *item)
void can_search ()
void show_mode_sizer (bool show)
std::vector< PlaterPresetComboBox * > & combos_filament ()
void clear_combos_filament_badge ()
void udpate_combos_filament_badge ()
void add_mixed_filament ()
int ensure_mixed_filament (const std::vector< unsigned int > &components, const std::vector< int > &ratios)
void edit_mixed_filament (size_t idx)
void delete_mixed_filament_at (size_t idx)
void remove_all_mixed_filaments ()
void decompose_filament_color (int filament_idx)
void recalc_filament_scroll_sizes ()
void update_mixed_filament_list ()
bool has_broken_mixed_filament () const
bool has_broken_mixed_filament (const PartPlate *plate) const
void collect_physical_filament_info (std::vector< std::string > &color_strs, std::vector< std::string > &names, std::vector< std::string > &types, std::vector< size_t > *config_indices=nullptr)
Search::OptionsSearcher & get_searcher ()
Search::SettingsIndex & settings_index ()
std::string & get_search_line ()
void update_printer_thumbnail ()
bool need_auto_sync_after_connect_printer () const
void set_need_auto_sync_after_connect_printer (bool need_auto_sync)

Static Public Member Functions

static bool should_show_SEMM_buttons ()

Private Member Functions

void update_sync_ams_btn_enable (wxUpdateUIEvent &e)
void auto_calc_flushing_volumes_internal (const int filament_id, const int extruder_id)

Private Attributes

ConfigOptionMode m_mode
ScalableButton * ams_btn {nullptr}
bool m_last_slice_state = false
SyncNozzleAndAmsDialog * m_sna_dialog {nullptr}
FinishSyncAmsDialog * m_fna_dialog {nullptr}
std::vector< BedType > m_cur_combox_bed_types
std::string m_cur_image_bed_type
int m_last_combo_bedtype_count {0}
bool m_begin_sync_printer_status {false}
SyncAmsInfoDialog * m_sync_dlg {nullptr}
std::unique_ptr< priv > p
wxBoxSizer * m_scrolled_sizer = nullptr
bool m_need_auto_sync_after_connect_printer {false}

Detailed Description

Member Enumeration Documentation

◆ DockingState

Enumerator
None 
Left 
Right 
174 {
175 None, Left, Right
176 };
@ Right
Definition Plater.hpp:175
@ None
Definition Plater.hpp:175
@ Left
Definition Plater.hpp:175

Constructor & Destructor Documentation

◆ Sidebar() [1/3]

Slic3r::GUI::Sidebar::Sidebar ( Plater * parent)
2769 : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(39 * wxGetApp().em_unit(), -1)), p(new priv(parent))
2770{
2772 Choice::register_dynamic_list("support_interface_filament", &dynamic_physical_filament_list);
2773 Choice::register_dynamic_list("outer_wall_filament_id", &dynamic_filament_list);
2774 Choice::register_dynamic_list("inner_wall_filament_id", &dynamic_filament_list);
2775 Choice::register_dynamic_list("sparse_infill_filament_id", &dynamic_filament_list);
2776 Choice::register_dynamic_list("internal_solid_filament_id", &dynamic_filament_list);
2777 Choice::register_dynamic_list("top_surface_filament_id", &dynamic_filament_list);
2778 Choice::register_dynamic_list("bottom_surface_filament_id", &dynamic_filament_list);
2780
2781 p->scrolled = new wxPanel(this);
2782 // p->scrolled->SetScrollbars(0, 100, 1, 2); // ys_DELETE_after_testing. pixelsPerUnitY = 100
2783 // but this cause the bad layout of the sidebar, when all infoboxes appear.
2784 // As a result we can see the empty block at the bottom of the sidebar
2785 // But if we set this value to 5, layout will be better
2786 //p->scrolled->SetScrollRate(0, 5);
2787 p->scrolled->SetBackgroundColour(*wxWHITE);
2788
2789
2790 SetFont(wxGetApp().normal_font());
2791#ifndef __APPLE__
2792#ifdef _WIN32
2793 wxGetApp().UpdateDarkUI(this);
2794 wxGetApp().UpdateDarkUI(p->scrolled);
2795#else
2796 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
2797#endif
2798#endif
2799
2800 int em = wxGetApp().em_unit();
2801 //BBS refine layout and styles
2802 // Sizer in the scrolled area
2803 auto* scrolled_sizer = m_scrolled_sizer = new wxBoxSizer(wxVERTICAL);
2804 p->scrolled->SetSizer(scrolled_sizer);
2805
2806 wxColour title_bg = wxColour(248, 248, 248);
2807 wxColour inactive_text = wxColour(86, 86, 86);
2808 wxColour active_text = wxColour(0, 0, 0);
2809 wxColour static_line_col = wxColour(166, 169, 170);
2810
2811#ifdef __WINDOWS__
2812 p->scrolled->SetDoubleBuffered(true);
2813#endif //__WINDOWS__
2814
2815 // add printer
2816 {
2817 /***************** 1. create printer title bar **************/
2818 // 1.1 create title bar resources
2819 p->m_panel_printer_title = new StaticBox(p->scrolled, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL | wxBORDER_NONE);
2820 p->m_panel_printer_title->SetBackgroundColor(title_bg);
2821 p->m_panel_printer_title->SetBackgroundColor2(0xF1F1F1);
2822
2823 p->m_printer_icon = new ScalableButton(p->m_panel_printer_title, wxID_ANY, "printer");
2824 p->m_text_printer_settings = new Label(p->m_panel_printer_title, _L("Printer"), LB_PROPAGATE_MOUSE_EVENT | wxST_ELLIPSIZE_END);
2825
2826 p->m_printer_icon->Bind(wxEVT_BUTTON, [](wxCommandEvent& e) {
2827 //auto wizard_t = new ConfigWizard(wxGetApp().mainframe);
2828 //wizard_t->run(ConfigWizard::RR_USER, ConfigWizard::SP_CUSTOM);
2829 });
2830
2831 // ORCA use connect button on titlebar
2832 p->m_printer_connect = new ScalableButton(p->m_panel_printer_title, wxID_ANY, "monitor_signal_strong");
2833 p->m_printer_connect->SetToolTip(_L("Connection"));
2834 p->m_printer_connect->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) {
2835 PhysicalPrinterDialog dlg(this->GetParent());
2836 dlg.ShowModal();
2837 });
2838
2839 // ORCA use sync button on titlebar
2840 p->m_printer_bbl_sync = new ScalableButton(p->m_panel_printer_title, wxID_ANY, "printer_sync_not");
2841 p->m_printer_bbl_sync->SetToolTip(_L("Synchronize nozzle information and the number of AMS"));
2842 p->m_printer_bbl_sync->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) {
2843 deal_btn_sync();
2844 });
2845
2846 p->m_printer_setting = new ScalableButton(p->m_panel_printer_title, wxID_ANY, "settings");
2847 p->m_printer_setting->Bind(wxEVT_BUTTON, [](wxCommandEvent &e) {
2848 // p->editing_filament = -1;
2849 // wxGetApp().params_dialog()->Popup();
2850 // wxGetApp().get_tab(Preset::TYPE_FILAMENT)->restore_last_select_item();
2851 wxGetApp().run_wizard(ConfigWizard::RR_USER, ConfigWizard::SP_PRINTERS);
2852 });
2853
2854 wxBoxSizer* h_sizer_title = new wxBoxSizer(wxHORIZONTAL);
2855 h_sizer_title->Add(p->m_printer_icon, 0, wxALIGN_CENTRE | wxLEFT, FromDIP(SidebarProps::TitlebarMargin()));
2856 h_sizer_title->AddSpacer(FromDIP(SidebarProps::ElementSpacing()));
2857 h_sizer_title->Add(p->m_text_printer_settings, 1, wxALIGN_CENTER | wxRIGHT, FromDIP(SidebarProps::WideSpacing()));
2858 //h_sizer_title->AddStretchSpacer();
2859 h_sizer_title->Add(p->m_printer_connect , 0, wxALIGN_CENTER | wxRIGHT, FromDIP(SidebarProps::WideSpacing())); // used larger margin to prevent accidental clicks
2860 h_sizer_title->Add(p->m_printer_bbl_sync, 0, wxALIGN_CENTER | wxRIGHT, FromDIP(SidebarProps::WideSpacing())); // used larger margin to prevent accidental clicks
2861 h_sizer_title->Add(p->m_printer_setting, 0, wxALIGN_CENTER);
2862 h_sizer_title->AddSpacer(FromDIP(SidebarProps::TitlebarMargin()));
2863 h_sizer_title->SetMinSize(-1, 3 * em);
2864
2865 p->m_panel_printer_title->SetSizer(h_sizer_title);
2866 p->m_panel_printer_title->Layout();
2867
2868 // 1.2 Add spliters around title bar
2869
2870 // add printer title
2871 scrolled_sizer->Add(p->m_panel_printer_title, 0, wxEXPAND | wxALL, 0);
2872 // ORCA Bind with LEFT_DOWN, since closing a dialog over the title bar can send it a stray LEFT_UP
2873 auto toggle_printer_section = ([this] (wxMouseEvent & e) {
2874 if (!p || !p->combo_printer || !p->m_text_printer_settings || !p->m_panel_printer_content || !m_scrolled_sizer)
2875 return;
2876 // ORCA Show printer name on title when its folded to inform user without expanding it again
2877 bool isShown = p->m_panel_printer_content->IsShown();
2878 wxString title = _L("Printer") + wxString(!isShown ? "" : (" | " + p->combo_printer->GetValue()));
2879 p->m_text_printer_settings->SetLabel(title);
2880 p->m_panel_printer_content->Show(!isShown);
2881 p->m_panel_printer_separator->Show(isShown);
2882 m_scrolled_sizer->Layout();
2883 });
2884 p->m_panel_printer_title->Bind(wxEVT_LEFT_DOWN , toggle_printer_section);
2885 p->m_panel_printer_title->Bind(wxEVT_LEFT_DCLICK, toggle_printer_section);
2886 // ORCA add bottom border for seperation wile sections folded
2887 p->m_panel_printer_separator = new wxPanel(p->scrolled, wxID_ANY, wxDefaultPosition, wxSize(-1, FromDIP(2))); // ORCA staticline class not works without string
2888 p->m_panel_printer_separator->SetBackgroundColour("#FFFFFF");
2889 scrolled_sizer->Add(p->m_panel_printer_separator, 0, wxEXPAND);
2890
2891 /*************************** 2. add printer content ************************/
2892
2893 p->m_panel_printer_content = new wxPanel(p->scrolled, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
2894 p->m_panel_printer_content->SetBackgroundColour(wxColour(255, 255, 255));
2895
2896 struct PanelColors {
2897 wxColour bg_normal = "#FFFFFF";
2898 wxColour bg_focus = "#E5F0EE";
2899 wxColour bd_normal = "#DBDBDB";
2900 wxColour bd_hover = "#009688";
2901 wxColour bd_focus = "#009688";
2902 };
2903 PanelColors panel_color;
2904
2905 p->panel_printer_preset = new StaticBox(p->m_panel_printer_content);
2906 p->panel_printer_preset->SetCornerRadius(FromDIP(PRINTER_PANEL_RADIUS));
2907 p->panel_printer_preset->SetBorderColor(panel_color.bd_normal);
2908 p->panel_printer_preset->SetMinSize(FromDIP(PRINTER_PANEL_SIZE));
2909 p->panel_printer_preset->Bind(wxEVT_LEFT_DOWN, [this](auto & evt) {
2910 p->combo_printer->wxEvtHandler::ProcessEvent(evt);
2911 });
2912 // ORCA Hide Cover automatically if there is not enough space
2913 p->panel_printer_preset->Bind(wxEVT_SIZE, [this](auto & e) {
2914 auto current_width = e.GetSize().GetWidth();
2915 auto narrow_width = FromDIP(235);
2916 auto label_width = p->combo_printer->GetTextExtent(p->combo_printer->GetStringSelection()).GetWidth();
2917 auto min_width = label_width + FromDIP(25 + PRINTER_PANEL_SIZE.GetWidth());
2918 if(((min_width < narrow_width && min_width > current_width) || (current_width < narrow_width && min_width > narrow_width)) && p->image_printer->IsShown())
2919 p->image_printer->Hide();
2920 else if((current_width > min_width || !(current_width < narrow_width)) && !p->image_printer->IsShown())
2921 p->image_printer->Show();
2922 e.Skip();
2923 });
2924
2925 // hover state data for printer panel
2926 auto printer_preset_hovered = std::make_shared<std::unordered_set<wxWindow*>>();
2927
2928 p->btn_edit_printer = new ScalableButton(p->panel_printer_preset, wxID_ANY, "edit");
2929 p->btn_edit_printer->SetToolTip(_L("Click to edit preset"));
2930 p->btn_edit_printer->Hide(); // hide for first launch
2931 p->btn_edit_printer->Bind(wxEVT_BUTTON, [this, panel_color, printer_preset_hovered](wxCommandEvent){
2932 p->editing_filament = -1;
2933 if (p->combo_printer->switch_to_tab())
2934 p->editing_filament = 0;
2935 // ORCA: FIX crash on wxGTK, directly modifying UI (self->Hide() / parent->Layout()) inside a button event can crash because callbacks are not re-entrant, leaving widgets in an inconsistent state
2936 wxGetApp().CallAfter([this, panel_color, printer_preset_hovered]() {
2937 // ORCA clicking edit button not triggers wxEVT_KILL_FOCUS wxEVT_LEAVE_WINDOW make changes manually to prevent stucked colors when opening printer settings
2938 if (!p || !p->panel_printer_preset || !p->btn_edit_printer)
2939 return;
2940 p->panel_printer_preset->SetBorderColor(panel_color.bd_normal);
2941 printer_preset_hovered->clear();
2942 p->btn_edit_printer->Hide();
2943 p->panel_printer_preset->Layout();
2944 });
2945 });
2946
2947 ScalableBitmap bitmap_printer(p->panel_printer_preset, "printer_placeholder", PRINTER_THUMBNAIL_SIZE.GetHeight());
2948 p->image_printer = new wxStaticBitmap(p->panel_printer_preset, wxID_ANY, bitmap_printer.bmp(), wxDefaultPosition, FromDIP(PRINTER_THUMBNAIL_SIZE), 0);
2949 p->image_printer->Bind(wxEVT_LEFT_DOWN, [this](auto &evt) {
2950 p->combo_printer->wxEvtHandler::ProcessEvent(evt);
2951 });
2952
2953 p->combo_printer = new PlaterPresetComboBox(p->panel_printer_preset, Preset::TYPE_PRINTER);
2954 p->combo_printer->SetBorderWidth(0);
2955 p->combo_printer->SetMaxSize(wxSize(-1, FromDIP(30))); // limiting height makes badge visible
2956 // ORCA paint whole combobox on focus
2957 auto printer_focus_bg = [this, panel_color](bool focused){
2958 auto bg_color = StateColor::darkModeColorFor(focused ? panel_color.bg_focus : panel_color.bg_normal);
2959 p->panel_printer_preset->SetBackgroundColor(bg_color);
2960 p->panel_printer_preset->SetBorderColor(focused ? panel_color.bd_focus : panel_color.bd_normal);
2961 p->btn_edit_printer->SetBackgroundColour(bg_color);
2962 p->image_printer->SetBackgroundColour(bg_color);
2963 p->combo_printer->SetBackgroundColour(bg_color); // paints margins instead combo background
2964 };
2965 p->combo_printer->Bind(wxEVT_SET_FOCUS, [printer_focus_bg](auto& e) {printer_focus_bg(true ); e.Skip();});
2966 p->combo_printer->Bind(wxEVT_KILL_FOCUS, [printer_focus_bg](auto& e) {printer_focus_bg(false); e.Skip();});
2967
2968 /* ORCA This part moved to titlebar
2969 p->btn_connect_printer = new ScalableButton(p->panel_printer_preset, wxID_ANY, "monitor_signal_strong");
2970 p->btn_connect_printer->SetBackgroundColour(wxColour(255, 255, 255));
2971 p->btn_connect_printer->SetToolTip(_L("Connection"));
2972 p->btn_connect_printer->Bind(wxEVT_BUTTON, [this, combo_printer](wxCommandEvent)
2973 {
2974 PhysicalPrinterDialog dlg(this->GetParent());
2975 dlg.ShowModal();
2976 });
2977 */
2978 // ORCA use Show/Hide to gain text area instead using blank icon. also manages hover effect for border
2979 for (wxWindow *w : std::initializer_list<wxWindow *>{p->panel_printer_preset, p->btn_edit_printer, p->image_printer, p->combo_printer}) {
2980 w->Bind(wxEVT_ENTER_WINDOW, [this, w, panel_color, printer_preset_hovered](wxMouseEvent &e) {
2981 printer_preset_hovered->insert(w);
2982 if(!p->combo_printer->HasFocus())
2983 p->panel_printer_preset->SetBorderColor(panel_color.bd_hover);
2984 e.Skip();
2985 });
2986 w->Bind(wxEVT_LEAVE_WINDOW, [this, w, panel_color, printer_preset_hovered](wxMouseEvent &e) {
2987 printer_preset_hovered->erase(w);
2988 if (printer_preset_hovered->empty() && !p->combo_printer->HasFocus())
2989 p->panel_printer_preset->SetBorderColor(panel_color.bd_normal);
2990 e.Skip();
2991 });
2992 }
2993 // Perform show/hide in wxEVT_IDLE after enter/leave events have settled.
2994 // This prevents the extraneous enter/leave events generated by the
2995 // layout change itself from causing a feedback loop.
2996 Bind(wxEVT_IDLE, [this, printer_preset_hovered](wxIdleEvent &e) {
2997 auto hovered = !printer_preset_hovered->empty();
2998 if (p->btn_edit_printer->IsShown() != hovered) {
2999 if (hovered) {
3000 p->btn_edit_printer->Show();
3001 } else {
3002 p->btn_edit_printer->Hide();
3003 }
3004 p->panel_printer_preset->Layout();
3005 }
3006 });
3007
3008 // ORCA unified Nozzle diameter selection
3009 p->panel_nozzle_dia = new StaticBox(p->m_panel_printer_content);
3010 p->panel_nozzle_dia->SetCornerRadius(FromDIP(PRINTER_PANEL_RADIUS));
3011 p->panel_nozzle_dia->SetBorderColor(panel_color.bd_normal);
3012 p->panel_nozzle_dia->SetMinSize(FromDIP(PRINTER_PANEL_SIZE));
3013 p->panel_nozzle_dia->Bind(wxEVT_LEFT_DOWN, [this](auto & evt) {
3014 p->combo_nozzle_dia->wxEvtHandler::ProcessEvent(evt);
3015 });
3016
3017 // "Variant", not "Nozzle": picking one switches the printer preset (see panel_nozzle_dia).
3018 // TRN Sidebar label of the printer variant (nozzle) selector; picking one switches the printer preset.
3019 p->label_nozzle_title = new Label(p->panel_nozzle_dia, _L("Variant"), LB_PROPAGATE_MOUSE_EVENT);
3020 p->label_nozzle_title->SetFont(Label::Body_10);
3021
3022 p->combo_nozzle_dia = new ComboBox(p->panel_nozzle_dia, wxID_ANY, wxString(""), wxDefaultPosition, wxDefaultSize, 0, nullptr, wxCB_READONLY);
3023 p->combo_nozzle_dia->SetBorderWidth(0);
3024 p->combo_nozzle_dia->GetDropDown().SetUseContentWidth(true);
3025 p->combo_nozzle_dia->SetMinSize(FromDIP(wxSize(PRINTER_PANEL_SIZE.GetWidth() - 4, 26))); // requires a static value in here
3026 p->combo_nozzle_dia->SetMaxSize(FromDIP(wxSize(PRINTER_PANEL_SIZE.GetWidth() - 4, 26))); // using -1 with wxEXPAND has issues
3027 p->combo_nozzle_dia->Bind(wxEVT_COMBOBOX, [this](auto &e) {
3028 // This box is the machine-variant selector, so it switches the printer preset directly
3029 // instead of feeding an extruder card's combo. Deferred, because switching preset
3030 // rebuilds this very combo.
3031 const wxString diameter = p->combo_nozzle_dia->GetValue();
3032 p->combo_nozzle_dia->CallAfter([this, diameter]() {
3033 p->is_switching_diameter = true;
3034 p->switch_diameter_to(diameter);
3035 p->is_switching_diameter = false;
3036 });
3037 e.Skip();
3038 });
3039 // ORCA paint whole combobox on focus
3040 auto nozzle_focus_bg = [this, panel_color](bool focused){
3041 auto bg_color = StateColor::darkModeColorFor(focused ? panel_color.bg_focus : panel_color.bg_normal);
3042 p->panel_nozzle_dia->SetBackgroundColor(bg_color);
3043 p->panel_nozzle_dia->SetBorderColor(focused ? panel_color.bd_focus : panel_color.bd_normal);
3044 p->label_nozzle_title->SetBackgroundColour(bg_color);
3045 p->label_nozzle_type->SetBackgroundColour(bg_color);
3046 p->combo_nozzle_dia->SetBackgroundColour(bg_color); // paints margins instead combo background
3047 };
3048 p->combo_nozzle_dia->Bind(wxEVT_SET_FOCUS, [nozzle_focus_bg](auto& e) {nozzle_focus_bg(true ); e.Skip();});
3049 p->combo_nozzle_dia->Bind(wxEVT_KILL_FOCUS, [nozzle_focus_bg](auto& e) {nozzle_focus_bg(false); e.Skip();});
3050
3051 p->label_nozzle_type = new Label(p->panel_nozzle_dia, _L("Brass"), LB_PROPAGATE_MOUSE_EVENT | wxST_ELLIPSIZE_END | wxALIGN_CENTRE_HORIZONTAL);
3052 p->label_nozzle_type->SetFont(Label::Body_10);
3053 p->label_nozzle_type->SetMinSize(FromDIP(wxSize(56, -1)));
3054 p->label_nozzle_type->SetMaxSize(FromDIP(wxSize(56, -1)));
3055
3056 // highlight border on hover
3057 auto nozzle_dia_hovered = std::make_shared<std::unordered_set<wxWindow*>>();
3058 for (wxWindow *w : std::initializer_list<wxWindow *>{p->panel_nozzle_dia, p->label_nozzle_title, p->label_nozzle_type, p->combo_nozzle_dia}) {
3059 w->Bind(wxEVT_ENTER_WINDOW, [this, w, panel_color, nozzle_dia_hovered](wxMouseEvent &e) {
3060 nozzle_dia_hovered->insert(w);
3061 if(!p->combo_nozzle_dia->HasFocus())
3062 p->panel_nozzle_dia->SetBorderColor(panel_color.bd_hover);
3063 e.Skip();
3064 });
3065 w->Bind(wxEVT_LEAVE_WINDOW, [this, w, panel_color, nozzle_dia_hovered](wxMouseEvent &e) {
3066 nozzle_dia_hovered->erase(w);
3067 if (nozzle_dia_hovered->empty() && !p->combo_nozzle_dia->HasFocus())
3068 p->panel_nozzle_dia->SetBorderColor(panel_color.bd_normal);
3069 e.Skip();
3070 });
3071 }
3072
3073 wxGridSizer *nozzle_dia_sizer = new wxGridSizer(3, 1, FromDIP(2), 0);
3074 nozzle_dia_sizer->Add(p->label_nozzle_title, 1, wxALIGN_CENTER | wxTOP , FromDIP(2));
3075 nozzle_dia_sizer->Add(p->combo_nozzle_dia , 0, wxALIGN_CENTER);
3076 nozzle_dia_sizer->Add(p->label_nozzle_type , 1, wxALIGN_CENTER | wxBOTTOM, FromDIP(1));
3077
3078 p->panel_nozzle_dia->SetSizer(nozzle_dia_sizer);
3079
3080 // Bed type selection
3081 p->panel_printer_bed = new StaticBox(p->m_panel_printer_content);
3082 p->panel_printer_bed->SetCornerRadius(FromDIP(PRINTER_PANEL_RADIUS));
3083 p->panel_printer_bed->SetBorderColor(panel_color.bd_normal);
3084 p->panel_printer_bed->SetMinSize(FromDIP(PRINTER_PANEL_SIZE));
3085 p->panel_printer_bed->Bind(wxEVT_LEFT_DOWN, [this](auto &evt) {
3087 p->combo_printer_bed->wxEvtHandler::ProcessEvent(evt);
3088 });
3089
3090 //ScalableButton *wiki_bed = new ScalableButton(p->panel_printer_bed, wxID_ANY, "help");
3091 //wiki_bed->Bind(wxEVT_BUTTON, [](wxCommandEvent) {
3092 // wxLaunchDefaultBrowser("https://wiki.bambulab.com/en/x1/manual/compatibility-and-parameter-settings-of-filaments");
3093 //});
3094
3095 ScalableBitmap bitmap_bed(p->panel_printer_bed, "printer_placeholder", PRINTER_THUMBNAIL_SIZE.GetHeight());
3096 p->image_printer_bed = new wxStaticBitmap(p->panel_printer_bed, wxID_ANY, bitmap_bed.bmp(), wxDefaultPosition, wxDefaultSize, 0);
3097 p->image_printer_bed->Bind(wxEVT_LEFT_DOWN, [this](auto &evt) {
3099 p->combo_printer_bed->wxEvtHandler::ProcessEvent(evt);
3100 });
3101
3102 p->combo_printer_bed = new ComboBox(p->panel_printer_bed, wxID_ANY, wxString(""), wxDefaultPosition, wxDefaultSize, 0, nullptr, wxCB_READONLY);
3103 p->combo_printer_bed->SetBorderWidth(0);
3104 p->combo_printer_bed->GetDropDown().SetUseContentWidth(true);
3105 p->combo_printer_bed->SetMinSize(FromDIP(wxSize(18,-1))); // ORCA show only arrow
3106 p->combo_printer_bed->SetMaxSize(FromDIP(wxSize(18,-1))); // ORCA show only arrow
3108
3109 p->combo_printer_bed->Bind(wxEVT_COMBOBOX, [this](auto &e) {
3110 auto image_path = get_cur_select_bed_image();
3111 p->image_printer_bed->SetBitmap(create_scaled_bitmap(image_path, this, PRINTER_THUMBNAIL_SIZE.GetHeight()));
3112 e.Skip();
3113 });
3114
3115 // ORCA paint whole combobox on focus
3116 auto bed_focus_bg = [this, panel_color](bool focused){
3117 auto bg_color = StateColor::darkModeColorFor(focused ? panel_color.bg_focus : panel_color.bg_normal);
3118 p->panel_printer_bed->SetBackgroundColor(bg_color);
3119 p->panel_printer_bed->SetBorderColor(focused ? panel_color.bd_focus : panel_color.bd_normal);
3120 p->image_printer_bed->SetBackgroundColour(bg_color);
3121 p->combo_printer_bed->SetBackgroundColour(bg_color); // paints margins instead combo background
3122 };
3123 p->combo_printer_bed->Bind(wxEVT_SET_FOCUS, [bed_focus_bg](auto& e) {bed_focus_bg(true ); e.Skip();});
3124 p->combo_printer_bed->Bind(wxEVT_KILL_FOCUS, [bed_focus_bg](auto& e) {bed_focus_bg(false); e.Skip();});
3125
3126 // highlight border on hover
3127 auto printer_bed_hovered = std::make_shared<std::unordered_set<wxWindow*>>();
3128 for (wxWindow *w : std::initializer_list<wxWindow *>{p->panel_printer_bed, p->image_printer_bed, p->combo_printer_bed}) {
3129 w->Bind(wxEVT_ENTER_WINDOW, [this, w, panel_color, printer_bed_hovered](wxMouseEvent &e) {
3130 printer_bed_hovered->insert(w);
3131 if(!p->combo_printer_bed->HasFocus())
3132 p->panel_printer_bed->SetBorderColor(panel_color.bd_hover);
3133 if(w == p->image_printer_bed && !p->combo_printer_bed->is_drop_down()) // dont trigger while combo open
3135 e.Skip();
3136 });
3137 w->Bind(wxEVT_LEAVE_WINDOW, [this, w, panel_color, printer_bed_hovered](wxMouseEvent &e) {
3138 printer_bed_hovered->erase(w);
3139 if (printer_bed_hovered->empty() && !p->combo_printer_bed->HasFocus())
3140 p->panel_printer_bed->SetBorderColor(panel_color.bd_normal);
3141 if(w == p->image_printer_bed)
3143 e.Skip();
3144 });
3145 }
3146
3147 wxBoxSizer *bed_type_sizer = new wxBoxSizer(wxHORIZONTAL);
3148 bed_type_sizer->Add(p->combo_printer_bed, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
3149 bed_type_sizer->Add(p->image_printer_bed, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
3150
3151 p->panel_printer_bed->SetSizer(bed_type_sizer);
3152
3153 AppConfig *app_config = wxGetApp().app_config;
3154 std::string str_bed_type = app_config->get("curr_bed_type");
3155 int bed_type_value = atoi(str_bed_type.c_str());
3156 // hotfix: btDefault is added as the first one in BedType, and app_config should not be btDefault
3157 if (bed_type_value == 0) {
3158 app_config->set("curr_bed_type", "1");
3159 bed_type_value = 1;
3160 }
3161
3162 int bed_type_idx = bed_type_value - 1;
3163 p->combo_printer_bed->Select(bed_type_idx);
3164
3165 auto& project_config = wxGetApp().preset_bundle->project_config;
3166 /*const t_config_enum_values* keys_map = print_config_def.get("curr_bed_type")->enum_keys_map;
3167 BedType bed_type = btCount;
3168 for (auto item : *keys_map) {
3169 if (item.first == str_bed_type)
3170 bed_type = (BedType)item.second;
3171 }*/
3172 BedType bed_type = (BedType)bed_type_value;
3173 project_config.set_key_value("curr_bed_type", new ConfigOptionEnum<BedType>(bed_type));
3174
3175 /* ORCA THIS PART MOVED TO TITLEBAR
3176 // Sync printer information
3177 btn_sync = new Button(p->m_panel_printer_content, _L("Sync info"), "printer_sync", 0, 32);
3178 //btn_sync->SetFont(Label::Body_8);
3179 btn_sync->SetToolTip(_L("Synchronize nozzle information and the number of AMS"));
3180 btn_sync->SetCornerRadius(8);
3181 StateColor btn_sync_bg_col(
3182 std::pair<wxColour, int>(wxColour("#CECECE"), StateColor::Pressed),
3183 std::pair<wxColour, int>(wxColour("#F8F8F8"), StateColor::Hovered),
3184 std::pair<wxColour, int>(wxColour("#F8F8F8"), StateColor::Normal));
3185 StateColor btn_sync_bd_col(
3186 std::pair<wxColour, int>(wxColour("#009688"), StateColor::Pressed),
3187 std::pair<wxColour, int>(wxColour("#009688"), StateColor::Hovered),
3188 std::pair<wxColour, int>(wxColour("#EEEEEE"), StateColor::Normal));
3189 btn_sync->SetBackgroundColor(btn_sync_bg_col);
3190 btn_sync->SetBorderColor(btn_sync_bd_col);
3191 btn_sync->SetCanFocus(false);
3192 btn_sync->SetPaddingSize({FromDIP(6), FromDIP(12)});
3193 btn_sync->SetMinSize(BTN_SYNC_SIZE);
3194 btn_sync->SetMaxSize(BTN_SYNC_SIZE);
3195 btn_sync->SetVertical();
3196 btn_sync->Bind(wxEVT_UPDATE_UI, &Sidebar::update_sync_ams_btn_enable, this);
3197 btn_sync->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) {
3198 deal_btn_sync();
3199 });
3200 p->btn_sync_printer = btn_sync;
3201 */
3202 p->timer_sync_printer->Bind(wxEVT_TIMER, [this] (wxTimerEvent & e) {
3203 p->flush_printer_sync();
3204 });
3205
3206
3207 p->left_extruder = new ExtruderGroup(p->m_panel_printer_content, 0, _L("Left Nozzle"));
3208 p->right_extruder = new ExtruderGroup(p->m_panel_printer_content, 1, _L("Right Nozzle"));
3209 p->single_extruder = new ExtruderGroup(p->m_panel_printer_content, -1, _L("Nozzle"));
3210 // manuallySetNozzleCount refreshes the badge and the plater itself; it is a no-op unless the
3211 // printer has a multi-nozzle extruder (and the edit button is only enabled then, see
3212 // enable_nozzle_count_edit).
3213 p->left_extruder->SetOnHoverClick([]() { GUI::manuallySetNozzleCount(0); });
3214 p->right_extruder->SetOnHoverClick([]() { GUI::manuallySetNozzleCount(1); });
3215 p->single_extruder->SetEditEnabled(false);
3216 // Orca: keep the floating switcher icon aligned with the left extruder's AMS row when the
3217 // extruder card is resized (the overlay is absolutely positioned, not managed by a sizer).
3218 p->left_extruder->Bind(wxEVT_SIZE, [this](wxSizeEvent &evt) {
3219 if (p->extruder_separator_icon && p->extruder_separator_icon->IsShown()) {
3220 wxPoint left_box_pos = p->left_extruder->GetPosition();
3221 wxPoint ams_local_pos = p->left_extruder->hsizer_ams->GetPosition();
3222 wxSize left_size = p->left_extruder->sizer->GetSize();
3223 wxSize ams_size = p->left_extruder->hsizer_ams->GetSize();
3224 wxSize icon_size = p->extruder_separator_icon->GetSize();
3225 int ams_abs_y = left_box_pos.y + ams_local_pos.y + FromDIP(4);
3226 int center_x = left_size.GetWidth() + FromDIP(6) - icon_size.GetWidth() / 2;
3227 int center_y = ams_abs_y + (ams_size.GetHeight() - icon_size.GetHeight()) / 2 - icon_size.GetHeight() / 2;
3228 p->extruder_separator_icon->SetPosition(wxPoint(center_x, center_y));
3229 if (p->m_panel_printer_content)
3230 p->m_panel_printer_content->Refresh();
3231 }
3232 evt.Skip();
3233 });
3234 auto switch_diameter = [this](wxCommandEvent & evt) {
3235 auto extruder = dynamic_cast<ExtruderGroup *>(dynamic_cast<ComboBox *>(evt.GetEventObject())->GetParent());
3236 p->is_switching_diameter = true;
3237 p->switch_diameter(extruder == p->single_extruder);
3238 p->is_switching_diameter = false;
3239 };
3240 p->left_extruder->combo_diameter->Bind(wxEVT_COMBOBOX, switch_diameter);
3241 p->right_extruder->combo_diameter->Bind(wxEVT_COMBOBOX, switch_diameter);
3242 p->single_extruder->combo_diameter->Bind(wxEVT_COMBOBOX, switch_diameter);
3243
3244 p->vsizer_printer = new wxBoxSizer(wxVERTICAL);
3245 p->layout_printer(true, true);
3246 p->m_panel_printer_content->SetSizer(p->vsizer_printer);
3247 p->m_panel_printer_content->Layout();
3248 scrolled_sizer->Add(p->m_panel_printer_content, 0, wxEXPAND, 0);
3249 }
3250
3251 {
3252
3253 // Orca: Sidebar - Filament titlebar UI
3254 // add filament title
3255 p->m_panel_filament_title = new StaticBox(p->scrolled, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL | wxBORDER_NONE);
3256 p->m_panel_filament_title->SetBackgroundColor(title_bg);
3257 p->m_panel_filament_title->SetBackgroundColor2(0xF1F1F1);
3258 // ORCA Bind with LEFT_DOWN, since closing a dialog over the title bar can send it a stray LEFT_UP
3259 auto toggle_filament_section = ([this](wxMouseEvent &e) {
3260 if (!p || !p->m_filament_area_wrapper || !m_scrolled_sizer || !p->m_bpButton_set_filament || !p->m_purge_mode_btn || !p->m_flushing_volume_btn || !p->m_bpButton_add_filament || !ams_btn)
3261 return;
3262 // ORCA exclude area of del button from titlebar collapse/expand feature to fix undesired collapse when user spams del filament button
3263 // also block fold/unfold feature when user clicks to spacing between icons
3264 int exclude_pt = p->m_bpButton_set_filament->GetPosition().x; // maximum fixed item
3265 if (p->m_purge_mode_btn->IsShown()) exclude_pt = p->m_purge_mode_btn->GetPosition().x;
3266 else if (p->m_flushing_volume_btn->IsShown()) exclude_pt = p->m_flushing_volume_btn->GetPosition().x;
3267 else if (p->m_bpButton_add_filament->IsShown()) exclude_pt = p->m_bpButton_add_filament->GetPosition().x - FromDIP(30); // reserve spacing for delete button
3268 else if (ams_btn->IsShown()) exclude_pt = ams_btn->GetPosition().x;
3269 if (e.GetPosition().x > exclude_pt)
3270 return;
3271 bool isShown = p->m_filament_area_wrapper->IsShown();
3272 p->m_filament_area_wrapper->Show(!isShown);
3273 p->m_panel_filament_separator->Show(isShown);
3274 m_scrolled_sizer->Layout();
3275
3276 CallAfter([this]{update_filaments_counter(true);}); // call after all UI processing done
3277 });
3278 p->m_panel_filament_title->Bind(wxEVT_LEFT_DOWN , toggle_filament_section);
3279 p->m_panel_filament_title->Bind(wxEVT_LEFT_DCLICK, toggle_filament_section);
3280
3281 wxBoxSizer* bSizer39;
3282 bSizer39 = new wxBoxSizer( wxHORIZONTAL );
3283 p->m_filament_icon = new ScalableButton(p->m_panel_filament_title, wxID_ANY, "filament");
3284 p->m_staticText_filament_settings = new Label(p->m_panel_filament_title, _L("Project Filaments"), LB_PROPAGATE_MOUSE_EVENT);
3285 bSizer39->Add(p->m_filament_icon, 0, wxALIGN_CENTER | wxLEFT, FromDIP(SidebarProps::TitlebarMargin()));
3286 bSizer39->Add(p->m_staticText_filament_settings, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, FromDIP(SidebarProps::ElementSpacing()));
3287 bSizer39->SetMinSize(-1, FromDIP(30));
3288
3289 p->m_staticText_filament_count = new Label(p->m_panel_filament_title, "(0)", LB_PROPAGATE_MOUSE_EVENT);
3290 bSizer39->Add(p->m_staticText_filament_count, 0, wxALIGN_CENTER );
3291 bSizer39->Add(FromDIP(10), 0, 0, 0, 0);
3292
3293 p->m_panel_filament_title->SetSizer( bSizer39 );
3294 p->m_panel_filament_title->Layout();
3295 scrolled_sizer->Add(p->m_panel_filament_title, 0, wxEXPAND | wxALL, 0);
3296 // ORCA add bottom border for seperation wile sections folded
3297 p->m_panel_filament_separator = new wxPanel(p->scrolled, wxID_ANY, wxDefaultPosition, wxSize(-1, FromDIP(2))); // ORCA staticline class not works without string
3298 p->m_panel_filament_separator->SetBackgroundColour("#FFFFFF");
3299 scrolled_sizer->Add(p->m_panel_filament_separator, 0, wxEXPAND);
3300
3301 bSizer39->AddStretchSpacer(1);
3302
3303 p->m_purge_mode_btn = new Button(p->m_panel_filament_title, _L("Purge mode"));
3304 p->m_purge_mode_btn->SetStyle(ButtonStyle::Confirm, ButtonType::Compact);
3305
3306 p->m_purge_mode_btn->Bind(wxEVT_BUTTON, [](wxCommandEvent &e) {
3307 auto &preset_bundle = *wxGetApp().preset_bundle;
3308 auto support_fast_purge_opt = preset_bundle.printers.get_edited_preset().config.option<ConfigOptionBool>("support_fast_purge_mode");
3309 bool support_fast_purge = support_fast_purge_opt ? support_fast_purge_opt->value : false;
3310 auto dlg_type = support_fast_purge ? PurgeModeDialogType::FastMode : PurgeModeDialogType::MultiNozzle;
3311 PurgeModeDialog dlg(static_cast<wxWindow *>(wxGetApp().mainframe), dlg_type);
3312 if (dlg.ShowModal() == wxID_OK) {
3313 preset_bundle.project_config.set_key_value("prime_volume_mode", new ConfigOptionEnum<PrimeVolumeMode>(dlg.get_selected_mode()));
3314 wxGetApp().plater()->update();
3315 }
3316 });
3317
3318 bSizer39->Add(p->m_purge_mode_btn, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(4));
3319 bSizer39->Hide(p->m_purge_mode_btn); // hidden on launch; shown only for printers that support purge mode selection
3320
3321 // BBS
3322 // add wiping dialog
3323 //wiping_dialog_button->SetFont(wxGetApp().normal_font());
3324 p->m_flushing_volume_btn = new Button(p->m_panel_filament_title, _L("Flushing volumes"));
3325 p->m_flushing_volume_btn->SetStyle(ButtonStyle::Confirm, ButtonType::Compact);
3326 p->m_flushing_volume_btn->SetId(wxID_RESET);
3327 auto has_modify = is_flush_config_modified();
3328 set_flushing_volume_warning(has_modify);
3329
3330 p->m_flushing_volume_btn->Bind(wxEVT_BUTTON, ([parent, this](wxCommandEvent &e) {
3331 open_flushing_dialog(parent, SimpleEvent(EVT_SCHEDULE_BACKGROUND_PROCESS, parent));
3332 p->plater->get_view3D_canvas3D()->reload_scene(true);
3333 p->plater->update();
3334 }));
3335
3336 bSizer39->Add(p->m_flushing_volume_btn, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(4));
3337 bSizer39->Hide(p->m_flushing_volume_btn); // ORCA Ensure button is hidden on launch while 1 filament exist
3338
3339 ScalableButton* add_btn = new ScalableButton(p->m_panel_filament_title, wxID_ANY, "add_filament");
3340 add_btn->SetToolTip(_L("Add one filament"));
3341 add_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e){
3342 add_filament();
3344 });
3345 p->m_bpButton_add_filament = add_btn;
3346
3347 // ORCA Moved add button after delete button to prevent add button position change when remove icon automatically hidden
3348
3349 ScalableButton* del_btn = new ScalableButton(p->m_panel_filament_title, wxID_ANY, "delete_filament");
3350 del_btn->SetToolTip(_L("Remove last filament"));
3351 del_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) {
3354 });
3355 p->m_bpButton_del_filament = del_btn;
3356
3357 bSizer39->Add(del_btn, 0, wxALIGN_CENTER | wxLEFT, FromDIP(SidebarProps::IconSpacing()));
3358 bSizer39->Add(add_btn, 0, wxALIGN_CENTER | wxLEFT, FromDIP(SidebarProps::IconSpacing())); // ORCA Moved add button after delete button to prevent add button position change when remove icon automatically hidden
3359
3360 bSizer39->Hide(p->m_bpButton_del_filament); // ORCA Ensure button is hidden on launch while 1 filament exist
3361
3362 ams_btn = new ScalableButton(p->m_panel_filament_title, wxID_ANY, "ams_fila_sync", wxEmptyString, wxDefaultSize, wxDefaultPosition,
3363 wxBU_EXACTFIT | wxNO_BORDER, false, 16); // ORCA match icon size with other icons as 16x16
3364 ams_btn->SetToolTip(_L("Synchronize filament list from AMS"));
3365 ams_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) {
3366 sync_ams_list();
3367 });
3368
3369 ams_btn->Bind(wxEVT_UPDATE_UI, &Sidebar::update_sync_ams_btn_enable, this);
3370 p->m_bpButton_ams_filament = ams_btn;
3371
3372 bSizer39->Add(ams_btn, 0, wxALIGN_CENTER | wxLEFT, FromDIP(SidebarProps::WideSpacing()));
3373 //bSizer39->Add(FromDIP(10), 0, 0, 0, 0 );
3374
3375 ScalableButton* set_btn = new ScalableButton(p->m_panel_filament_title, wxID_ANY, "settings");
3376 set_btn->SetToolTip(_L("Set filaments to use"));
3377 set_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) {
3378 p->editing_filament = -1;
3379 // wxGetApp().params_dialog()->Popup();
3380 // wxGetApp().get_tab(Preset::TYPE_FILAMENT)->restore_last_select_item();
3381 wxGetApp().run_wizard(ConfigWizard::RR_USER, ConfigWizard::SP_FILAMENTS);
3382 });
3383 p->m_bpButton_set_filament = set_btn;
3384
3385 bSizer39->Add(set_btn, 0, wxALIGN_CENTER | wxLEFT, FromDIP(SidebarProps::WideSpacing()));
3386 bSizer39->AddSpacer(FromDIP(SidebarProps::TitlebarMargin()));
3387
3388 // ---- Wrapper panel for collapse/expand of all filament content ----
3389 p->m_filament_area_wrapper = new wxPanel(p->scrolled, wxID_ANY);
3390 p->m_filament_area_wrapper->SetBackgroundColour(*wxWHITE);
3391 auto* wrapper_sizer = new wxBoxSizer(wxVERTICAL);
3392
3393 // add filament content
3394 p->m_panel_filament_content = new wxScrolledWindow(p->m_filament_area_wrapper, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
3395 p->m_panel_filament_content->SetScrollRate(0, FromDIP(20));
3396 //p->m_panel_filament_content->SetMaxSize(wxSize{-1, FromDIP(174)});
3397 p->m_panel_filament_content->SetBackgroundColour(wxColour(255, 255, 255));
3398
3399 //wxBoxSizer* bSizer_filament_content;
3400 //bSizer_filament_content = new wxBoxSizer( wxHORIZONTAL );
3401
3402 // Orca: Sidebar - Filament content UI: setup filament selection combos panel layout
3403 // Creates a two-column grid layout for filament selection dropdowns within the scrollable panel
3404 p->sizer_filaments = new wxBoxSizer(wxHORIZONTAL);
3405 p->sizer_filaments->Add(new wxBoxSizer(wxVERTICAL), 1, wxEXPAND);
3406 p->sizer_filaments->Add(new wxBoxSizer(wxVERTICAL), 1, wxEXPAND);
3407
3408 p->combos_filament.push_back(nullptr);
3409
3410 /* first filament item */
3411 init_filament_combo(&p->combos_filament[0], 0);
3412
3413 //bSizer_filament_content->Add(p->sizer_filaments, 1, wxALIGN_CENTER | wxALL);
3414 wxSizer *sizer_filaments2 = new wxBoxSizer(wxVERTICAL);
3415 sizer_filaments2->Add(p->sizer_filaments, 0, wxEXPAND, 0);
3416 p->m_panel_filament_content->SetSizer(sizer_filaments2);
3417 p->m_panel_filament_content->Layout();
3418
3420
3421 wrapper_sizer->Add(p->m_panel_filament_content, 0, wxEXPAND);
3422
3423 // ---- Mixed-color filament section ----
3424 // A mixed filament is a virtual slot realized from 2-3 physical filaments at slicing time.
3425 // Everything here stays hidden until at least two physical filaments exist, so a single
3426 // filament setup looks exactly as before.
3427 {
3428 // 1) "+ Add Mixed Filament" button, shown only while no mixed filament exists yet.
3429 p->m_btn_add_mixed_filament = new wxPanel(p->m_filament_area_wrapper, wxID_ANY);
3430 p->m_btn_add_mixed_filament->SetBackgroundColour(StateColor::darkModeColorFor(wxColour("#F8F8F8")));
3431 p->m_btn_add_mixed_filament->SetMinSize(wxSize(-1, FromDIP(23)));
3432 {
3433 auto* btn_sizer = new wxBoxSizer(wxHORIZONTAL);
3434 auto* icon_add = new ScalableButton(p->m_btn_add_mixed_filament, wxID_ANY, "add_filament", wxEmptyString,
3435 wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, false, 16);
3436 auto* add_label = new wxStaticText(p->m_btn_add_mixed_filament, wxID_ANY, _L("Add Mixed Filament"),
3437 wxDefaultPosition, wxDefaultSize, 0);
3438 add_label->SetFont(::Label::Body_13);
3439 btn_sizer->AddStretchSpacer();
3440 btn_sizer->Add(icon_add, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(4));
3441 btn_sizer->Add(add_label, 0, wxALIGN_CENTER_VERTICAL);
3442 btn_sizer->AddStretchSpacer();
3443 p->m_btn_add_mixed_filament->SetSizer(btn_sizer);
3444 p->m_btn_add_mixed_filament->SetCursor(wxCursor(wxCURSOR_HAND));
3445 // Whole panel is the hit target, so forward clicks from the children too.
3446 auto on_click = [this](wxMouseEvent&) { add_mixed_filament(); };
3447 p->m_btn_add_mixed_filament->Bind(wxEVT_LEFT_UP, on_click);
3448 add_label->Bind(wxEVT_LEFT_UP, on_click);
3449 icon_add->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { add_mixed_filament(); });
3450 }
3451 wrapper_sizer->Add(p->m_btn_add_mixed_filament, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP | wxBOTTOM, FromDIP(8));
3452
3453 // 2) Title row with add / remove buttons, shown once a mixed filament exists.
3454 p->m_panel_mixed_title = new wxPanel(p->m_filament_area_wrapper, wxID_ANY);
3455 p->m_panel_mixed_title->SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
3456 {
3457 auto* title_sizer = new wxBoxSizer(wxHORIZONTAL);
3458 p->m_text_mixed_title = new StaticLine(p->m_panel_mixed_title, false, _L("Mixed Filament"));
3459 p->m_text_mixed_title->SetFont(::Label::Head_14);
3460 p->m_text_mixed_title->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#363636")));
3461 title_sizer->Add(p->m_text_mixed_title, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(SidebarProps::TitlebarMargin()));
3462
3463 p->m_btn_mixed_del = new ScalableButton(p->m_panel_mixed_title, wxID_ANY, "delete_filament");
3464 p->m_btn_mixed_del->SetToolTip(_L("Remove last mixed filament"));
3465 p->m_btn_mixed_del->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) {
3466 auto* plater_ptr = dynamic_cast<Plater*>(GetParent());
3467 if (!plater_ptr) return;
3468 auto mixed_indices = plater_ptr->mixed_filament_config_indices();
3469 if (!mixed_indices.empty())
3470 delete_mixed_filament_at(mixed_indices.size() - 1);
3471 });
3472 title_sizer->Add(p->m_btn_mixed_del, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(SidebarProps::IconSpacing()));
3473
3474 p->m_btn_mixed_del_all = new ScalableButton(p->m_panel_mixed_title, wxID_ANY, "delete_all_filaments");
3475 p->m_btn_mixed_del_all->SetToolTip(_L("Remove all mixed filaments"));
3476 p->m_btn_mixed_del_all->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { remove_all_mixed_filaments(); });
3477 title_sizer->Add(p->m_btn_mixed_del_all, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(SidebarProps::IconSpacing()));
3478
3479 p->m_btn_mixed_add = new ScalableButton(p->m_panel_mixed_title, wxID_ANY, "add_filament");
3480 p->m_btn_mixed_add->SetToolTip(_L("Add mixed filament"));
3481 p->m_btn_mixed_add->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { add_mixed_filament(); });
3482 title_sizer->Add(p->m_btn_mixed_add, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(SidebarProps::IconSpacing()));
3483 title_sizer->AddSpacer(FromDIP(SidebarProps::TitlebarMargin()));
3484
3485 p->m_panel_mixed_title->SetSizer(title_sizer);
3486 }
3487 wrapper_sizer->Add(p->m_panel_mixed_title, 0, wxEXPAND | wxTOP | wxBOTTOM, FromDIP(8));
3488
3489 // 3) Mixed filament rows, in their own scroll area so a long mixed list does not
3490 // push the physical filament list off screen.
3491 p->m_mixed_scroll_area = new wxScrolledWindow(p->m_filament_area_wrapper, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
3492 p->m_mixed_scroll_area->SetScrollRate(0, FromDIP(20));
3493 p->m_mixed_scroll_area->SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
3494 {
3495 auto* mix_scroll_sizer = new wxBoxSizer(wxVERTICAL);
3496 p->m_panel_mixed_content = new wxPanel(p->m_mixed_scroll_area, wxID_ANY);
3497 p->m_panel_mixed_content->SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
3498
3499 // Two columns, same idiom as sizer_filaments.
3500 p->m_sizer_mixed_filaments = new wxBoxSizer(wxHORIZONTAL);
3501 p->m_sizer_mixed_filaments->Add(new wxBoxSizer(wxVERTICAL), 1, wxEXPAND);
3502 p->m_sizer_mixed_filaments->Add(new wxBoxSizer(wxVERTICAL), 1, wxEXPAND);
3503
3504 auto* sizer_mixed2 = new wxBoxSizer(wxVERTICAL);
3505 sizer_mixed2->Add(p->m_sizer_mixed_filaments, 0, wxEXPAND, 0);
3506 p->m_panel_mixed_content->SetSizer(sizer_mixed2);
3507 mix_scroll_sizer->Add(p->m_panel_mixed_content, 0, wxEXPAND | wxBOTTOM, FromDIP(8));
3508 p->m_mixed_scroll_area->SetSizer(mix_scroll_sizer);
3509 }
3510 p->m_mixed_scroll_area->EnableScrolling(false, true);
3511 p->m_mixed_scroll_area->ShowScrollbars(wxSHOW_SB_NEVER, wxSHOW_SB_DEFAULT);
3512 p->m_mixed_scroll_area->Bind(wxEVT_SIZE, [this](wxSizeEvent& e) {
3513 int w = p->m_mixed_scroll_area->GetClientSize().GetWidth();
3514 if (w > 0)
3515 p->m_mixed_scroll_area->SetVirtualSize(w, p->m_mixed_scroll_area->GetVirtualSize().GetHeight());
3516 e.Skip();
3517 });
3518 wrapper_sizer->Add(p->m_mixed_scroll_area, 0, wxEXPAND, 0);
3519
3520 // 4) Warning bar for mixes whose components were deleted or whose types disagree.
3521 p->m_panel_mixed_warning = new wxPanel(p->m_filament_area_wrapper, wxID_ANY);
3522 p->m_panel_mixed_warning->SetBackgroundColour(StateColor::darkModeColorFor(*wxWHITE));
3523 {
3524 auto* warn_sizer = new wxBoxSizer(wxHORIZONTAL);
3525 p->m_text_mixed_warning = new wxStaticText(p->m_panel_mixed_warning, wxID_ANY,
3526 _L("Mixed filament has invalid or mismatched components. Please re-edit affected entries."));
3527 p->m_text_mixed_warning->SetForegroundColour(StateColor::darkModeColorFor(wxColour("#D01B1B")));
3528 p->m_text_mixed_warning->SetFont(::Label::Body_12);
3529 p->m_text_mixed_warning->Wrap(FromDIP(360));
3530 warn_sizer->Add(p->m_text_mixed_warning, 1, wxALL, FromDIP(6));
3531 p->m_panel_mixed_warning->SetSizer(warn_sizer);
3532 }
3533 wrapper_sizer->Add(p->m_panel_mixed_warning, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(8));
3534
3535 // Hidden until update_mixed_filament_list() decides otherwise.
3536 p->m_btn_add_mixed_filament->Hide();
3537 p->m_panel_mixed_title->Hide();
3538 p->m_mixed_scroll_area->Hide();
3539 p->m_panel_mixed_content->Hide();
3540 p->m_panel_mixed_warning->Hide();
3541 }
3542 // ---- End mixed-color filament section ----
3543
3544 p->m_filament_area_wrapper->SetSizer(wrapper_sizer);
3545 p->m_filament_area_wrapper->Layout();
3546 scrolled_sizer->Add(p->m_filament_area_wrapper, 0, wxEXPAND | wxTOP | wxBOTTOM, FromDIP(SidebarProps::ContentMarginV())); // ORCA use vertical margin on parent otherwise it shows scrollbar even on 1 filament
3547 // ---- End filament area ----
3548 }
3549
3550 {
3551 //add project title
3552 auto params_panel = ((MainFrame*)parent->GetParent())->m_param_panel;
3553 if (params_panel) {
3554 params_panel->get_top_panel()->Reparent(p->scrolled);
3555 auto spliter_1 = new ::StaticLine(p->scrolled);
3556 spliter_1->SetLineColour("#A6A9AA");
3557 scrolled_sizer->Add(spliter_1, 0, wxEXPAND);
3558 scrolled_sizer->Add(params_panel->get_top_panel(), 0, wxEXPAND);
3559 auto spliter_2 = new ::StaticLine(p->scrolled);
3560 spliter_2->SetLineColour("#CECECE");
3561 scrolled_sizer->Add(spliter_2, 0, wxEXPAND);
3562 }
3563
3564 //add project content
3565 p->sizer_params = new wxBoxSizer(wxVERTICAL);
3566
3567 // ORCA: Update search box to modern style
3568 p->m_search_bar = new StaticBox(p->scrolled);
3569 p->m_search_bar->SetCornerRadius(0);
3570 p->m_search_bar->SetBorderColor(wxColour("#CECECE"));
3571
3572 p->m_search_item = new TextInput(p->m_search_bar, wxEmptyString, wxEmptyString, "", wxDefaultPosition, wxDefaultSize, 0 | wxBORDER_NONE);
3573 p->m_search_item->SetIcon(*BitmapCache().load_svg("search", FromDIP(16), FromDIP(16))); // ORCA: Add search icon to search box
3574
3575 wxTextCtrl* text_ctrl = p->m_search_item->GetTextCtrl();
3576 text_ctrl->SetHint(_L("Search plate, object and part."));
3577 text_ctrl->SetForegroundColour(wxColour("#262E30"));
3578 text_ctrl->SetFont(Label::Body_13);
3579 text_ctrl->SetSize(wxSize(-1, FromDIP(16))); // Centers text vertically
3580
3581 text_ctrl->Bind(wxEVT_SET_FOCUS, [this](wxFocusEvent& e) {
3582 if (p->dia->IsShown()) {
3583 e.Skip();
3584 return;
3585 }
3586 p->m_search_bar->SetBorderColor(wxColour("#009688"));
3587 wxPoint pos = this->p->m_search_bar->ClientToScreen(wxPoint(0, 0));
3588#ifndef __WXGTK__
3589 pos.y += this->p->m_search_bar->GetRect().height;
3590#else
3591 this->p->m_search_item->Enable(false);
3592#endif
3593 p->dia->SetPosition(pos);
3594 p->dia->Popup();
3595 e.Skip(); // required to show caret
3596 });
3597
3598 auto search_sizer = new wxBoxSizer(wxHORIZONTAL);
3599 search_sizer->Add(new wxWindow(p->m_search_bar, wxID_ANY, wxDefaultPosition, wxSize(0, 0)), 0, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(1));
3600 search_sizer->Add(p->m_search_item, 1, wxEXPAND | wxALL, FromDIP(2));
3601 p->m_search_bar->SetSizer(search_sizer);
3602 p->m_search_bar->Layout();
3603 search_sizer->Fit(p->m_search_bar);
3604
3605 p->m_object_list = new ObjectList(p->scrolled);
3606 p->m_object_list->SetBackgroundColour(*wxWHITE);
3607 p->m_object_list->Bind(wxCUSTOMEVT_EXIT_SEARCH, [this](wxCommandEvent&) {
3608#ifdef __WXGTK__
3609 this->p->m_search_item->Enable(true);
3610#endif
3611 this->p->m_search_bar->SetBorderColor(wxColour("#CECECE"));
3612 this->p->m_search_item->GetTextCtrl()->SetValue(""); // reset value when close
3613 });
3614
3615 p->sizer_params->Add(p->m_search_bar, 0, wxALL | wxEXPAND, 0);
3616 p->sizer_params->Add(p->m_object_list, 1, wxEXPAND | wxTOP, 0);
3617 scrolled_sizer->Add(p->sizer_params, 2, wxEXPAND | wxLEFT, 0);
3618 p->m_object_list->Hide();
3619 p->m_search_bar->Hide();
3620 // Frequently Object Settings
3621 p->object_settings = new ObjectSettings(p->scrolled);
3622
3623 p->dia = new Search::SearchObjectDialog(p->m_object_list, p->scrolled->GetParent(), p->m_search_item);
3624#if !NEW_OBJECT_SETTING
3625 p->object_settings->Hide();
3626 p->sizer_params->Add(p->object_settings->get_sizer(), 0, wxEXPAND | wxTOP, 5 * em / 10);
3627#else
3628 if (params_panel) {
3629 params_panel->Reparent(p->scrolled);
3630 scrolled_sizer->Add(params_panel, 3, wxEXPAND);
3631 }
3632#endif
3633 }
3634
3635 p->object_layers = new ObjectLayers(p->scrolled);
3636 p->object_layers->Hide();
3637 p->sizer_params->Add(p->object_layers->get_sizer(), 0, wxEXPAND | wxTOP, 0);
3638
3639 auto *sizer = new wxBoxSizer(wxVERTICAL);
3640 sizer->Add(p->scrolled, 1, wxEXPAND);
3641 SetSizer(sizer);
3642}
@ Confirm
Definition Button.hpp:25
@ Compact
Definition Button.hpp:31
#define LB_PROPAGATE_MOUSE_EVENT
Definition Label.hpp:11
#define _L(s)
Definition OBJ.cpp:34
#define PRINTER_PANEL_SIZE
Definition Plater.cpp:362
#define PRINTER_PANEL_RADIUS
Definition Plater.cpp:363
#define PRINTER_THUMBNAIL_SIZE
Definition Plater.cpp:361
class WXDLLIMPEXP_FWD_CORE wxStaticText
Definition ProgressDialog.hpp:30
void open_flushing_dialog(wxEvtHandler *parent, const wxEvent &event)
Definition WipeTowerDialog.cpp:273
bool is_flush_config_modified()
Definition WipeTowerDialog.cpp:239
static wxFont Body_13
Definition Label.hpp:54
static wxFont Head_14
Definition Label.hpp:45
static wxFont Body_12
Definition Label.hpp:55
static wxFont Body_10
Definition Label.hpp:56
static void register_dynamic_list(std::string const &optname, DynamicList *list)
Definition Field.cpp:1534
@ SP_PRINTERS
Definition ConfigWizard.hpp:33
@ SP_FILAMENTS
Definition ConfigWizard.hpp:34
@ RR_USER
Definition ConfigWizard.hpp:27
static int ElementSpacing()
Definition Plater.hpp:153
static int WideSpacing()
Definition Plater.hpp:152
static int IconSpacing()
Definition Plater.hpp:151
static int ContentMarginV()
Definition Plater.hpp:150
static int TitlebarMargin()
Definition Plater.hpp:148
void update_filaments_area_height()
Definition Plater.cpp:5448
std::unique_ptr< priv > p
Definition Plater.hpp:330
void add_filament()
Definition Plater.cpp:5821
ScalableButton * ams_btn
Definition Plater.hpp:160
void deal_btn_sync()
Definition Plater.cpp:6720
void remove_all_mixed_filaments()
Definition Plater.cpp:5337
void on_enter_image_printer_bed(wxMouseEvent &evt)
Definition Plater.cpp:3646
void delete_mixed_filament_at(size_t idx)
Definition Plater.cpp:5359
void update_filaments_counter(bool force_layout=false)
Definition Plater.cpp:5467
void add_mixed_filament()
Definition Plater.cpp:5160
void init_filament_combo(PlaterPresetComboBox **combo, const int filament_idx)
Definition Plater.cpp:3699
void delete_filament(size_t filament_id=size_t(-1), int replace_filament_id=-1)
Definition Plater.cpp:5834
void update_sync_ams_btn_enable(wxUpdateUIEvent &e)
Definition Plater.cpp:2757
void set_flushing_volume_warning(const bool flushing_volume_modify)
Definition Plater.cpp:6687
void sync_ams_list(bool is_from_big_sync_btn=false)
Definition Plater.cpp:6304
void on_leave_image_printer_bed(wxMouseEvent &evt)
Definition Plater.cpp:3661
bool reset_bed_type_combox_choices(bool is_sidebar_init=false)
Definition Plater.cpp:4230
wxBoxSizer * m_scrolled_sizer
Definition Plater.hpp:332
std::string get_cur_select_bed_image()
Definition Plater.cpp:4212
@ TYPE_PRINTER
Definition Preset.hpp:250
static wxColour darkModeColorFor(wxColour const &color)
Definition StateColor.cpp:219
wxColour bg_color()
Definition SpeedDialDialog.cpp:69
wxMouseEvent
Definition CameraPopup.cpp:47
void manuallySetNozzleCount(int extruder_id)
Definition MultiNozzleSync.cpp:320
static DynamicFilamentList dynamic_filament_list
Definition Plater.cpp:1412
static DynamicFilamentList dynamic_physical_filament_list(true)
@ ObjectList
Definition Shortcuts.hpp:21
@ Plater
Definition Shortcuts.hpp:21
@ FastMode
Definition PurgeModeDialog.hpp:48
@ MultiNozzle
Definition PurgeModeDialog.hpp:47
Vec3d pos(const Pt &p)
Definition ReprojectPointsOnMesh.hpp:16
bool load_svg(const char *path, Model *model, std::string &message)
Definition svg.cpp:309
BedType
Definition PrintConfig.hpp:507
@ hovered
Definition GLGizmoEmboss.cpp:223
Definition Plater.cpp:869
int em_unit(wxWindow *win)
Definition wxExtensions.cpp:424
wxBitmap create_scaled_bitmap(const std::string &bmp_name_in, wxWindow *win, const int px_cnt, const bool grayscale, const std::string &new_color, const bool menu_bitmap, const bool resize, const bool bitmap2, const std::vector< std::string > &array_new_color)
Definition wxExtensions.cpp:448

References _L, add_filament(), add_mixed_filament(), ams_btn, ScalableBitmap::bmp(), Label::Body_10, Label::Body_12, Label::Body_13, Compact, Confirm, Slic3r::GUI::SidebarProps::ContentMarginV(), create_scaled_bitmap(), StateColor::darkModeColorFor(), deal_btn_sync(), delete_filament(), delete_mixed_filament_at(), Slic3r::GUI::dynamic_filament_list, Slic3r::GUI::dynamic_physical_filament_list, Slic3r::GUI::SidebarProps::ElementSpacing(), em_unit(), Slic3r::GUI::FastMode, Slic3r::AppConfig::get(), get_cur_select_bed_image(), Slic3r::GUI::PurgeModeDialog::get_selected_mode(), Label::Head_14, Slic3r::GUI::SidebarProps::IconSpacing(), init_filament_combo(), is_flush_config_modified(), LB_PROPAGATE_MOUSE_EVENT, Slic3r::load_svg(), m_scrolled_sizer, Slic3r::GUI::manuallySetNozzleCount(), Slic3r::GUI::Plater::mixed_filament_config_indices(), Slic3r::GUI::MultiNozzle, Slic3r::GUI::ObjectList, on_enter_image_printer_bed(), on_leave_image_printer_bed(), open_flushing_dialog(), p, PRINTER_PANEL_RADIUS, PRINTER_PANEL_SIZE, PRINTER_THUMBNAIL_SIZE, Slic3r::GUI::Choice::register_dynamic_list(), remove_all_mixed_filaments(), reset_bed_type_combox_choices(), Slic3r::GUI::ConfigWizard::RR_USER, Slic3r::AppConfig::set(), set_flushing_volume_warning(), Slic3r::GUI::DPIAware< P >::ShowModal(), Slic3r::GUI::ConfigWizard::SP_FILAMENTS, Slic3r::GUI::ConfigWizard::SP_PRINTERS, sync_ams_list(), Slic3r::GUI::SidebarProps::TitlebarMargin(), Slic3r::Preset::TYPE_PRINTER, update_filaments_area_height(), update_filaments_counter(), update_sync_ams_btn_enable(), Slic3r::ConfigOptionSingle< T >::value, Slic3r::GUI::SidebarProps::WideSpacing(), Slic3r::GUI::wxMouseEvent, and wxStaticText.

Referenced by Sidebar(), Sidebar(), operator=(), and operator=().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Sidebar() [2/3]

Slic3r::GUI::Sidebar::Sidebar ( Sidebar && )
delete

References Sidebar().

Here is the call graph for this function:

◆ Sidebar() [3/3]

Slic3r::GUI::Sidebar::Sidebar ( const Sidebar & )
delete

References Sidebar().

Here is the call graph for this function:

◆ ~Sidebar()

Slic3r::GUI::Sidebar::~Sidebar ( )
3644{}

Member Function Documentation

◆ add_custom_filament()

void Slic3r::GUI::Sidebar::add_custom_filament ( wxColour new_col,
const std::string & preset_name = std::string(),
bool skip_preset_validation = false )
5935 {
5936 if (is_new_project_in_gcode3mf()) { return; }
5937 if (p->combos_filament.size() >= MAXIMUM_EXTRUDER_NUMBER) return;
5938 if (wxGetApp().preset_bundle->filament_presets.size() >= MAXIMUM_EXTRUDER_NUMBER) return;
5939
5940 // Mixed-color slots are kept at the tail of the filament arrays, so a new physical
5941 // filament has to be inserted just after the last physical one rather than appended.
5942 // Count actual colour slots, not filament_presets or the combos: the extruder-count spinner
5943 // reaches this before the sidebar has rebuilt, and update_multi_material_filament_presets()
5944 // can have grown filament_presets alone.
5945 auto *bundle = wxGetApp().preset_bundle;
5946 size_t insert_pos = bundle->num_physical_filaments();
5947 size_t total = insert_pos + bundle->num_mixed_filaments();
5948 int filament_count = (int)(total + 1);
5949 std::string new_color = new_col.GetAsString(wxC2S_HTML_SYNTAX).ToStdString();
5950 bundle->set_num_filaments(filament_count, new_color);
5951
5952 // Maintain physical-first ordering: rotate the new slot from end to insert_pos.
5953 // No mixed slots -> insert_pos == total -> every rotate below is a no-op.
5954 if (insert_pos < total) {
5955 auto& presets = wxGetApp().preset_bundle->filament_presets;
5956 std::rotate(presets.begin() + insert_pos, presets.begin() + total, presets.end());
5957
5958 auto& project_config = wxGetApp().preset_bundle->project_config;
5959 auto& ams_mc = wxGetApp().preset_bundle->ams_multi_color_filment;
5960
5961 auto rotate_strings = [&](const char* key) {
5962 if (auto* opt = project_config.option<ConfigOptionStrings>(key))
5963 if (opt->values.size() > total)
5964 std::rotate(opt->values.begin() + insert_pos, opt->values.begin() + total, opt->values.end());
5965 };
5966 auto rotate_ints = [&](const char* key) {
5967 if (auto* opt = project_config.option<ConfigOptionInts>(key))
5968 if (opt->values.size() > total)
5969 std::rotate(opt->values.begin() + insert_pos, opt->values.begin() + total, opt->values.end());
5970 };
5971 auto rotate_bools = [&](const char* key) {
5972 if (auto* opt = project_config.option<ConfigOptionBools>(key))
5973 if (opt->values.size() > total)
5974 std::rotate(opt->values.begin() + insert_pos, opt->values.begin() + total, opt->values.end());
5975 };
5976
5977 rotate_strings("filament_colour");
5978 rotate_strings("filament_multi_colour");
5979 rotate_strings("filament_colour_type");
5980 rotate_ints("filament_map");
5981 rotate_ints("filament_nozzle_map");
5982 rotate_ints("filament_volume_map");
5983 rotate_bools("filament_is_mixed");
5984 rotate_strings("filament_mixed_components");
5985 rotate_strings("filament_mixed_sublayer_ratios");
5986 rotate_bools("filament_mixed_gradient");
5987 rotate_strings("filament_mixed_gradient_range");
5988 rotate_strings("filament_mixed_gradient_curve");
5989 rotate_bools("filament_mixed_gradient_per_part");
5990
5991 if (ams_mc.size() > total)
5992 std::rotate(ams_mc.begin() + insert_pos, ams_mc.begin() + total, ams_mc.end());
5993
5994 // Remap object/volume extruder IDs and paint data: anything >= insert_pos+1 (1-based) shifts up by 1
5995 int threshold_1based = (int)(insert_pos + 1);
5996 auto ebt_threshold = EnforcerBlockerType(threshold_1based);
5997 for (auto* obj : wxGetApp().plater()->model().objects) {
5998 if (obj->config.has("extruder")) {
5999 int ext = obj->config.extruder();
6000 if (ext >= threshold_1based)
6001 obj->config.set("extruder", ext + 1);
6002 }
6003 for (auto* vol : obj->volumes) {
6004 if (vol->config.has("extruder")) {
6005 int ext = vol->config.extruder();
6006 if (ext >= threshold_1based)
6007 vol->config.set("extruder", ext + 1);
6008 }
6009 vol->mmu_segmentation_facets.shift_states_above(*vol, ebt_threshold, +1);
6010 }
6011 }
6012 }
6013
6014 if (!preset_name.empty() &&
6015 wxGetApp().preset_bundle->filaments.find_preset(preset_name, false) &&
6016 insert_pos < wxGetApp().preset_bundle->filament_presets.size()) {
6017 wxGetApp().preset_bundle->filament_presets[insert_pos] = preset_name;
6018 }
6019
6020 wxGetApp().plater()->get_partplate_list().on_filament_added(filament_count);
6021 wxGetApp().plater()->on_filament_count_change(filament_count);
6022 wxGetApp().get_tab(Preset::TYPE_PRINT)->update();
6023 wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config);
6024 auto_calc_flushing_volumes(insert_pos);
6025}
void auto_calc_flushing_volumes(const int filament_idx=-1, const int extruder_id=-1)
Automatically calculates flushing volumes.
Definition Plater.cpp:6973
bool is_new_project_in_gcode3mf()
Definition Plater.cpp:6027
@ TYPE_PRINT
Definition Preset.hpp:246
static constexpr size_t MAXIMUM_EXTRUDER_NUMBER
Definition libslic3r.h:70
static Plater * plater()
Definition GUI_Factories.cpp:400
EnforcerBlockerType
Definition TriangleSelector.hpp:24
ConfigOptionIntsTempl< false > ConfigOptionInts
Definition Config.hpp:1154
ConfigOptionBoolsTempl< false > ConfigOptionBools
Definition Config.hpp:2066

References auto_calc_flushing_volumes(), is_new_project_in_gcode3mf(), MAXIMUM_EXTRUDER_NUMBER, p, Slic3r::GUI::plater(), and Slic3r::Preset::TYPE_PRINT.

Referenced by add_filament(), decompose_filament_color(), and Slic3r::GUI::Tab::on_value_change().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_filament()

void Slic3r::GUI::Sidebar::add_filament ( )
5821 {
5822 if (p->combos_filament.size() >= MAXIMUM_EXTRUDER_NUMBER) return;
5823 wxColour new_col = Plater::get_next_color_for_filament();
5824 add_custom_filament(new_col);
5825
5826 auto filament_list = p->m_panel_filament_content;
5827 if(!filament_list->IsShown()){
5828 filament_list->Show(); // ORCA show list if its folded
5829 m_scrolled_sizer->Layout();
5830 }
5831 filament_list->Scroll(-1, INT_MAX); // ORCA scroll to end of list on changes to inform user about filament count
5832}
static wxColour get_next_color_for_filament()
Definition Plater.cpp:8511
void add_custom_filament(wxColour new_col, const std::string &preset_name=std::string(), bool skip_preset_validation=false)
Definition Plater.cpp:5935

References add_custom_filament(), Slic3r::GUI::Plater::get_next_color_for_filament(), m_scrolled_sizer, MAXIMUM_EXTRUDER_NUMBER, and p.

Referenced by Sidebar().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_mixed_filament()

void Slic3r::GUI::Sidebar::add_mixed_filament ( )
5161{
5162 auto* plater = dynamic_cast<Plater*>(GetParent());
5163 if (!plater) return;
5164
5165 size_t num_physical = p->combos_filament.size();
5166 if (num_physical < 2) return;
5167 if (wxGetApp().preset_bundle->filament_presets.size() >= size_t(EnforcerBlockerType::ExtruderMax)) return;
5168
5169 std::vector<std::string> color_strs, names, types;
5170 collect_physical_filament_info(color_strs, names, types);
5171
5172 MixedFilamentDialog dlg(this, color_strs, names, types);
5173 if (dlg.ShowModal() == wxID_OK) {
5174 auto result = dlg.get_result();
5175 create_mixed_filament_from_result(this, result, color_strs);
5176 }
5177}
void collect_physical_filament_info(std::vector< std::string > &color_strs, std::vector< std::string > &names, std::vector< std::string > &types, std::vector< size_t > *config_indices=nullptr)
Definition Plater.cpp:4943
static bool create_mixed_filament_from_result(Sidebar *sidebar, const MixedFilamentResult &result, const std::vector< std::string > &color_strs)
Definition Plater.cpp:5033
@ ExtruderMax
Definition TriangleSelector.hpp:66

References collect_physical_filament_info(), Slic3r::GUI::create_mixed_filament_from_result(), Slic3r::ExtruderMax, Slic3r::GUI::MixedFilamentDialog::get_result(), p, Slic3r::GUI::plater(), and Slic3r::GUI::DPIAware< P >::ShowModal().

Referenced by Sidebar().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ auto_calc_flushing_volumes()

void Slic3r::GUI::Sidebar::auto_calc_flushing_volumes ( const int filament_idx = -1,
const int extruder_id = -1 )

Automatically calculates flushing volumes.

Parameters
filament_idxSpecifies the filament index to calculate. -1 indicates all filament indices.
extruder_idSpecifies the extruder id to calculate. -1 indicates all extruders indices.
6973 {
6974
6975 std::vector<int> filament_indices;
6976 std::vector<int> extruder_indices;
6977
6978 auto& preset_bundle = wxGetApp().preset_bundle;
6979 auto filament_ptr = preset_bundle->project_config.option<ConfigOptionStrings>("filament_colour");
6980 int filament_count = filament_ptr ? filament_ptr->size() : 0;
6981 int extruder_count = preset_bundle->get_printer_extruder_count();
6982
6983 if (filament_idx < 0) {
6984 filament_indices.resize(filament_count);
6985 std::iota(filament_indices.begin(), filament_indices.end(), 0);
6986 }
6987 else {
6988 filament_indices.emplace_back(filament_idx);
6989 }
6990
6991 if (extruder_id < 0) {
6992 extruder_indices.resize(extruder_count);
6993 std::iota(extruder_indices.begin(), extruder_indices.end(), 0);
6994 }
6995 else {
6996 extruder_indices.emplace_back(extruder_id);
6997 }
6998
6999 for (auto eidx : extruder_indices) {
7000 for (auto fidx : filament_indices) {
7002 }
7003 }
7004
7005 wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config);
7006 wxGetApp().plater()->update_project_dirty_from_presets();
7007 wxPostEvent(this, SimpleEvent(EVT_SCHEDULE_BACKGROUND_PROCESS, this));
7008 auto has_modify = is_flush_config_modified();
7009 set_flushing_volume_warning(has_modify);
7010 p->plater->update();
7011}
void auto_calc_flushing_volumes_internal(const int filament_id, const int extruder_id)
Definition Plater.cpp:7014

References auto_calc_flushing_volumes_internal(), is_flush_config_modified(), p, set_flushing_volume_warning(), and Slic3r::ConfigOptionVector< T >::size().

Referenced by add_custom_filament(), Slic3r::anonymous_namespace{PluginHostPresets.cpp}::bind_filament_target(), and sync_ams_list().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ auto_calc_flushing_volumes_internal()

void Slic3r::GUI::Sidebar::auto_calc_flushing_volumes_internal ( const int filament_id,
const int extruder_id )
private
7015{
7016 auto& preset_bundle = wxGetApp().preset_bundle;
7017 // A mixed-colour slot is virtual and is never flushed to or from: leave its row and column
7018 // alone (the flushing dialog hides them and only compares physical slots).
7019 if (modify_id >= 0 && preset_bundle->is_mixed_filament((size_t)modify_id))
7020 return;
7021 auto& project_config = preset_bundle->project_config;
7022 const auto& full_config = wxGetApp().preset_bundle->full_config();
7023 auto& ams_multi_color_filament = preset_bundle->ams_multi_color_filment;
7024 size_t extruder_nums = preset_bundle->get_printer_extruder_count();
7025 int nozzle_flush_dataset = full_config.option<ConfigOptionIntsNullable>("nozzle_flush_dataset")->values[extruder_id];
7026 std::vector<double> init_matrix = get_flush_volumes_matrix((project_config.option<ConfigOptionFloats>("flush_volumes_matrix"))->values, extruder_id, extruder_nums);
7027
7028 const std::vector<int>& min_flush_volumes = get_min_flush_volumes(full_config, extruder_id);
7029
7030 const auto* flush_multi_opt = project_config.option<ConfigOptionFloats>("flush_multiplier");
7031 float flush_multiplier = flush_multi_opt ? (float)flush_multi_opt->get_at(extruder_id) : 1.f;
7032 std::vector<double> matrix = init_matrix;
7033 int m_max_flush_volume = Slic3r::g_max_flush_volume;
7034 unsigned int m_number_of_extruders = (int)(sqrt(init_matrix.size()) + 0.001);
7035
7036 const std::vector<std::string> extruder_colours = wxGetApp().plater()->get_extruder_colors_from_plater_config();
7037 std::vector<std::vector<wxColour>> multi_colours;
7038
7039 // Support for multi-color filament
7040 for (int i = 0; i < extruder_colours.size(); ++i) {
7041 std::vector<wxColour> single_filament;
7042 if (i < ams_multi_color_filament.size()) {
7043 if (!ams_multi_color_filament[i].empty()) {
7044 std::vector<std::string> colors = ams_multi_color_filament[i];
7045 for (int j = 0; j < colors.size(); ++j) {
7046 single_filament.push_back(wxColour(colors[j]));
7047 }
7048 multi_colours.push_back(single_filament);
7049 continue;
7050 }
7051 }
7052
7053 single_filament.push_back(wxColour(extruder_colours[i]));
7054 multi_colours.push_back(single_filament);
7055 }
7056
7057 if (modify_id >= 0 && modify_id < multi_colours.size()) {
7058 for (int i = 0; i < multi_colours.size(); ++i) {
7059 if (preset_bundle->is_mixed_filament((size_t)i))
7060 continue;
7061 // from to modify
7062 int from_idx = i;
7063 if (from_idx != modify_id) {
7064 Slic3r::FlushVolCalculator calculator(min_flush_volumes[from_idx], m_max_flush_volume, nozzle_flush_dataset);
7065 int flushing_volume = 0;
7066 bool is_from_support = is_support_filament(from_idx);
7067 bool is_to_support = is_support_filament(modify_id);
7068 if (is_to_support) {
7069 flushing_volume = Slic3r::g_flush_volume_to_support;
7070 }
7071 else {
7072 for (int j = 0; j < multi_colours[from_idx].size(); ++j) {
7073 const wxColour& from = multi_colours[from_idx][j];
7074 for (int k = 0; k < multi_colours[modify_id].size(); ++k) {
7075 const wxColour& to = multi_colours[modify_id][k];
7076 int volume = calculator.calc_flush_vol(from.Alpha(), from.Red(), from.Green(), from.Blue(), to.Alpha(), to.Red(), to.Green(), to.Blue());
7077 flushing_volume = std::max(flushing_volume, volume);
7078 }
7079 }
7080 if (is_from_support)
7081 flushing_volume = std::max(flushing_volume, Slic3r::g_min_flush_volume_from_support);
7082 }
7083 matrix[m_number_of_extruders * from_idx + modify_id] = flushing_volume;
7084 }
7085
7086 // modify to to
7087 int to_idx = i;
7088 if (to_idx != modify_id) {
7089 Slic3r::FlushVolCalculator calculator(min_flush_volumes[modify_id], m_max_flush_volume, nozzle_flush_dataset);
7090 bool is_from_support = is_support_filament(modify_id);
7091 bool is_to_support = is_support_filament(to_idx);
7092 int flushing_volume = 0;
7093 if (is_to_support) {
7094 flushing_volume = Slic3r::g_flush_volume_to_support;
7095 }
7096 else {
7097 for (int j = 0; j < multi_colours[modify_id].size(); ++j) {
7098 const wxColour& from = multi_colours[modify_id][j];
7099 for (int k = 0; k < multi_colours[to_idx].size(); ++k) {
7100 const wxColour& to = multi_colours[to_idx][k];
7101 int volume = calculator.calc_flush_vol(from.Alpha(), from.Red(), from.Green(), from.Blue(), to.Alpha(), to.Red(), to.Green(), to.Blue());
7102 flushing_volume = std::max(flushing_volume, volume);
7103 }
7104 }
7105 if (is_from_support)
7106 flushing_volume = std::max(flushing_volume, Slic3r::g_min_flush_volume_from_support);
7107
7108 matrix[m_number_of_extruders * modify_id + to_idx] = flushing_volume;
7109 }
7110 }
7111 }
7112 }
7113 set_flush_volumes_matrix((project_config.option<ConfigOptionFloats>("flush_volumes_matrix"))->values, matrix, extruder_id, extruder_nums);
7114}
const double & get_at(size_t i) const
Definition Config.hpp:676
bool is_support_filament(int extruder_id, bool strict_check)
Definition GUI_App.cpp:10492
std::vector< int > get_min_flush_volumes(const DynamicPrintConfig &full_config, size_t nozzle_id)
Definition Plater.cpp:1246
const int g_max_flush_volume
Definition FlushVolCalc.cpp:15
ConfigOptionIntsTempl< true > ConfigOptionIntsNullable
Definition Config.hpp:1155
static void set_flush_volumes_matrix(std::vector< T > &out_matrix, const std::vector< T > &fv_matrix, size_t extruder_id=-1, size_t nozzle_nums=1)
Definition PrintConfig.hpp:2698
const int g_min_flush_volume_from_support
Definition FlushVolCalc.cpp:12
static std::vector< T > get_flush_volumes_matrix(const std::vector< T > &fv_matrix, size_t extruder_id=-1, size_t nozzle_nums=1)
Definition PrintConfig.hpp:2685
const int g_flush_volume_to_support
Definition FlushVolCalc.cpp:13
zaa_minimize_perimeter_height flush_multiplier((ConfigOptionEnum< PrimeVolumeMode >, prime_volume_mode))((ConfigOptionFloats
bool empty(const BoundingBoxBase< PointType, PointsType > &bb)
Definition BoundingBox.hpp:273
ConfigOptionFloatsTempl< false > ConfigOptionFloats
Definition Config.hpp:1015

References Slic3r::FlushVolCalculator::calc_flush_vol(), Slic3r::empty(), Slic3r::flush_multiplier(), Slic3r::g_flush_volume_to_support, Slic3r::g_max_flush_volume, Slic3r::g_min_flush_volume_from_support, Slic3r::get_flush_volumes_matrix(), Slic3r::GUI::get_min_flush_volumes(), Slic3r::GUI::is_support_filament(), and Slic3r::set_flush_volumes_matrix().

Referenced by auto_calc_flushing_volumes().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ build_filament_ams_list()

std::map< int, DynamicPrintConfig > Slic3r::GUI::Sidebar::build_filament_ams_list ( MachineObject * obj)

Build a map of filament configurations from the connected printer's AMS (Automatic Material System).

Data Flow Architecture:

This function reads pre-populated state from MachineObject - it does NOT directly call NetworkAgent APIs. The data pipeline is:

Printer Device (MQTT/LAN messages) ↓ NetworkAgent (receives JSON, triggers OnMessageFn callbacks) ↓ MachineObject::parse_json() (updates device state) ├── vt_slot (std::vector<DevAmsTray>) - virtual tray data for external filament └── DevFilaSystem → DevAms → DevAmsTray - AMS unit hierarchy ↓ build_filament_ams_list() [THIS FUNCTION] - aggregates into DynamicPrintConfig maps

Data Sources:

  • obj->vt_slot: Virtual trays for external/manual filament loading (when ams_support_virtual_tray is true)
  • obj->GetFilaSystem()->GetAmsList(): Map of AMS units, each containing multiple DevAmsTray slots

Return Value:

  • Map key encoding:
    • Virtual trays: 0x10000 + vt_tray.id (first/main extruder), or just vt_tray.id (secondary)
    • AMS trays: 0x10000 + (ams_id * 4 + slot_id) (main extruder), or (ams_id * 4 + slot_id) (secondary)
    • The 0x10000 flag indicates the main/right extruder
  • Map value: DynamicPrintConfig with filament properties (id, type, color, etc.)
Parameters
objThe MachineObject representing the connected printer (nullable)
Returns
Map of tray indices to filament configurations
6093{
6094 std::map<int, DynamicPrintConfig> filament_ams_list;
6095 if (!obj) return filament_ams_list;
6096
6097 // For pull-mode agents (e.g., HTTP REST API), refresh DevFilaSystem first
6098 auto* agent = wxGetApp().getDeviceManager()->get_agent();
6099 if (agent && agent->get_filament_sync_mode() == FilamentSyncMode::pull) {
6100 if (!agent->fetch_filament_info(obj->get_dev_id())) {
6101 return filament_ams_list;
6102 }
6103 }
6104
6105 auto build_tray_config = [](DevAmsTray const &tray, std::string const &name, std::string ams_id, std::string slot_id) {
6106 BOOST_LOG_TRIVIAL(info) << boost::format("build_filament_ams_list: name %1% setting_id %2% type %3% color %4%")
6107 % name % tray.setting_id % tray.m_fila_type % tray.color;
6108 DynamicPrintConfig tray_config;
6109 tray_config.set_key_value("filament_id", new ConfigOptionStrings{tray.setting_id});
6110 tray_config.set_key_value("tag_uid", new ConfigOptionStrings{tray.tag_uid});
6111 tray_config.set_key_value("ams_id", new ConfigOptionStrings{ams_id});
6112 tray_config.set_key_value("slot_id", new ConfigOptionStrings{slot_id});
6113 tray_config.set_key_value("filament_type", new ConfigOptionStrings{tray.m_fila_type});
6114 tray_config.set_key_value("tray_name", new ConfigOptionStrings{ name });
6115 tray_config.set_key_value("filament_colour", new ConfigOptionStrings{into_u8(wxColour("#" + tray.color).GetAsString(wxC2S_HTML_SYNTAX))});
6116 tray_config.set_key_value("filament_multi_colour", new ConfigOptionStrings{});
6117 tray_config.set_key_value("filament_colour_type", new ConfigOptionStrings{std::to_string(tray.ctype)});
6118 tray_config.set_key_value("filament_exist", new ConfigOptionBools{tray.is_exists});
6119 tray_config.set_key_value("filament_slot_placeholder", new ConfigOptionBools{tray.is_slot_placeholder});
6120 std::optional<FilamentBaseInfo> info;
6121 if (wxGetApp().preset_bundle) {
6122 info = wxGetApp().preset_bundle->get_filament_by_filament_id(tray.setting_id);
6123 }
6124 tray_config.set_key_value("filament_is_support", new ConfigOptionBools{ info.has_value() ? info->is_support : false});
6125 for (int i = 0; i < tray.cols.size(); ++i) {
6126 tray_config.opt<ConfigOptionStrings>("filament_multi_colour")->values.push_back(into_u8(wxColour("#" + tray.cols[i]).GetAsString(wxC2S_HTML_SYNTAX)));
6127 }
6128 return tray_config;
6129 };
6130
6131 if (obj->ams_support_virtual_tray) {
6132 int extruder = 0x10000; // Main (first) extruder at right
6133 for (auto & vt_tray : obj->vt_slot) {
6134 filament_ams_list.emplace(extruder + stoi(vt_tray.id), build_tray_config(vt_tray, "Ext",vt_tray.id, "0"));//254 or 255
6135 extruder = 0;
6136 }
6137 }
6138
6139 auto get_ams_name = [](int ams_id, int slot_id)->std::string {
6140 if (ams_id >= 0 && ams_id < 26) {
6141 char slot_name = slot_id + '1';
6142 return std::string(1, 'A' + ams_id) + std::string(1, slot_name);
6143 } else if (ams_id >= 128 && ams_id < 153) {
6144 return "HT-" + std::string(1, 'A' + (ams_id - 128));
6145 } else {
6146 assert(false);
6147 }
6148 return std::string();
6149 };
6150
6151 auto list = obj->GetFilaSystem()->GetAmsList();
6152 for (auto ams : list) {
6153 int ams_id = std::stoi(ams.first);
6154 int extruder = ams.second->GetExtruderId() ? 0 : 0x10000; // Main (first) extruder at right
6155 for (auto tray : ams.second->GetTrays()) {
6156 int slot_id = std::stoi(tray.first);
6157 filament_ams_list.emplace(extruder + (ams_id * 4 + slot_id),
6158 build_tray_config(*tray.second, get_ams_name(ams_id, slot_id), std::to_string(ams_id), std::to_string(slot_id)));
6159 }
6160 }
6161 return filament_ams_list;
6162}
std::string into_u8(const wxString &str)
Definition GUI.cpp:549
@ pull
On-demand fetch via REST API (blocking call).
Definition IPrinterAgent.hpp:59

References Slic3r::MachineObject::ams_support_virtual_tray, Slic3r::DevAmsTray::color, Slic3r::DevAmsTray::cols, Slic3r::DevAmsTray::ctype, Slic3r::MachineObject::get_dev_id(), Slic3r::MachineObject::GetFilaSystem(), Slic3r::GUI::into_u8(), Slic3r::DevAmsTray::is_exists, Slic3r::DevAmsTray::is_slot_placeholder, Slic3r::DevAmsTray::m_fila_type, Slic3r::DynamicConfig::opt(), Slic3r::pull, Slic3r::DynamicConfig::set_key_value(), Slic3r::DevAmsTray::setting_id, Slic3r::DevAmsTray::tag_uid, and Slic3r::MachineObject::vt_slot.

Referenced by load_ams_list().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ can_search()

void Slic3r::GUI::Sidebar::can_search ( )
7122{
7123 p->can_search();
7124}

References p.

◆ change_filament()

void Slic3r::GUI::Sidebar::change_filament ( size_t from_id,
size_t to_id )
5893{
5894 // Merging a physical filament into a mixed one that lists it as a component would delete
5895 // the very filament the mix depends on, leaving it broken. Warn before doing so.
5896 auto& pb = *wxGetApp().preset_bundle;
5897 bool from_is_physical = !pb.is_mixed_filament(from_id);
5898 bool to_is_mixed = pb.is_mixed_filament(to_id);
5899
5900 if (from_is_physical && to_is_mixed) {
5901 auto* comp_opt = pb.project_config.option<ConfigOptionStrings>("filament_mixed_components");
5902 if (comp_opt && to_id < comp_opt->values.size()) {
5903 auto comps = Slic3r::parse_mixed_components(comp_opt->values[to_id]);
5904 unsigned int from_1based = (unsigned int)from_id + 1;
5905 bool target_uses_source = false;
5906 for (unsigned int c : comps) {
5907 if (c == from_1based) {
5908 target_uses_source = true;
5909 break;
5910 }
5911 }
5912 if (target_uses_source) {
5913 int ret = wxMessageBox(
5914 _L("The target mixed filament uses this physical filament as a component. "
5915 "Merging will remove this physical filament and may invalidate the mixed filament. Continue?"),
5916 _L("Warning"),
5917 wxOK | wxCANCEL | wxICON_WARNING);
5918 if (ret != wxOK)
5919 return;
5920 }
5921 }
5922 }
5923
5924 delete_filament(from_id, int(to_id));
5925}
std::vector< unsigned int > parse_mixed_components(const std::string &str)
Definition FilamentMixer.cpp:172

References _L, delete_filament(), and Slic3r::parse_mixed_components().

Referenced by sync_ams_list(), and update_mixed_filament_list().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ change_top_border_for_mode_sizer()

void Slic3r::GUI::Sidebar::change_top_border_for_mode_sizer ( bool increase_border)
4280{
4281 // BBS
4282#if 0
4283 if (p->mode_sizer) {
4284 p->mode_sizer->set_items_flag(increase_border ? wxTOP : 0);
4285 p->mode_sizer->set_items_border(increase_border ? int(0.5 * wxGetApp().em_unit()) : 0);
4286 }
4287#endif
4288}

References em_unit(), and p.

Here is the call graph for this function:

◆ clear_combos_filament_badge()

void Slic3r::GUI::Sidebar::clear_combos_filament_badge ( )
6897{
6898 auto &combos_filament = p->combos_filament;
6899 for (auto &c : combos_filament) { // clear flag
6900 c->set_sync_badge(false);
6901 }
6902}
std::vector< PlaterPresetComboBox * > & combos_filament()
Definition Plater.cpp:6891

References combos_filament(), and p.

Referenced by sync_ams_list().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ collapse()

void Slic3r::GUI::Sidebar::collapse ( bool collapse)
6854{ p->plater->collapse_sidebar(collapse); }
void collapse(bool collapse)
Definition Plater.cpp:6854

References collapse(), and p.

Referenced by collapse(), and get_eject_shown().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ collect_physical_filament_info()

void Slic3r::GUI::Sidebar::collect_physical_filament_info ( std::vector< std::string > & color_strs,
std::vector< std::string > & names,
std::vector< std::string > & types,
std::vector< size_t > * config_indices = nullptr )
4947{
4948 color_strs.clear();
4949 names.clear();
4950 types.clear();
4951 if (config_indices)
4952 config_indices->clear();
4953
4954 size_t num_physical = p->combos_filament.size();
4955 auto& project_config = wxGetApp().preset_bundle->project_config;
4956 auto* is_mixed_opt = project_config.option<ConfigOptionBools>("filament_is_mixed");
4957 std::vector<size_t> physical_indices;
4958 const size_t total = wxGetApp().preset_bundle->filament_presets.size();
4959 physical_indices.reserve(num_physical);
4960 for (size_t i = 0; i < total && physical_indices.size() < num_physical; ++i) {
4961 if (!is_mixed_opt || i >= is_mixed_opt->values.size() || !is_mixed_opt->values[i])
4962 physical_indices.push_back(i);
4963 }
4964 while (physical_indices.size() < num_physical)
4965 physical_indices.push_back(physical_indices.size());
4966 if (config_indices)
4967 *config_indices = physical_indices;
4968
4969 auto* colours_opt = project_config.option<ConfigOptionStrings>("filament_colour");
4970 if (colours_opt) {
4971 for (size_t i = 0; i < num_physical; ++i) {
4972 const size_t cfg_idx = physical_indices[i];
4973 if (cfg_idx < colours_opt->values.size())
4974 color_strs.push_back(colours_opt->values[cfg_idx]);
4975 }
4976 }
4977
4978 for (size_t i = 0; i < num_physical; ++i) {
4979 auto* combo = p->combos_filament[i];
4980 names.push_back(into_u8(combo ? combo->GetValue() : wxString::Format(_L("Filament %d"), int(i + 1))));
4981 }
4982
4983 auto& preset_bundle = *wxGetApp().preset_bundle;
4984 for (size_t i = 0; i < num_physical; ++i) {
4985 const size_t cfg_idx = physical_indices[i];
4986 Preset* preset = nullptr;
4987 if (cfg_idx < preset_bundle.filament_presets.size())
4988 preset = preset_bundle.filaments.find_preset(preset_bundle.filament_presets[cfg_idx]);
4989 std::string ft;
4990 if (preset) {
4991 std::string display_type;
4992 ft = preset->config.get_filament_type(display_type);
4993 }
4994 if (ft.empty()) ft = "PLA";
4995 types.push_back(ft);
4996 }
4997}
size_t size() const override
Definition Config.hpp:722
@ Preset
Definition calib.hpp:39

References _L, Slic3r::Preset::config, Slic3r::DynamicPrintConfig::get_filament_type(), Slic3r::GUI::into_u8(), and p.

Referenced by add_mixed_filament(), decompose_filament_color(), edit_mixed_filament(), and ensure_mixed_filament().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ combos_filament()

std::vector< PlaterPresetComboBox * > & Slic3r::GUI::Sidebar::combos_filament ( )
6892{
6893 return p->combos_filament;
6894}

References p.

Referenced by Slic3r::anonymous_namespace{PluginHostPresets.cpp}::bind_filament_target(), clear_combos_filament_badge(), Slic3r::GUI::create_mixed_filament_from_result(), on_filament_count_change(), on_filaments_delete(), sync_ams_list(), and udpate_combos_filament_badge().

Here is the caller graph for this function:

◆ create_printer_preset()

void Slic3r::GUI::Sidebar::create_printer_preset ( )
3682{
3683 CreatePrinterPresetDialog dlg(wxGetApp().mainframe);
3684 int res = dlg.ShowModal();
3685 if (wxID_OK == res) {
3686 wxGetApp().load_current_presets();
3687 wxGetApp().mainframe->update_side_preset_ui();
3690 CreatePresetSuccessfulDialog success_dlg(wxGetApp().mainframe, SuccessType::PRINTER);
3691 int res = success_dlg.ShowModal();
3692 if (res == wxID_OK) {
3693 p->editing_filament = -1;
3694 if (p->combo_printer->switch_to_tab()) p->editing_filament = 0;
3695 }
3696 }
3697}
void update_ui_from_settings()
Definition Plater.cpp:6863
void update_all_preset_comboboxes()
Definition Plater.cpp:3795
@ PRINTER
Definition CreatePresetsDialog.hpp:228

References p, Slic3r::GUI::PRINTER, Slic3r::GUI::DPIAware< P >::ShowModal(), update_all_preset_comboboxes(), and update_ui_from_settings().

Here is the call graph for this function:

◆ deal_btn_sync()

void Slic3r::GUI::Sidebar::deal_btn_sync ( )
6720 {
6722 bool only_external_material;
6723 // Manual "sync machine" button: is_manual=true so an H2C pops the MultiNozzleSyncDialog to pick a nozzle option.
6724 auto ok = p->sync_extruder_list(only_external_material, true);
6725 if (ok) {
6727 }
6729 wxGetApp().plater()->update_machine_sync_status();
6730}
void pop_sync_nozzle_and_ams_dialog()
Definition Plater.cpp:6762
bool m_begin_sync_printer_status
Definition Plater.hpp:167

References m_begin_sync_printer_status, p, and pop_sync_nozzle_and_ams_dialog().

Referenced by Sidebar().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ decompose_filament_color()

void Slic3r::GUI::Sidebar::decompose_filament_color ( int filament_idx)
5372{
5373 if (filament_idx == kSidebarContextMenuFilamentId)
5374 filament_idx = p->m_menu_filament_id;
5375 if (filament_idx < 0)
5376 return;
5377
5378 auto& project_config = wxGetApp().preset_bundle->project_config;
5379 auto* colours_opt = project_config.option<ConfigOptionStrings>("filament_colour");
5380 if (!colours_opt || static_cast<size_t>(filament_idx) >= colours_opt->values.size())
5381 return;
5382
5383 wxColour target_color(colours_opt->values[filament_idx]);
5384
5385 std::vector<std::string> color_strs, names, types;
5386 std::vector<size_t> physical_config_indices;
5387 collect_physical_filament_info(color_strs, names, types, &physical_config_indices);
5388
5389 // Build decompose-specific types: ColorDecomposeDialog needs "PLA Basic"
5390 // distinction (for CMYW/RYBW card visibility), while collect_physical_filament_info
5391 // now returns coarse filament_type (e.g. "PLA" for all PLA variants).
5392 std::vector<std::string> decompose_types;
5393 {
5394 auto& pb = *wxGetApp().preset_bundle;
5395 for (size_t i = 0; i < physical_config_indices.size(); ++i) {
5396 const size_t ci = physical_config_indices[i];
5397 Preset* pr = (ci < pb.filament_presets.size())
5398 ? pb.filaments.find_preset(pb.filament_presets[ci]) : nullptr;
5399 decompose_types.push_back(filament_type_for_color_decompose(pr));
5400 }
5401 }
5402
5403 size_t source_physical_idx = size_t(-1);
5404 for (size_t i = 0; i < physical_config_indices.size(); ++i) {
5405 if (physical_config_indices[i] == static_cast<size_t>(filament_idx)) {
5406 source_physical_idx = i;
5407 break;
5408 }
5409 }
5410
5411 ColorDecomposeDialog dlg(this,
5412 source_physical_idx == size_t(-1) ? -1 : static_cast<int>(source_physical_idx),
5413 target_color, color_strs, names, decompose_types,
5414 wxGetApp().preset_bundle->filament_presets.size(),
5415 static_cast<size_t>(EnforcerBlockerType::ExtruderMax),
5416 physical_config_indices);
5417 int modal_res = dlg.ShowModal();
5418 if (modal_res == wxID_OK) {
5419 ColorDecomposeResult dialog_result = dlg.get_result();
5420 MixedFilamentResult mixed_result;
5421 std::vector<DecomposeMissingComponent> missing_components;
5422 if (!prepare_decompose_mixed_result(dialog_result, static_cast<size_t>(filament_idx), source_physical_idx,
5423 color_strs, decompose_types, physical_config_indices, mixed_result, missing_components))
5424 return;
5425
5426 if (!confirm_create_decompose_missing_components(this, missing_components))
5427 return;
5428
5429 for (const DecomposeMissingComponent& missing : missing_components) {
5430 size_t before_count = p->combos_filament.size();
5431 add_custom_filament(wxColour(missing.official_component.color_hex), missing.preset_name, true);
5432 size_t after_count = p->combos_filament.size();
5433 if (after_count <= before_count)
5434 return;
5435 set_created_standard_component_metadata(before_count, missing.official_component);
5436 if (missing.component_idx < mixed_result.components.size())
5437 mixed_result.components[missing.component_idx] = static_cast<unsigned int>(before_count + 1);
5438 }
5439
5440 if (!missing_components.empty()) {
5441 collect_physical_filament_info(color_strs, names, types, &physical_config_indices);
5442 }
5443
5444 create_mixed_filament_from_result(this, mixed_result, color_strs);
5445 }
5446}
void set_created_standard_component_metadata(size_t config_idx, const DecomposeOfficialComponent &component)
Definition ColorDecomposeSupport.cpp:115
std::string filament_type_for_color_decompose(Preset *preset)
Definition ColorDecomposeSupport.cpp:221
bool confirm_create_decompose_missing_components(wxWindow *parent, const std::vector< DecomposeMissingComponent > &missing)
Definition ColorDecomposeSupport.cpp:395
constexpr int kSidebarContextMenuFilamentId
Definition Plater.hpp:117
bool prepare_decompose_mixed_result(const ColorDecomposeResult &result, size_t source_config_idx, size_t source_physical_idx, const std::vector< std::string > &physical_colors, const std::vector< std::string > &physical_types, const std::vector< size_t > &physical_config_indices, MixedFilamentResult &out_result, std::vector< DecomposeMissingComponent > &missing)
Definition ColorDecomposeSupport.cpp:289

References add_custom_filament(), collect_physical_filament_info(), Slic3r::GUI::MixedFilamentResult::components, Slic3r::GUI::confirm_create_decompose_missing_components(), Slic3r::GUI::create_mixed_filament_from_result(), Slic3r::ExtruderMax, Slic3r::GUI::filament_type_for_color_decompose(), Slic3r::GUI::ColorDecomposeDialog::get_result(), Slic3r::GUI::kSidebarContextMenuFilamentId, p, Slic3r::GUI::prepare_decompose_mixed_result(), Slic3r::GUI::set_created_standard_component_metadata(), and Slic3r::GUI::DPIAware< P >::ShowModal().

Here is the call graph for this function:

◆ delete_filament()

void Slic3r::GUI::Sidebar::delete_filament ( size_t filament_id = size_t(-1),
int replace_filament_id = -1 )
5834 {
5835 if (is_new_project_in_gcode3mf()) { return; }
5836 if (p->combos_filament.size() <= 1) return;
5837
5838 size_t filament_count = p->combos_filament.size() - 1;
5839 if (filament_id == size_t(-2)) {
5840 filament_id = p->m_menu_filament_id;
5841 }
5842 if (filament_id == size_t(-1)) {
5843 filament_id = filament_count;
5844 }
5845
5846 // Mixed (virtual) slots have no combo of their own, so their config index lies past
5847 // filament_count; bound explicit ids by the total slot count instead.
5848 size_t total_filaments = wxGetApp().preset_bundle->filament_presets.size();
5849 if (filament_id > filament_count && filament_id >= total_filaments)
5850 return;
5851
5852 bool is_mixed = (filament_id >= p->combos_filament.size());
5853
5854 if (!is_mixed) {
5855 if (wxGetApp().preset_bundle->is_the_only_edited_filament(filament_id) || (filament_id == 0)) {
5856 wxGetApp().get_tab(Preset::TYPE_FILAMENT)->select_preset(wxGetApp().preset_bundle->filament_presets[0], false, "", true);
5857 }
5858
5859 if (p->editing_filament == filament_id || p->editing_filament >= filament_count) {
5860 p->editing_filament = -1;
5861 }
5862 }
5863
5864 // update_num_filaments() shrinks filament_is_mixed along with the other per-filament arrays,
5865 // so snapshot it first — the paint cleanup below needs to know which slots were mixed
5866 // *before* the delete to avoid discarding assignments to still-valid mixed slots.
5867 std::vector<unsigned char> is_mixed_snapshot;
5868 if (auto* opt = wxGetApp().preset_bundle->project_config.option<ConfigOptionBools>("filament_is_mixed"))
5869 is_mixed_snapshot = opt->values;
5870
5871 wxGetApp().preset_bundle->update_num_filaments(filament_id);
5872
5873 // filament_count only counts physical combos, so with mixed slots present it is not the
5874 // new number of slots; recompute from the shrunk preset list for the downstream updates.
5875 size_t total_after_delete = wxGetApp().preset_bundle->filament_presets.size();
5876 wxGetApp().plater()->get_partplate_list().on_filament_deleted(total_after_delete, filament_id);
5877 wxGetApp().plater()->on_filaments_delete(total_after_delete, filament_id, replace_filament_id > (int)filament_id ? (replace_filament_id - 1) : replace_filament_id, is_mixed_snapshot);
5878 wxGetApp().get_tab(Preset::TYPE_PRINT)->update();
5879 wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config);
5880
5881 wxGetApp().plater()->update();
5882
5883 auto filament_list = p->m_panel_filament_content;
5884 if(!filament_list->IsShown()){
5885 filament_list->Show(); // ORCA show list if its folded
5886 m_scrolled_sizer->Layout();
5887 }
5888
5889 filament_list->Scroll(-1, INT_MAX); // ORCA scroll to end of list on changes to inform user about filament count
5890}
@ TYPE_FILAMENT
Definition Preset.hpp:248

References is_new_project_in_gcode3mf(), m_scrolled_sizer, p, Slic3r::Preset::TYPE_FILAMENT, and Slic3r::Preset::TYPE_PRINT.

Referenced by Sidebar(), change_filament(), delete_mixed_filament_at(), and Slic3r::GUI::Tab::on_value_change().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ delete_mixed_filament_at()

void Slic3r::GUI::Sidebar::delete_mixed_filament_at ( size_t idx)
5360{
5361 auto* plater = dynamic_cast<Plater*>(GetParent());
5362 if (!plater) return;
5363
5364 auto mixed_indices = plater->mixed_filament_config_indices();
5365 if (panel_idx >= mixed_indices.size()) return;
5366 size_t cfg_idx = mixed_indices[panel_idx];
5367
5368 delete_filament(cfg_idx, -1);
5369}
std::vector< size_t > mixed_filament_config_indices() const
Definition Plater.cpp:15704

References delete_filament(), and Slic3r::GUI::plater().

Referenced by Sidebar(), remove_all_mixed_filaments(), and update_mixed_filament_list().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ edit_filament()

void Slic3r::GUI::Sidebar::edit_filament ( )
5928{
5929 p->editing_filament = -1;
5930 if (p->m_menu_filament_id >= 0 && p->m_menu_filament_id < p->combos_filament.size()
5931 && p->combos_filament[p->m_menu_filament_id]->switch_to_tab())
5932 p->editing_filament = p->m_menu_filament_id; // sync with TabPresetComboxBox's m_filament_idx
5933}

References p.

◆ edit_mixed_filament()

void Slic3r::GUI::Sidebar::edit_mixed_filament ( size_t idx)
5180{
5181 auto* plater = dynamic_cast<Plater*>(GetParent());
5182 if (!plater) return;
5183
5184 auto mixed_indices = plater->mixed_filament_config_indices();
5185 if (panel_idx >= mixed_indices.size()) return;
5186 size_t cfg_idx = mixed_indices[panel_idx];
5187
5188 std::vector<std::string> color_strs, names, types;
5189 collect_physical_filament_info(color_strs, names, types);
5190
5191 auto& project_config = wxGetApp().preset_bundle->project_config;
5192 MixedFilamentResult existing;
5193 auto* components_opt = project_config.option<ConfigOptionStrings>("filament_mixed_components");
5194 auto* ratios_opt = project_config.option<ConfigOptionStrings>("filament_mixed_sublayer_ratios");
5195
5196 // Parse existing components
5197 if (components_opt && cfg_idx < components_opt->values.size()) {
5198 const std::string& cs = components_opt->values[cfg_idx];
5199 std::istringstream iss(cs);
5200 std::string tok;
5201 while (std::getline(iss, tok, ',')) {
5202 unsigned int v = 0;
5203 if (std::sscanf(tok.c_str(), "%u", &v) == 1)
5204 existing.components.push_back(v);
5205 }
5206 }
5207 // Parse existing ratios
5208 if (ratios_opt && cfg_idx < ratios_opt->values.size()) {
5209 CNumericLocalesSetter c_locale_setter;
5210 const std::string& rs = ratios_opt->values[cfg_idx];
5211 std::istringstream iss(rs);
5212 std::string tok;
5213 while (std::getline(iss, tok, ',')) {
5214 float v = 0;
5215 if (std::sscanf(tok.c_str(), "%f", &v) == 1)
5216 existing.ratios.push_back((int)(v * 100 + 0.5f));
5217 }
5218 }
5219 if (existing.components.size() < 2) {
5220 existing.components = {1, 2};
5221 existing.ratios = {50, 50};
5222 } else if (existing.ratios.size() != existing.components.size()) {
5223 BOOST_LOG_TRIVIAL(warning) << "Mixed filament edit: ratio count ("
5224 << existing.ratios.size() << ") != component count ("
5225 << existing.components.size()
5226 << "), resetting to even distribution";
5227 int n = (int)existing.components.size();
5228 existing.ratios.assign(n, 100 / n);
5229 existing.ratios[0] += 100 - (100 / n) * n;
5230 }
5231
5232 // Read gradient settings
5233 auto* grad_opt = project_config.option<ConfigOptionBools>("filament_mixed_gradient");
5234 if (grad_opt && cfg_idx < grad_opt->values.size())
5235 existing.gradient_enabled = grad_opt->values[cfg_idx];
5236 auto* grad_range_opt = project_config.option<ConfigOptionStrings>("filament_mixed_gradient_range");
5237 if (existing.gradient_enabled && grad_range_opt && cfg_idx < grad_range_opt->values.size()) {
5238 CNumericLocalesSetter c_locale_setter;
5239 float v0 = 0, v1 = 0;
5240 if (std::sscanf(grad_range_opt->values[cfg_idx].c_str(), "%f,%f", &v0, &v1) == 2)
5241 existing.gradient_direction = (v0 > v1) ? 0 : 1;
5242 }
5243 auto* grad_curve_opt = project_config.option<ConfigOptionStrings>("filament_mixed_gradient_curve");
5244 if (existing.gradient_enabled && grad_curve_opt && cfg_idx < grad_curve_opt->values.size()) {
5245 auto curve = Slic3r::parse_gradient_curve(grad_curve_opt->values[cfg_idx]);
5246 existing.gradient_curve = curve.points;
5247 }
5248 auto* per_part_opt = project_config.option<ConfigOptionBools>("filament_mixed_gradient_per_part");
5249 if (existing.gradient_enabled && per_part_opt && cfg_idx < per_part_opt->values.size())
5250 existing.per_part_gradient = per_part_opt->values[cfg_idx];
5251
5252 MixedFilamentDialog dlg(this, existing, color_strs, names, types);
5253 if (dlg.ShowModal() == wxID_OK) {
5254 auto result = dlg.get_result();
5255 if (result.components.size() < 2 || result.ratios.size() < 2) return;
5256
5257 // Serialize components
5258 std::string comp_str;
5259 for (size_t i = 0; i < result.components.size(); ++i) {
5260 if (i > 0) comp_str += ",";
5261 comp_str += std::to_string(result.components[i]);
5262 }
5263 components_opt->values[cfg_idx] = comp_str;
5264
5265 // Serialize ratios
5266 int ratio_sum = 0;
5267 for (int r : result.ratios) ratio_sum += r;
5268 if (ratio_sum <= 0) ratio_sum = 100;
5269
5270 std::string ratio_str;
5271 {
5272 CNumericLocalesSetter c_locale_setter;
5273 for (size_t i = 0; i < result.ratios.size(); ++i) {
5274 if (i > 0) ratio_str += ",";
5275 char buf[32];
5276 std::snprintf(buf, sizeof(buf), "%.4f", (float)result.ratios[i] / ratio_sum);
5277 ratio_str += buf;
5278 }
5279 }
5280 ratios_opt->values[cfg_idx] = ratio_str;
5281
5282 // Gradient settings — ensure keys exist in dynamic config
5283 if (!project_config.option("filament_mixed_gradient"))
5284 project_config.set_key_value("filament_mixed_gradient", new ConfigOptionBools({false}));
5285 if (!project_config.option("filament_mixed_gradient_range"))
5286 project_config.set_key_value("filament_mixed_gradient_range", new ConfigOptionStrings({""}) );
5287 if (!project_config.option("filament_mixed_gradient_curve"))
5288 project_config.set_key_value("filament_mixed_gradient_curve", new ConfigOptionStrings({""}) );
5289 if (!project_config.option("filament_mixed_gradient_per_part"))
5290 project_config.set_key_value("filament_mixed_gradient_per_part", new ConfigOptionBools({false}));
5291
5292 {
5293 auto* grad_opt = project_config.option<ConfigOptionBools>("filament_mixed_gradient");
5294 while (grad_opt->values.size() <= cfg_idx) grad_opt->values.push_back(false);
5295 grad_opt->values[cfg_idx] = result.gradient_enabled;
5296 }
5297 {
5298 auto* grad_range_opt = project_config.option<ConfigOptionStrings>("filament_mixed_gradient_range");
5299 while (grad_range_opt->values.size() <= cfg_idx) grad_range_opt->values.push_back("");
5300 if (result.gradient_enabled && result.components.size() == 2) {
5301 const char* fmt = (result.gradient_direction == 0) ? "0.9000,0.1000" : "0.1000,0.9000";
5302 grad_range_opt->values[cfg_idx] = fmt;
5303 } else {
5304 grad_range_opt->values[cfg_idx] = "";
5305 }
5306 }
5307 {
5308 auto* grad_curve_opt = project_config.option<ConfigOptionStrings>("filament_mixed_gradient_curve");
5309 while (grad_curve_opt->values.size() <= cfg_idx) grad_curve_opt->values.push_back("");
5310 grad_curve_opt->values[cfg_idx] = serialize_mixed_gradient_curve_if_custom(result);
5311 }
5312 {
5313 auto* per_part_opt = project_config.option<ConfigOptionBools>("filament_mixed_gradient_per_part");
5314 while (per_part_opt->values.size() <= cfg_idx) per_part_opt->values.push_back(false);
5315 per_part_opt->values[cfg_idx] = result.gradient_enabled && result.per_part_gradient;
5316 }
5317
5318 // Compute blended color
5319 std::string blended = blend_mixed_color(result.components, result.ratios, color_strs);
5320 auto* colours_opt = project_config.option<ConfigOptionStrings>("filament_colour");
5321 if (colours_opt && cfg_idx < colours_opt->values.size())
5322 colours_opt->values[cfg_idx] = blended;
5323
5324 auto* multi_colour_opt = project_config.option<ConfigOptionStrings>("filament_multi_colour");
5325 if (multi_colour_opt && cfg_idx < multi_colour_opt->values.size())
5326 multi_colour_opt->values[cfg_idx] = blended;
5327
5328 // The edited slot keeps its index, so nothing else refreshes the per-feature filament
5329 // lists - and its blended colour and type are what they show for it.
5332 wxGetApp().plater()->update_project_dirty_from_presets();
5333 wxPostEvent(this, SimpleEvent(EVT_SCHEDULE_BACKGROUND_PROCESS, this));
5334 }
5335}
std::vector< unsigned char > values
Definition Config.hpp:418
void update_mixed_filament_list()
Definition Plater.cpp:4326
void update_dynamic_filament_list()
Definition Plater.cpp:6627
static std::string blend_mixed_color(const std::vector< unsigned int > &comp_ids, const std::vector< int > &ratios, const std::vector< std::string > &color_strs)
Definition Plater.cpp:4315
static std::string serialize_mixed_gradient_curve_if_custom(const MixedFilamentResult &result)
Definition Plater.cpp:5005
GradientCurve parse_gradient_curve(const std::string &s)
Definition FilamentMixer.cpp:269

References Slic3r::GUI::blend_mixed_color(), collect_physical_filament_info(), Slic3r::GUI::MixedFilamentResult::components, Slic3r::GUI::MixedFilamentDialog::get_result(), Slic3r::GUI::MixedFilamentResult::gradient_curve, Slic3r::GUI::MixedFilamentResult::gradient_direction, Slic3r::GUI::MixedFilamentResult::gradient_enabled, Slic3r::parse_gradient_curve(), Slic3r::GUI::MixedFilamentResult::per_part_gradient, Slic3r::GUI::plater(), Slic3r::GUI::MixedFilamentResult::ratios, Slic3r::GUI::serialize_mixed_gradient_curve_if_custom(), Slic3r::GUI::DPIAware< P >::ShowModal(), Slic3r::ConfigOptionVector< T >::size(), update_dynamic_filament_list(), update_mixed_filament_list(), and Slic3r::ConfigOptionVector< T >::values.

Referenced by update_mixed_filament_list().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ enable_buttons()

void Slic3r::GUI::Sidebar::enable_buttons ( bool enable)
6698{
6699#if 0
6700 p->btn_reslice->Enable(enable);
6701 p->btn_export_gcode->Enable(enable);
6702 p->btn_send_gcode->Enable(enable);
6703// p->btn_eject_device->Enable(enable);
6704 p->btn_export_gcode_removable->Enable(enable);
6705#endif
6706}

References p.

◆ enable_nozzle_count_edit()

void Slic3r::GUI::Sidebar::enable_nozzle_count_edit ( bool enable)
6620{
6621 if (!p)
6622 return;
6623 p->left_extruder->SetEditEnabled(enable);
6624 p->right_extruder->SetEditEnabled(enable);
6625}

References p.

◆ enable_purge_mode_btn()

void Slic3r::GUI::Sidebar::enable_purge_mode_btn ( bool enable)
6597{
6598 if (!p || !p->m_purge_mode_btn)
6599 return;
6600 p->m_purge_mode_btn->Show(enable);
6601 wxGetApp().CallAfter([this]() {
6602 p->m_panel_filament_title->Layout();
6603 this->Layout();
6604 });
6605}

References p.

◆ ensure_mixed_filament()

int Slic3r::GUI::Sidebar::ensure_mixed_filament ( const std::vector< unsigned int > & components,
const std::vector< int > & ratios )
5133{
5134 if (components.size() < 2 || components.size() != ratios.size())
5135 return -1;
5136 if (p->combos_filament.size() < 2)
5137 return -1;
5138 if (std::accumulate(ratios.begin(), ratios.end(), 0) <= 0)
5139 return -1;
5140
5141 if (const int existing = find_fixed_mixed_filament(wxGetApp().preset_bundle->project_config, components, ratios);
5142 existing >= 0)
5143 return existing;
5144
5145 if (wxGetApp().preset_bundle->filament_presets.size() >= size_t(EnforcerBlockerType::ExtruderMax))
5146 return -1;
5147
5148 std::vector<std::string> color_strs, names, types;
5149 collect_physical_filament_info(color_strs, names, types);
5150
5151 MixedFilamentResult result;
5152 result.components = components;
5153 result.ratios = ratios;
5154 const size_t created_at = wxGetApp().preset_bundle->filament_presets.size();
5155 if (!create_mixed_filament_from_result(this, result, color_strs))
5156 return -1;
5157 return int(created_at);
5158}
int find_fixed_mixed_filament(const ConfigBase &project_config, const std::vector< unsigned int > &components, const std::vector< int > &weights)
Definition FilamentMixer.cpp:461

References collect_physical_filament_info(), Slic3r::GUI::MixedFilamentResult::components, Slic3r::GUI::create_mixed_filament_from_result(), Slic3r::ExtruderMax, Slic3r::find_fixed_mixed_filament(), p, and Slic3r::GUI::MixedFilamentResult::ratios.

Here is the call graph for this function:

◆ filament_panel()

wxPanel * Slic3r::GUI::Sidebar::filament_panel ( )
6666{
6667 return p->m_panel_filament_content;
6668}

References p.

◆ finish_param_edit()

void Slic3r::GUI::Sidebar::finish_param_edit ( )
6889{ p->editing_filament = -1; }

References p.

◆ get_big_btn_sync_pos_size()

void Slic3r::GUI::Sidebar::get_big_btn_sync_pos_size ( wxPoint & pt,
wxSize & size )
6223{
6224 size = p->m_printer_bbl_sync->GetSize();
6225 pt = p->m_printer_bbl_sync->GetScreenPosition();
6226}

References p.

◆ get_cur_combox_bed_types()

const std::vector< BedType > & Slic3r::GUI::Sidebar::get_cur_combox_bed_types ( )
inline
195{ return m_cur_combox_bed_types; }
std::vector< BedType > m_cur_combox_bed_types
Definition Plater.hpp:164

References m_cur_combox_bed_types.

◆ get_cur_select_bed_image()

std::string Slic3r::GUI::Sidebar::get_cur_select_bed_image ( )
4213{
4214 auto select_bed_type = get_cur_select_bed_type();
4215 //auto series_suffix_str = m_cur_image_bed_type.empty() ? "" : ("_" + m_cur_image_bed_type);
4216 auto image_path = bed_type_thumbnails[select_bed_type];// + series_suffix_str;
4217 return image_path;
4218}
BedType get_cur_select_bed_type()
Definition Plater.cpp:4202
static std::map< BedType, std::string > bed_type_thumbnails
Definition Plater.cpp:453

References Slic3r::GUI::bed_type_thumbnails, and get_cur_select_bed_type().

Referenced by Sidebar(), msw_rescale(), on_enter_image_printer_bed(), and update_presets().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_cur_select_bed_type()

BedType Slic3r::GUI::Sidebar::get_cur_select_bed_type ( )
4202 {
4203 int selection = p->combo_printer_bed->GetSelection();
4204 if (selection < 0 && selection >= m_cur_combox_bed_types.size()) {
4205 p->combo_printer_bed->SetSelection(0);
4206 selection = 0;
4207 }
4208 auto select_bed_type = m_cur_combox_bed_types[selection];
4209 return select_bed_type;
4210}

References m_cur_combox_bed_types, and p.

Referenced by get_cur_select_bed_image().

Here is the caller graph for this function:

◆ get_eject_shown()

bool Slic3r::GUI::Sidebar::get_eject_shown ( ) const

References collapse().

Here is the call graph for this function:

◆ get_search_line()

std::string & Slic3r::GUI::Sidebar::get_search_line ( )
6923{
6924 return p->searcher.search_string();
6925}

References p.

◆ get_searcher()

Search::OptionsSearcher & Slic3r::GUI::Sidebar::get_searcher ( )
6913{
6914 return p->searcher;
6915}

References p.

◆ get_sidebar_pos_right_x()

int Slic3r::GUI::Sidebar::get_sidebar_pos_right_x ( )
6204{
6205 return this->GetScreenPosition().x + this->GetSize().x;
6206}

◆ get_small_btn_sync_pos_size()

void Slic3r::GUI::Sidebar::get_small_btn_sync_pos_size ( wxPoint & pt,
wxSize & size )
6228 {
6229 size = ams_btn->GetSize();
6230 pt = ams_btn->GetScreenPosition();
6231}

References ams_btn.

Referenced by pop_finsish_sync_ams_dialog(), and pop_sync_nozzle_and_ams_dialog().

Here is the caller graph for this function:

◆ get_wiping_dialog_button()

wxButton * Slic3r::GUI::Sidebar::get_wiping_dialog_button ( )
6680{
6681#if 0
6682 return p->frequently_changed_parameters->get_wiping_dialog_button();
6683#endif
6684 return NULL;
6685}

References p.

◆ has_broken_mixed_filament() [1/2]

bool Slic3r::GUI::Sidebar::has_broken_mixed_filament ( ) const
4862{
4863 auto* plater = dynamic_cast<Plater*>(GetParent());
4864 if (!plater) return false;
4866}
PartPlate * get_curr_plate()
Definition PartPlate.hpp:962
PartPlateList & get_partplate_list()
Definition Plater.cpp:22578
bool has_broken_mixed_filament() const
Definition Plater.cpp:4861

References has_broken_mixed_filament(), and Slic3r::GUI::plater().

Referenced by has_broken_mixed_filament().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ has_broken_mixed_filament() [2/2]

bool Slic3r::GUI::Sidebar::has_broken_mixed_filament ( const PartPlate * plate) const
4869{
4870 if (!plate) return false;
4871 auto* plater = dynamic_cast<Plater*>(GetParent());
4872 if (!plater) return false;
4873
4874 auto& project_config = wxGetApp().preset_bundle->project_config;
4875 auto* is_mixed_opt = project_config.option<ConfigOptionBools>("filament_is_mixed");
4876 auto* comp_strs_opt = project_config.option<ConfigOptionStrings>("filament_mixed_components");
4877 if (!is_mixed_opt || !comp_strs_opt) return false;
4878
4879 size_t num_physical = p->combos_filament.size();
4880 auto broken_slots = check_mixed_filament_integrity(is_mixed_opt->values, comp_strs_opt->values, num_physical);
4881
4882 // Type consistency check
4883 {
4884 std::vector<std::string> physical_types;
4885 auto& preset_bundle = *wxGetApp().preset_bundle;
4886 for (size_t i = 0; i < num_physical; ++i) {
4887 std::string ft;
4888 if (i < preset_bundle.filament_presets.size()) {
4889 auto* preset = preset_bundle.filaments.find_preset(preset_bundle.filament_presets[i]);
4890 if (preset) {
4891 std::string display_type;
4892 ft = preset->config.get_filament_type(display_type);
4893 }
4894 }
4895 if (ft.empty()) ft = "PLA";
4896 physical_types.push_back(ft);
4897 }
4898 auto type_mismatch_slots = check_mixed_filament_type_consistency(
4899 is_mixed_opt->values, comp_strs_opt->values, physical_types);
4900 broken_slots.insert(broken_slots.end(), type_mismatch_slots.begin(), type_mismatch_slots.end());
4901 }
4902
4903 if (broken_slots.empty()) return false;
4904
4905 std::set<size_t> broken_1based;
4906 for (size_t s : broken_slots) broken_1based.insert(s + 1);
4907
4908 // Scan model objects on the given plate for raw extruder assignments
4909 // (don't use get_extruders() which expands mixed slots)
4910 for (auto& entry : plater->model().objects) {
4911 if (!plate->contain_instance_totally(entry, 0))
4912 continue;
4913 // Check object-level extruder
4914 int obj_ext = entry->config.has("extruder") ? entry->config.extruder() : 1;
4915 if (broken_1based.count((size_t)obj_ext))
4916 return true;
4917 for (auto* vol : entry->volumes) {
4918 // Check volume-level extruder
4919 int vol_ext = vol->config.has("extruder") ? vol->config.extruder() : obj_ext;
4920 if (broken_1based.count((size_t)vol_ext))
4921 return true;
4922 // Check color painting data (mmu segmentation facets)
4923 if (vol->is_model_part() && !vol->mmu_segmentation_facets.empty()) {
4924 for (size_t broken_slot : broken_1based) {
4925 if (vol->mmu_segmentation_facets.has_facets(*vol, EnforcerBlockerType(broken_slot)))
4926 return true;
4927 }
4928 }
4929 }
4930 // Check height range modifier extruder overrides
4931 for (auto& [range, cfg] : entry->layer_config_ranges) {
4932 if (cfg.has("extruder")) {
4933 int layer_ext = cfg.option("extruder")->getInt();
4934 if (layer_ext > 0 && broken_1based.count((size_t)layer_ext))
4935 return true;
4936 }
4937 }
4938 }
4939
4940 return false;
4941}
const Model & model() const
Definition Plater.cpp:16047
ModelObjectPtrs objects
Definition Model.hpp:1702
auto range(Cont &&cont)
Definition libslic3r.h:405
std::vector< size_t > check_mixed_filament_type_consistency(const std::vector< unsigned char > &is_mixed, const std::vector< std::string > &comp_strs, const std::vector< std::string > &filament_types)
Definition FilamentMixer.cpp:564
std::vector< size_t > check_mixed_filament_integrity(const std::vector< unsigned char > &is_mixed, const std::vector< std::string > &comp_strs, size_t num_physical)
Definition FilamentMixer.cpp:493

References Slic3r::check_mixed_filament_integrity(), Slic3r::check_mixed_filament_type_consistency(), Slic3r::GUI::PartPlate::contain_instance_totally(), p, Slic3r::GUI::plater(), Slic3r::range(), and Slic3r::ConfigOptionVector< unsigned char >::values.

Here is the call graph for this function:

◆ init_filament_combo()

void Slic3r::GUI::Sidebar::init_filament_combo ( PlaterPresetComboBox ** combo,
const int filament_idx )
3700{
3701 *combo = new PlaterPresetComboBox(p->m_panel_filament_content, Slic3r::Preset::TYPE_FILAMENT);
3702 (*combo)->set_filament_idx(filament_idx);
3703
3704 auto combo_and_btn_sizer = new wxBoxSizer(wxHORIZONTAL);
3705
3706 // BBS: filament double columns
3707
3708 // int em = wxGetApp().em_unit();
3709 if ((filament_idx % 2) == 0) // Dont add right column item. this one create equal spacing on left, right & middle
3710 combo_and_btn_sizer->AddSpacer(FromDIP((filament_idx % 2) == 0 ? 12 : 3)); // Content Margin
3711
3712 (*combo)->clr_picker->SetLabel(wxString::Format("%d", filament_idx + 1));
3713 combo_and_btn_sizer->Add((*combo)->clr_picker, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(SidebarProps::ElementSpacing()) - FromDIP(2)); // ElementSpacing - 2 (from combo box))
3714 combo_and_btn_sizer->Add(*combo, 1, wxALL | wxEXPAND, FromDIP(2))->SetMinSize({-1, 30 * wxGetApp().em_unit() / 10}); // ORCA ensure height matches with PlaterPresetComboBox
3715
3716 /* BBS hide del_btn
3717 ScalableButton* del_btn = new ScalableButton(p->m_panel_filament_content, wxID_ANY, "delete_filament");
3718 del_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e){
3719 int extruder_count = std::max(1, (int)p->combos_filament.size() - 1);
3720
3721 update_objects_list_filament_column(std::max(1, extruder_count - 1));
3722 on_filament_count_change(extruder_count);
3723 wxGetApp().preset_bundle->printers.get_edited_preset().set_num_extruders(extruder_count);
3724 wxGetApp().preset_bundle->update_multi_material_filament_presets();
3725 });
3726
3727 combo_and_btn_sizer->Add(32 * em / 10, 0, 0, 0, 0);
3728 combo_and_btn_sizer->Add(del_btn, 0, wxALIGN_CENTER_VERTICAL, 5 * em / 10);
3729 */
3730 ScalableButton* edit_btn = new ScalableButton(p->m_panel_filament_content, wxID_ANY, "menu_filament");
3731 edit_btn->SetToolTip(_L("Click to edit preset"));
3732
3733 PlaterPresetComboBox* combobox = (*combo);
3734 edit_btn->Bind(wxEVT_BUTTON, [this, edit_btn, combobox, filament_idx](wxCommandEvent) {
3735 bool single_or_bbl = should_show_SEMM_buttons();
3736 bool is_multi_material = p->combos_filament.size() > 1;
3737 if(single_or_bbl && is_multi_material) {
3738 // MULTI MATERIAL Show menu
3739 auto menu = p->plater->filament_action_menu(filament_idx);
3740 wxPoint pt { 0, edit_btn->GetSize().GetHeight() + FromDIP(2) };
3741 pt = edit_btn->ClientToScreen(pt);
3742 pt = wxGetApp().mainframe->ScreenToClient(pt);
3743 p->m_menu_filament_id = filament_idx;
3744 p->plater->PopupMenu(menu, (int) pt.x, pt.y);
3745 }
3746 else {
3747 // SINGLE MATERIAL / MULTI EXTRUDER / TOOLCHANGER / IDEX Opens Dialog directly
3748 p->editing_filament = filament_idx;
3749 combobox->switch_to_tab();
3750 }
3751 });
3752 combobox->edit_btn = edit_btn;
3753
3754 combo_and_btn_sizer->Add(edit_btn, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(SidebarProps::ElementSpacing()) - FromDIP(2)); // ElementSpacing - 2 (from combo box))
3755
3756 combo_and_btn_sizer->AddSpacer(FromDIP(SidebarProps::ContentMargin()));
3757
3758 // BBS: filament double columns
3759 auto side = filament_idx % 2;
3760 auto /***/sizer_filaments = this->p->sizer_filaments->GetItem(side)->GetSizer();
3761 if (side == 1 && filament_idx > 1) sizer_filaments->Remove(filament_idx / 2);
3762 sizer_filaments->Add(combo_and_btn_sizer, 1, wxEXPAND);
3763 if (side == 0 && filament_idx > 0) {
3764 sizer_filaments = this->p->sizer_filaments->GetItem(1)->GetSizer();
3765 sizer_filaments->AddStretchSpacer(1);
3766 }
3767}
static int ContentMargin()
Definition Plater.hpp:149
static bool should_show_SEMM_buttons()
Definition Plater.cpp:6559

References _L, Slic3r::GUI::SidebarProps::ContentMargin(), Slic3r::GUI::PlaterPresetComboBox::edit_btn, Slic3r::GUI::SidebarProps::ElementSpacing(), p, should_show_SEMM_buttons(), Slic3r::GUI::PlaterPresetComboBox::switch_to_tab(), and Slic3r::Preset::TYPE_FILAMENT.

Referenced by Sidebar(), and on_filament_count_change().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_collapsed()

bool Slic3r::GUI::Sidebar::is_collapsed ( )
6852{ return p->plater->is_sidebar_collapsed(); }

References p.

◆ is_fila_switch_ready()

bool Slic3r::GUI::Sidebar::is_fila_switch_ready ( )
6171{
6172 return p->is_fila_switch_ready();
6173}

References p.

Referenced by Slic3r::GUI::Sidebar::priv::sync_extruder_list(), and Slic3r::GUI::Sidebar::priv::update_sync_status().

Here is the caller graph for this function:

◆ is_multifilament()

bool Slic3r::GUI::Sidebar::is_multifilament ( )
6716{
6717 return p->combos_filament.size() > 1;
6718}

References p.

◆ is_new_project_in_gcode3mf()

bool Slic3r::GUI::Sidebar::is_new_project_in_gcode3mf ( )
6028{
6029 // A .gcode previewed with its own settings shows them here too, and is closed the same way.
6030 if (p->plater->using_exported_file() || p->plater->gcode_settings_loaded()) {
6031 auto filename = p->plater->get_preview_only_filename();
6032 auto text = wxString::Format(_L("After completing your operation, %s project will be closed and create a new project."), filename);
6033 MessageDialog dlg(wxGetApp().plater(), text, _L("Warning"),
6034 wxOK | wxICON_WARNING);
6035 dlg.ShowModal();
6036 p->plater->new_project();
6037 return true;
6038 }
6039 return false;
6040}

References _L, p, Slic3r::GUI::plater(), and Slic3r::GUI::DPIAware< P >::ShowModal().

Referenced by add_custom_filament(), and delete_filament().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ jump_to_object()

void Slic3r::GUI::Sidebar::jump_to_object ( ObjectDataViewModelNode * item)
7117{
7118 p->jump_to_object(item);
7119}

References p.

◆ jump_to_option() [1/2]

void Slic3r::GUI::Sidebar::jump_to_option ( const std::string & opt_key,
Preset::Type type,
const std::wstring & category )
5682{
5683 //const Search::Option& opt = p->searcher.get_option(opt_key, type);
5684 if (type == Preset::TYPE_PRINT) {
5685 auto tab = dynamic_cast<TabPrintModel*>(wxGetApp().params_panel()->get_current_tab());
5686 if (tab && tab->has_key(opt_key)) {
5687 tab->activate_option(opt_key, category);
5688 return;
5689 }
5690 wxGetApp().params_panel()->switch_to_global();
5691 }
5692 wxGetApp().get_tab(type)->activate_option(opt_key, category);
5693}

References Slic3r::Preset::TYPE_PRINT.

◆ jump_to_option() [2/2]

void Slic3r::GUI::Sidebar::jump_to_option ( size_t selected)
5696{
5697 const Search::Option& opt = p->searcher.get_option(selected);
5698 jump_to_option(opt.opt_key(), opt.type, opt.category);
5699
5700 // Switch to the Settings NotePad
5701// wxGetApp().mainframe->select_tab();
5702}
void jump_to_option(size_t selected)
Definition Plater.cpp:5695

References jump_to_option(), and p.

Referenced by jump_to_option().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_ams_list()

void Slic3r::GUI::Sidebar::load_ams_list ( MachineObject * obj)
6234{
6235 std::map<int, DynamicPrintConfig> filament_ams_list;
6236
6237 // build_filament_ams_list handles both subscription-based and non-subscription-based agents:
6238 // - For non-subscription agents, it calls fetch_filament_info() first to populate DevFilaSystem
6239 // - Then it always reads from DevFilaSystem to build the filament list
6240 if (obj) {
6241 filament_ams_list = build_filament_ams_list(obj);
6242 }
6243
6244 const std::string& device = obj ? obj->get_dev_id() : "";
6245 const bool same_device = p->ams_list_device == device;
6246
6247 // Keep sync metadata out of the device payload, but preserve it across a
6248 // subscription refresh when the physical filament in a slot is unchanged.
6249 // Otherwise the refreshed configs differ only by the missing
6250 // filament_changed key, causing combo boxes to rebuild and lose their
6251 // transient post-sync badges.
6252 auto &previous_filament_ams_list = wxGetApp().preset_bundle->filament_ams_list;
6253 for (auto &entry : filament_ams_list) {
6254 auto previous = previous_filament_ams_list.find(entry.first);
6255 const auto *previous_changed = previous == previous_filament_ams_list.end() ? nullptr :
6256 dynamic_cast<const ConfigOptionBool *>(previous->second.option("filament_changed"));
6257 if (!same_device || previous_changed == nullptr ||
6258 previous->second.opt_string("filament_id", 0u) != entry.second.opt_string("filament_id", 0u)) {
6259 continue;
6260 }
6261 entry.second.set_key_value("filament_changed",
6262 new ConfigOptionBool{previous_changed->value});
6263 }
6264
6265 bool device_change = !same_device;
6266 if (device_change) {
6267 p->ams_list_device = device;
6268 }
6269 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": %1% items") % filament_ams_list.size();
6270 if (wxGetApp().preset_bundle->filament_ams_list == filament_ams_list && !device_change)
6271 {
6272 return;
6273 }
6274 wxGetApp().preset_bundle->filament_ams_list = filament_ams_list;
6275
6276 for (auto c : p->combos_filament){
6277 c->set_sync_badge(false);
6278 c->update();
6279 }
6280
6281 if (!device_change) {
6282 size_t combo_index = 0;
6283 for (const auto &entry : filament_ams_list) {
6284 const auto &tray = entry.second;
6285 const bool has_filament = !tray.opt_string("filament_id", 0u).empty();
6286 const bool is_placeholder = tray.has("filament_slot_placeholder") &&
6287 tray.opt_bool("filament_slot_placeholder", 0u);
6288 if (!has_filament && !is_placeholder) {
6289 continue;
6290 }
6291 if (combo_index >= p->combos_filament.size()) {
6292 break;
6293 }
6294 const auto *filament_changed = dynamic_cast<const ConfigOptionBool *>(tray.option("filament_changed"));
6295 p->combos_filament[combo_index]->set_sync_badge(
6296 has_filament && !is_placeholder && filament_changed != nullptr && filament_changed->value);
6297 ++combo_index;
6298 }
6299 }
6300
6301 p->combo_printer->update();
6302}
std::map< int, DynamicPrintConfig > build_filament_ams_list(MachineObject *obj)
Definition Plater.cpp:6092

References build_filament_ams_list(), Slic3r::MachineObject::get_dev_id(), and p.

Here is the call graph for this function:

◆ msw_rescale()

void Slic3r::GUI::Sidebar::msw_rescale ( )
5486{
5487 SetMinSize(wxSize(39 * wxGetApp().em_unit(), -1));
5488 p->m_panel_printer_title->GetSizer()->SetMinSize(-1, 3 * wxGetApp().em_unit());
5489 p->m_panel_filament_title->GetSizer()
5490 ->SetMinSize(-1, 3 * wxGetApp().em_unit());
5491 p->m_printer_icon->msw_rescale();
5492 p->m_printer_connect->msw_rescale();
5493 p->m_printer_bbl_sync->msw_rescale();
5494 p->m_printer_icon->msw_rescale();
5495 p->m_printer_setting->msw_rescale();
5496
5497 p->panel_printer_preset->SetMinSize(FromDIP(PRINTER_PANEL_SIZE));
5498 p->panel_printer_preset->SetCornerRadius(FromDIP(PRINTER_PANEL_RADIUS));
5499 p->image_printer->SetSize(FromDIP(PRINTER_THUMBNAIL_SIZE));
5501 p->combo_printer->Rescale();
5502 p->combo_printer->SetMaxSize(wxSize(-1, FromDIP(30))); // limiting height makes badge visible
5503 p->btn_edit_printer->msw_rescale();
5504
5505 p->panel_nozzle_dia->SetMinSize(FromDIP(PRINTER_PANEL_SIZE));
5506 p->panel_nozzle_dia->SetCornerRadius(FromDIP(PRINTER_PANEL_RADIUS));
5507 p->combo_nozzle_dia->Rescale();
5508
5509 p->panel_printer_bed->SetMinSize(FromDIP(PRINTER_PANEL_SIZE));
5510 p->panel_printer_bed->SetCornerRadius(FromDIP(PRINTER_PANEL_RADIUS));
5511 p->combo_printer_bed->Rescale();
5512 p->combo_printer_bed->SetMinSize(FromDIP(wxSize(18,-1))); // ORCA show only arrow
5513 p->combo_printer_bed->SetMaxSize(FromDIP(wxSize(18,-1))); // ORCA show only arrow
5514 bool isDual = static_cast<wxBoxSizer *>(p->panel_printer_preset->GetSizer())->GetOrientation() == wxVERTICAL;
5515 auto image_path = get_cur_select_bed_image();
5516 p->image_printer_bed->SetBitmap(create_scaled_bitmap(image_path, this, PRINTER_THUMBNAIL_SIZE.GetHeight()));
5517 if (p->big_bed_image_popup){ // ORCA force rebuild frame. current wxwidget version not supports wxBITMAP_SCALE_FILL flag on wxStaticBitmap
5518 // also wxImage scaledImage = bit_map.ConvertToImage(); scaledImage.Rescale(FromDIP(m_image_px), FromDIP(m_image_px), wxIMAGE_QUALITY_HIGH);
5519 // didnt worked as expected and it requires use on set_bitmap. so that will try to scale everytime
5520 p->big_bed_image_popup->Destroy();
5521 p->big_bed_image_popup = nullptr;
5522 }
5523
5524 p->m_filament_icon->msw_rescale();
5525 p->m_bpButton_add_filament->msw_rescale();
5526 p->m_bpButton_del_filament->msw_rescale();
5527 p->m_bpButton_ams_filament->msw_rescale();
5528 p->m_bpButton_set_filament->msw_rescale();
5529 p->m_purge_mode_btn->Rescale();
5530 p->m_flushing_volume_btn->Rescale();
5531 set_flushing_volume_warning(is_flush_config_modified()); // ORCA reapply appearance
5532
5533 //BBS
5534 p->left_extruder->Rescale();
5535 p->right_extruder->Rescale();
5536 p->single_extruder->Rescale();
5537
5538 //p->btn_sync_printer->SetPaddingSize({FromDIP(6), FromDIP(12)});
5539 //p->btn_sync_printer->SetMinSize(BTN_SYNC_SIZE);
5540 //p->btn_sync_printer->Rescale();
5541#if 0
5542 if (p->mode_sizer)
5543 p->mode_sizer->msw_rescale();
5544#endif
5545
5546 //for (PlaterPresetComboBox* combo : std::vector<PlaterPresetComboBox*> { p->combo_print,
5547 // //p->combo_sla_print,
5548 // //p->combo_sla_material,
5549 // //p->combo_printer
5550 // } )
5551 // combo->msw_rescale();
5552
5553 for (PlaterPresetComboBox* combo : p->combos_filament)
5554 combo->msw_rescale();
5555
5556 p->m_panel_filament_content->Layout();
5557 update_filaments_area_height(); // ORCA resize after combos scaled
5558
5559 // BBS
5560 //p->frequently_changed_parameters->msw_rescale();
5561 //obj_list()->msw_rescale();
5562 // BBS TODO: add msw_rescale for newly added windows
5563 // BBS
5564 //p->object_manipulation->msw_rescale();
5565 p->object_settings->msw_rescale();
5566 p->m_search_item->Rescale();
5567 p->m_search_item->GetTextCtrl()->SetSize(wxSize(-1, FromDIP(16)));
5568 p->m_search_bar->Layout();
5569
5570 // BBS
5571#if 0
5572 p->object_info->msw_rescale();
5573
5574 p->btn_send_gcode->msw_rescale();
5575// p->btn_eject_device->msw_rescale();
5576 p->btn_export_gcode_removable->msw_rescale();
5577#ifdef _WIN32
5578 const int scaled_height = p->btn_export_gcode_removable->GetBitmapHeight();
5579#else
5580 const int scaled_height = p->btn_export_gcode_removable->GetBitmapHeight() + 4;
5581#endif
5582 p->btn_export_gcode->SetMinSize(wxSize(-1, scaled_height));
5583 p->btn_reslice ->SetMinSize(wxSize(-1, scaled_height));
5584#endif
5585 p->scrolled->Layout();
5586
5587 p->searcher.dlg_msw_rescale();
5588}
void update_printer_thumbnail()
Definition Plater.cpp:6929

References create_scaled_bitmap(), em_unit(), get_cur_select_bed_image(), is_flush_config_modified(), Slic3r::GUI::PlaterPresetComboBox::msw_rescale(), p, PRINTER_PANEL_RADIUS, PRINTER_PANEL_SIZE, PRINTER_THUMBNAIL_SIZE, set_flushing_volume_warning(), update_filaments_area_height(), and update_printer_thumbnail().

Here is the call graph for this function:

◆ need_auto_sync_after_connect_printer()

bool Slic3r::GUI::Sidebar::need_auto_sync_after_connect_printer ( ) const
inline
bool m_need_auto_sync_after_connect_printer
Definition Plater.hpp:333

References m_need_auto_sync_after_connect_printer.

Referenced by Slic3r::GUI::MainFrame::update_layout().

Here is the caller graph for this function:

◆ need_auto_sync_extruder_list_after_connect_priner()

bool Slic3r::GUI::Sidebar::need_auto_sync_extruder_list_after_connect_priner ( const MachineObject * obj)
6181{
6182 if(!obj)
6183 return false;
6184
6185 std::string machine_print_name = obj->get_show_printer_type();
6186 PresetBundle *preset_bundle = wxGetApp().preset_bundle;
6187 std::string target_model_id = preset_bundle->printers.get_selected_preset().get_printer_type(preset_bundle);
6188 if (machine_print_name != target_model_id) {
6189 return false;
6190 }
6191
6192 if (preset_bundle->get_printer_extruder_count() <= 1 || !obj->is_multi_extruders())
6193 return false;
6194
6195 return true;
6196}

References Slic3r::PresetBundle::get_printer_extruder_count(), Slic3r::Preset::get_printer_type(), Slic3r::PresetCollection::get_selected_preset(), Slic3r::MachineObject::get_show_printer_type(), Slic3r::MachineObject::is_multi_extruders(), and Slic3r::PresetBundle::printers.

Referenced by Slic3r::GUI::MonitorPanel::on_machine_selected().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ obj_layers()

ObjectLayers * Slic3r::GUI::Sidebar::obj_layers ( )
6651{
6652 return p->object_layers;
6653}

References p.

Referenced by sys_color_changed().

Here is the caller graph for this function:

◆ obj_list()

◆ obj_settings()

ObjectSettings * Slic3r::GUI::Sidebar::obj_settings ( )
6646{
6647 return p->object_settings;
6648}

References p.

Referenced by Slic3r::GUI::ObjectList::update_settings_item_and_selection().

Here is the caller graph for this function:

◆ og_freq_chng_params()

ConfigOptionsGroup * Slic3r::GUI::Sidebar::og_freq_chng_params ( const bool is_fff)
6671{
6672 // BBS
6673#if 0
6674 return p->frequently_changed_parameters->get_og(is_fff);
6675#endif
6676 return NULL;
6677}

References p.

◆ on_bed_type_change()

void Slic3r::GUI::Sidebar::on_bed_type_change ( BedType bed_type)
6043{
6044 // Orca: Map BedType to the current combo list (some printers filter types).
6045
6046 if (p->combo_printer_bed == nullptr)
6047 return;
6048
6049 for (size_t i = 0; i < m_cur_combox_bed_types.size(); ++i) {
6050 if (m_cur_combox_bed_types[i] == bed_type) {
6051 p->combo_printer_bed->SetSelection(int(i));
6052 return;
6053 }
6054 }
6055
6056 if (!m_cur_combox_bed_types.empty())
6057 p->combo_printer_bed->SetSelection(0);
6058}

References m_cur_combox_bed_types, and p.

Referenced by Slic3r::GUI::Plater::on_bed_type_change().

Here is the caller graph for this function:

◆ on_change_color_mode()

void Slic3r::GUI::Sidebar::on_change_color_mode ( bool is_dark)
3673 {
3674 const ModelObjectPtrs &mos = wxGetApp().model().objects;
3675 for (int i = 0; i < mos.size(); i++) {
3676 wxGetApp().obj_list()->update_info_items(i,nullptr,false,true);
3677 }
3678
3679}
std::vector< ModelObject * > ModelObjectPtrs
Definition CutUtils.hpp:13

References is_dark().

Here is the call graph for this function:

◆ on_enter_image_printer_bed()

void Slic3r::GUI::Sidebar::on_enter_image_printer_bed ( wxMouseEvent & evt)
3646 {
3647 //p->image_printer_bed->Bind(wxEVT_LEAVE_WINDOW, &Sidebar::on_leave_image_printer_bed, this);
3648 auto pos = p->panel_printer_bed->GetScreenPosition();
3649 auto rect = p->panel_printer_bed->GetRect();
3650 wxPoint temp_pos(pos.x + rect.GetWidth() + FromDIP(3), pos.y);
3651 if (p->big_bed_image_popup == nullptr)
3652 p->big_bed_image_popup = new ImageDPIFrame();
3653 auto image_path = get_cur_select_bed_image();
3654 p->big_bed_image_popup->set_bitmap(create_scaled_bitmap("big_" + image_path, p->big_bed_image_popup, p->big_bed_image_popup->get_image_px()));
3655 p->big_bed_image_popup->set_title(p->combo_printer_bed->GetString(p->combo_printer_bed->GetSelection()));
3656 p->big_bed_image_popup->SetCanFocus(false);
3657 p->big_bed_image_popup->SetPosition(temp_pos);
3658 p->big_bed_image_popup->on_show();
3659}

References create_scaled_bitmap(), get_cur_select_bed_image(), p, and Slic3r::GUI::wxMouseEvent.

Referenced by Sidebar().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ on_filament_count_change()

void Slic3r::GUI::Sidebar::on_filament_count_change ( size_t num_filaments)
5706{
5707 // num_filaments counts every slot; mixed-color slots are virtual and get no combo of
5708 // their own (they are rendered by update_mixed_filament_list instead), so the physical
5709 // subset drives the combo list.
5710 auto& project_config = wxGetApp().preset_bundle->project_config;
5711 auto* is_mixed_opt = project_config.option<ConfigOptionBools>("filament_is_mixed");
5712
5713 std::vector<size_t> physical_indices;
5714 for (size_t i = 0; i < num_filaments; ++i) {
5715 if (!is_mixed_opt || i >= is_mixed_opt->values.size() || !is_mixed_opt->values[i])
5716 physical_indices.push_back(i);
5717 }
5718 const size_t num_physical = physical_indices.size();
5719
5720 auto& choices = combos_filament();
5721
5722 if (num_physical == choices.size()) {
5723 // The ctor pre-creates one combo, so a single-filament project hits this guard before
5724 // any layout pass has sized the scroll areas; refresh them here as well.
5725 // Adding a mixed slot also lands here, since only the virtual count changed, so the
5726 // per-feature filament lists - which do list mixed slots - have to be refreshed too.
5730 return;
5731 }
5732
5733 if (choices.size() == 1 || num_physical == 1)
5734 choices[0]->GetDropDown().Invalidate();
5735
5736 wxWindowUpdateLocker noUpdates_scrolled_panel(this);
5737
5738 size_t i = choices.size();
5739 while (i < num_physical)
5740 {
5741 PlaterPresetComboBox* choice/*{ nullptr }*/;
5742 init_filament_combo(&choice, physical_indices[i]);
5743 int last_selection = choices.back()->GetSelection();
5744 choices.push_back(choice);
5745
5746 // initialize selection
5747 choice->update();
5748 choice->SetSelection(last_selection);
5749 ++i;
5750 }
5751
5752 // remove unused choices if any
5753 remove_unused_filament_combos(num_physical);
5754
5755 show_SEMM_buttons(); // ORCA
5756
5760
5761 Layout();
5762 p->m_panel_filament_title->Refresh();
5765}
void show_SEMM_buttons()
Definition Plater.cpp:6568
void remove_unused_filament_combos(const size_t current_extruder_count)
Definition Plater.cpp:3769
void recalc_filament_scroll_sizes()
Definition Plater.cpp:4294

References combos_filament(), init_filament_combo(), p, recalc_filament_scroll_sizes(), remove_unused_filament_combos(), ComboBox::SetSelection(), show_SEMM_buttons(), Slic3r::GUI::PlaterPresetComboBox::update(), update_dynamic_filament_list(), update_filaments_area_height(), update_mixed_filament_list(), and update_ui_from_settings().

Referenced by Slic3r::GUI::Plater::on_filament_count_change().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ on_filaments_delete()

void Slic3r::GUI::Sidebar::on_filaments_delete ( size_t filament_id)
5768{
5769 auto &choices = combos_filament();
5770
5771 // A mixed (virtual) slot has no combo of its own, so there is no combo UI to remove —
5772 // but the shared refresh below must still run so the mixed filament panel drops its row.
5773 if (filament_id < choices.size()) {
5774 if (choices.size() == 1)
5775 choices[0]->GetDropDown().Invalidate();
5776
5777 wxWindowUpdateLocker noUpdates_scrolled_panel(this);
5778
5779 // delete UI item
5780 {
5781 const int last = p->combos_filament.size() - 1;
5782 auto sizer_filaments = this->p->sizer_filaments->GetItem(last % 2)->GetSizer();
5783 sizer_filaments->Remove(last / 2);
5784
5785 PlaterPresetComboBox* to_delete_combox = p->combos_filament[filament_id];
5786 (*p->combos_filament[last]).Destroy();
5787 p->combos_filament.pop_back();
5788
5789 // BBS: filament double columns
5790 auto sizer_filaments0 = this->p->sizer_filaments->GetItem((size_t) 0)->GetSizer();
5791 auto sizer_filaments1 = this->p->sizer_filaments->GetItem(1)->GetSizer();
5792 if (p->combos_filament.size() < 2) {
5793 sizer_filaments1->Clear();
5794 } else {
5795 size_t c0 = sizer_filaments0->GetChildren().GetCount();
5796 size_t c1 = sizer_filaments1->GetChildren().GetCount();
5797 if (c0 < c1)
5798 sizer_filaments1->Remove(c1 - 1);
5799 else if (c0 > c1)
5800 sizer_filaments1->AddStretchSpacer(1);
5801 }
5802 }
5803
5804 show_SEMM_buttons(); // ORCA
5805
5806 for (size_t idx = filament_id ; idx < p->combos_filament.size(); ++idx) {
5807 p->combos_filament[idx]->update();
5808 }
5809 }
5810
5814
5815 Layout();
5816 p->m_panel_filament_title->Refresh();
5819}

References combos_filament(), p, recalc_filament_scroll_sizes(), show_SEMM_buttons(), update_dynamic_filament_list(), update_filaments_area_height(), update_mixed_filament_list(), and update_ui_from_settings().

Referenced by Slic3r::GUI::Plater::on_filaments_delete().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ on_full_screen()

void Slic3r::GUI::Sidebar::on_full_screen ( IntEvent & e)
6217 {
6218 if (m_sna_dialog) { m_sna_dialog->on_full_screen(e); }
6219 if (m_fna_dialog) { m_fna_dialog->on_full_screen(e); }
6220}
FinishSyncAmsDialog * m_fna_dialog
Definition Plater.hpp:163
SyncNozzleAndAmsDialog * m_sna_dialog
Definition Plater.hpp:162

References m_fna_dialog, and m_sna_dialog.

◆ on_leave_image_printer_bed()

void Slic3r::GUI::Sidebar::on_leave_image_printer_bed ( wxMouseEvent & evt)
3661 {
3662 //auto pos_x = evt.GetX();
3663 //auto pos_y = evt.GetY();
3664 //auto rect = p->image_printer_bed->GetRect();
3665 //if ((pos_x <= 0 || pos_y <= 0 || pos_x >= rect.GetWidth()) && p->big_bed_image_popup) {
3666 if (p->big_bed_image_popup) {
3667 bool was_visible = p->big_bed_image_popup->IsShown();
3668 p->big_bed_image_popup->on_hide();
3669 if(!p->combo_printer_bed->is_drop_down() && was_visible)
3670 p->combo_printer_bed->SetFocus(); // set focus back to bed type combo. this prevents weird look if focus on other item
3671 }
3672}

References p, and Slic3r::GUI::wxMouseEvent.

Referenced by Sidebar().

Here is the caller graph for this function:

◆ on_size()

void Slic3r::GUI::Sidebar::on_size ( SimpleEvent & e)
6208 {
6209 if (m_sna_dialog && m_sna_dialog->IsShown()) {
6211 }
6212 if (m_fna_dialog && m_fna_dialog->IsShown()) {
6214 }
6215}
void pop_finsish_sync_ams_dialog()
Definition Plater.cpp:6793

References m_fna_dialog, m_sna_dialog, pop_finsish_sync_ams_dialog(), and pop_sync_nozzle_and_ams_dialog().

Here is the call graph for this function:

◆ operator=() [1/2]

Sidebar & Slic3r::GUI::Sidebar::operator= ( const Sidebar & )
delete

References Sidebar(), is_dark(), and Slic3r::GUI::wxMouseEvent.

Here is the call graph for this function:

◆ operator=() [2/2]

Sidebar & Slic3r::GUI::Sidebar::operator= ( Sidebar && )
delete

References Sidebar().

Here is the call graph for this function:

◆ pop_finsish_sync_ams_dialog()

void Slic3r::GUI::Sidebar::pop_finsish_sync_ams_dialog ( )
6794{
6795 wxTheApp->CallAfter([this]() {
6796 wxPoint small_btn_pt;
6797 wxSize small_btn_size;
6798 get_small_btn_sync_pos_size(small_btn_pt, small_btn_size);
6799
6800 FinishSyncAmsDialog::InputInfo temp_fsa_info;
6801 temp_fsa_info.dialog_pos.y = small_btn_pt.y;
6802 setup_dialog_position(temp_fsa_info);
6803 temp_fsa_info.ams_btn_pos = small_btn_pt + wxPoint(small_btn_size.x / 2, small_btn_size.y / 2);
6804 if (m_sna_dialog) { m_sna_dialog->on_hide(); }
6805 if (m_fna_dialog) {
6806 m_fna_dialog->Destroy();
6807 m_fna_dialog = nullptr;
6808 }
6809 m_fna_dialog = new FinishSyncAmsDialog(temp_fsa_info);
6810 m_fna_dialog->on_show();
6811 });
6812
6813}
void get_small_btn_sync_pos_size(wxPoint &pt, wxSize &size)
Definition Plater.cpp:6228
void setup_dialog_position(T &info)
Definition Plater.cpp:6732

References Slic3r::GUI::FinishSyncAmsDialog::InputInfo::ams_btn_pos, Slic3r::GUI::FinishSyncAmsDialog::InputInfo::dialog_pos, get_small_btn_sync_pos_size(), m_fna_dialog, m_sna_dialog, and Slic3r::GUI::setup_dialog_position().

Referenced by on_size(), and sync_ams_list().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pop_sync_nozzle_and_ams_dialog()

void Slic3r::GUI::Sidebar::pop_sync_nozzle_and_ams_dialog ( )
6762 {
6763 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " begin pop_sync_nozzle_and_ams_dialog";
6764 auto agent = wxGetApp().getAgent();
6765 if (!agent || agent->get_filament_sync_mode() == FilamentSyncMode::none) {
6766 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " filament synchronization is not supported; skipping dialog";
6767 return;
6768 }
6769 wxTheApp->CallAfter([this]() {
6770 SyncNozzleAndAmsDialog::InputInfo temp_na_info;
6771 wxPoint big_btn_pt;
6772 wxSize big_btn_size;
6773 wxGetApp().plater()->sidebar().get_big_btn_sync_pos_size(big_btn_pt, big_btn_size);
6774 temp_na_info.dialog_pos = big_btn_pt + wxPoint(big_btn_size.x, big_btn_size.y) + wxPoint(FromDIP(big_btn_size.x / 10.f - 5), FromDIP(big_btn_size.y / 10.f));
6775
6776 temp_na_info.dialog_pos.y += FromDIP(2);
6777 setup_dialog_position(temp_na_info);
6778
6779 wxPoint small_btn_pt;
6780 wxSize small_btn_size;
6781 get_small_btn_sync_pos_size(small_btn_pt, small_btn_size);
6782 temp_na_info.ams_btn_pos = small_btn_pt + wxPoint(small_btn_size.x / 2, small_btn_size.y / 2);
6783 if (m_fna_dialog) { m_fna_dialog->on_hide(); }
6784 if (m_sna_dialog) {
6785 m_sna_dialog->Destroy();
6786 m_sna_dialog = nullptr;
6787 }
6788 m_sna_dialog = new SyncNozzleAndAmsDialog(temp_na_info);
6789 m_sna_dialog->on_show();
6790 });
6791}
@ none
Filament synchronization not supported.
Definition IPrinterAgent.hpp:57

References Slic3r::GUI::SyncNozzleAndAmsDialog::InputInfo::ams_btn_pos, Slic3r::GUI::SyncNozzleAndAmsDialog::InputInfo::dialog_pos, get_small_btn_sync_pos_size(), m_fna_dialog, m_sna_dialog, Slic3r::none, and Slic3r::GUI::setup_dialog_position().

Referenced by deal_btn_sync(), and on_size().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ print_panel()

wxPanel * Slic3r::GUI::Sidebar::print_panel ( )
6661{
6662 return p->m_panel_print_content;
6663}

References p.

◆ printer_combox()

PlaterPresetComboBox * Slic3r::GUI::Sidebar::printer_combox ( )
6634{
6635 return p->combo_printer;
6636}

References p.

◆ recalc_filament_scroll_sizes()

void Slic3r::GUI::Sidebar::recalc_filament_scroll_sizes ( )
4295{
4296 if (!p->m_mixed_scroll_area || !p->m_mixed_scroll_area->GetSizer())
4297 return;
4298
4299 // Same preferred-row budget the physical list uses, so both lists cap consistently.
4300 auto left_sizer = p->sizer_filaments->GetItem((size_t) 0)->GetSizer();
4301 auto combo_sizer = left_sizer->GetItem((size_t) 0)->GetSizer();
4302 const int row_h = combo_sizer ? combo_sizer->GetSize().GetHeight() : 0;
4303 int preferred_rows = std::ceil(0.5 * std::stoi(wxGetApp().app_config->get("filaments_area_preferred_count")));
4304 const int max_h = (row_h > 0) ? preferred_rows * row_h : -1;
4305
4306 auto content_size = p->m_mixed_scroll_area->GetSizer()->GetMinSize();
4307 if (max_h > 0 && content_size.y > max_h) {
4308 p->m_mixed_scroll_area->SetMaxSize({-1, max_h});
4309 content_size.y = max_h;
4310 } else {
4311 p->m_mixed_scroll_area->SetMaxSize({-1, -1});
4312 }
4313 p->m_mixed_scroll_area->SetMinSize({0, content_size.y});
4314}

References p.

Referenced by on_filament_count_change(), on_filaments_delete(), and update_mixed_filament_list().

Here is the caller graph for this function:

◆ remove_all_mixed_filaments()

void Slic3r::GUI::Sidebar::remove_all_mixed_filaments ( )
5338{
5339 auto *plater = dynamic_cast<Plater *>(GetParent());
5340 if (plater == nullptr)
5341 return;
5342 const size_t count = plater->mixed_filament_config_indices().size();
5343 if (count == 0)
5344 return;
5345
5346 // Worth a confirmation: this drops filament slots the model may be painted with, and anything
5347 // painted in one falls back to a plain filament.
5348 MessageDialog dlg(this, format_wxstr(_L_PLURAL("Remove %1% mixed filament?", "Remove all %1% mixed filaments?", count), count), _L("Mixed Filament"),
5349 wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION);
5350 if (dlg.ShowModal() != wxID_YES)
5351 return;
5352
5353 // Back to front: delete_mixed_filament_at() indexes the list as it stands, so removing from the end
5354 // leaves the indices of everything still to go untouched.
5355 for (size_t i = count; i-- > 0;)
5357}
static unsigned int count
Definition AuxiliaryDataViewModel.cpp:246
wxString format_wxstr(const char *fmt, TArgs &&... args)
Definition format.hpp:22
#define _L_PLURAL(s, plural, n)
Definition I18N.hpp:96

References _L, _L_PLURAL, count, delete_mixed_filament_at(), Slic3r::GUI::format_wxstr(), Slic3r::GUI::plater(), and Slic3r::GUI::DPIAware< P >::ShowModal().

Referenced by Sidebar().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ remove_unused_filament_combos()

void Slic3r::GUI::Sidebar::remove_unused_filament_combos ( const size_t current_extruder_count)
3770{
3771 if (current_extruder_count >= p->combos_filament.size())
3772 return;
3773 while (p->combos_filament.size() > current_extruder_count) {
3774 const int last = p->combos_filament.size() - 1;
3775 auto sizer_filaments = this->p->sizer_filaments->GetItem(last % 2)->GetSizer();
3776 sizer_filaments->Remove(last / 2);
3777 (*p->combos_filament[last]).Destroy();
3778 p->combos_filament.pop_back();
3779 }
3780 // BBS: filament double columns
3781 auto sizer_filaments0 = this->p->sizer_filaments->GetItem((size_t)0)->GetSizer();
3782 auto sizer_filaments1 = this->p->sizer_filaments->GetItem(1)->GetSizer();
3783 if (current_extruder_count < 2) {
3784 sizer_filaments1->Clear();
3785 } else {
3786 size_t c0 = sizer_filaments0->GetChildren().GetCount();
3787 size_t c1 = sizer_filaments1->GetChildren().GetCount();
3788 if (c0 < c1)
3789 sizer_filaments1->Remove(c1 - 1);
3790 else if (c0 > c1)
3791 sizer_filaments1->AddStretchSpacer(1);
3792 }
3793}

References p.

Referenced by on_filament_count_change().

Here is the caller graph for this function:

◆ reset_bed_type_combox_choices()

bool Slic3r::GUI::Sidebar::reset_bed_type_combox_choices ( bool is_sidebar_init = false)
4231{
4232 if (!p->combo_printer_bed) {
4233 return false;
4234 }
4235
4236 auto pm = p->plater->get_curr_printer_model();
4237 if (pm) {
4238 if (m_cur_image_bed_type != pm->image_bed_type) {
4239 m_cur_image_bed_type = pm->image_bed_type;
4240 }
4241 }
4242 if (m_last_combo_bedtype_count != 0 && pm) {
4243 auto cur_count = (int) BedType::btCount - 1 - pm->not_support_bed_types.size();
4244 if (cur_count == m_last_combo_bedtype_count) {//no change
4245 return false;
4246 }
4247 }
4248 const ConfigOptionDef *bed_type_def = print_config_def.get("curr_bed_type");
4249 p->combo_printer_bed->Clear();
4250 m_cur_combox_bed_types.clear();
4251 if (pm &&bed_type_def && bed_type_def->enum_keys_map) {
4252 int index = 0;
4253 for (auto item : bed_type_def->enum_labels) {
4254 index++;
4255 bool find = std::find(pm->not_support_bed_types.begin(), pm->not_support_bed_types.end(), item) != pm->not_support_bed_types.end();
4256 if (find) {
4257 continue;
4258 }
4259 m_cur_combox_bed_types.emplace_back(BedType(index));//BedType //btPC =1
4260 p->combo_printer_bed->AppendString(_L(item));
4261 }
4262 }
4263 else {
4265 int index = 0;
4266 for (auto item : bed_type_def->enum_labels) {
4267 index++;
4268 m_cur_combox_bed_types.emplace_back(BedType(index)); // BedType //btPC =1
4269 p->combo_printer_bed->AppendString(_L(item));
4270 }
4271 }
4272 m_last_combo_bedtype_count = p->combo_printer_bed->GetCount();
4273 if (!is_sidebar_init) {
4274 p->plater->get_partplate_list().check_all_plate_local_bed_type(m_cur_combox_bed_types);
4275 }
4276 return true;
4277}
const ConfigOptionDef * get(const t_config_option_key &opt_key) const
Definition Config.hpp:2662
int m_last_combo_bedtype_count
Definition Plater.hpp:166
std::string m_cur_image_bed_type
Definition Plater.hpp:165
@ btCount
Definition PrintConfig.hpp:515
const PrintConfigDef print_config_def
Definition PrintConfig.cpp:10099
RaycastManager::TrItems::iterator find(RaycastManager::TrItems &items, const RaycastManager::TrKey &key)
Definition RaycastManager.cpp:298

References _L, Slic3r::btCount, Slic3r::ConfigOptionDef::enum_keys_map, Slic3r::ConfigOptionDef::enum_labels, m_cur_combox_bed_types, m_cur_image_bed_type, m_last_combo_bedtype_count, p, and Slic3r::print_config_def.

Referenced by Sidebar(), and update_all_preset_comboboxes().

Here is the caller graph for this function:

◆ reset_fila_switch()

void Slic3r::GUI::Sidebar::reset_fila_switch ( )
6176{
6177 p->update_extruder_separator_icon(false, false);
6178}

References p.

◆ scrolled_panel()

wxPanel * Slic3r::GUI::Sidebar::scrolled_panel ( )
6656{
6657 return p->scrolled;
6658}

References p.

◆ search()

void Slic3r::GUI::Sidebar::search ( )
5677{
5678 p->searcher.search();
5679}

References p.

◆ set_bed_type_accord_combox()

void Slic3r::GUI::Sidebar::set_bed_type_accord_combox ( BedType bed_type)
4220 {
4221 for (size_t i = 0; i < m_cur_combox_bed_types.size(); i++) {
4222 if (m_cur_combox_bed_types[i] == bed_type) {
4223 p->combo_printer_bed->SelectAndNotify(i);
4224 return;
4225 }
4226 }
4227 p->combo_printer_bed->SelectAndNotify(0);
4228}

References m_cur_combox_bed_types, and p.

Referenced by update_all_preset_comboboxes().

Here is the caller graph for this function:

◆ set_btn_label()

void Slic3r::GUI::Sidebar::set_btn_label ( const ActionButtonType btn_type,
const wxString & label ) const
15634{
15635 switch (btn_type)
15636 {
15637 case ActionButtonType::abReslice: p->btn_reslice->SetLabelText(label); break;
15638 case ActionButtonType::abExport: p->btn_export_gcode->SetLabelText(label); break;
15639 case ActionButtonType::abSendGCode: /*p->btn_send_gcode->SetLabelText(label);*/ break;
15640 }
15641}
@ abReslice
Definition Plater.cpp:603
@ abSendGCode
Definition Plater.cpp:605
@ abExport
Definition Plater.cpp:604

References Slic3r::GUI::abExport, Slic3r::GUI::abReslice, Slic3r::GUI::abSendGCode, and p.

◆ set_extruder_nozzle_count()

void Slic3r::GUI::Sidebar::set_extruder_nozzle_count ( int extruder_id,
int nozzle_count )
6608{
6609 if (!p)
6610 return;
6611 if (extruder_id == 0) {
6612 p->left_extruder->SetCount(nozzle_count);
6613 p->single_extruder->SetCount(nozzle_count);
6614 } else if (extruder_id == 1) {
6615 p->right_extruder->SetCount(nozzle_count);
6616 }
6617}

References p.

◆ set_flushing_volume_warning()

void Slic3r::GUI::Sidebar::set_flushing_volume_warning ( const bool flushing_volume_modify)
6688{
6689 if(flushing_volume_modify){
6690 p->m_flushing_volume_btn->SetStyle(ButtonStyle::Regular, ButtonType::Compact);
6691 p->m_flushing_volume_btn->SetBorderColor(wxColour("#FF6F00"));
6692 }
6693 else
6694 p->m_flushing_volume_btn->SetStyle(ButtonStyle::Confirm, ButtonType::Compact);
6695}
@ Regular
Definition Button.hpp:24

References Compact, Confirm, p, and Regular.

Referenced by Sidebar(), auto_calc_flushing_volumes(), Slic3r::GUI::Plater::load_project(), msw_rescale(), and sys_color_changed().

Here is the caller graph for this function:

◆ set_need_auto_sync_after_connect_printer()

void Slic3r::GUI::Sidebar::set_need_auto_sync_after_connect_printer ( bool need_auto_sync)
inline
323{ m_need_auto_sync_after_connect_printer = need_auto_sync; }

References m_need_auto_sync_after_connect_printer.

Referenced by Slic3r::GUI::MonitorPanel::on_machine_selected(), and Slic3r::GUI::MainFrame::update_layout().

Here is the caller graph for this function:

◆ settings_index()

Search::SettingsIndex & Slic3r::GUI::Sidebar::settings_index ( )
6918{
6919 return p->searcher.index();
6920}

References p.

◆ should_show_SEMM_buttons()

bool Slic3r::GUI::Sidebar::should_show_SEMM_buttons ( )
static
6560{
6561 PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
6562 bool is_bbl_vendor = preset_bundle.is_bbl_vendor();
6563 auto cfg = preset_bundle.printers.get_edited_preset().config;
6564
6565 return cfg.opt_bool("single_extruder_multi_material") || is_bbl_vendor;
6566}

References Slic3r::Preset::config, Slic3r::PresetCollection::get_edited_preset(), Slic3r::PresetBundle::is_bbl_vendor(), Slic3r::DynamicConfig::opt_bool(), and Slic3r::PresetBundle::printers.

Referenced by Slic3r::GUI::MenuFactory::create_filament_action_menu(), init_filament_combo(), Slic3r::GUI::GLCanvas3D::is_flushing_matrix_error(), and show_SEMM_buttons().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ show_eject()

bool Slic3r::GUI::Sidebar::show_eject ( bool show) const

◆ show_export()

bool Slic3r::GUI::Sidebar::show_export ( bool show) const
6709{ return p->btn_export_gcode->Show(show); }

References p.

◆ show_export_removable()

bool Slic3r::GUI::Sidebar::show_export_removable ( bool show) const
6711{ return p->btn_export_gcode_removable->Show(show); }

References p.

◆ show_mode_sizer()

void Slic3r::GUI::Sidebar::show_mode_sizer ( bool show)
6858{
6859 //p->mode_sizer->Show(show);
6860}

◆ show_object_list()

bool Slic3r::GUI::Sidebar::show_object_list ( bool show) const
6877{
6878 p->m_search_bar->Show(show);
6879 if (!p->m_object_list->Show(show))
6880 return false;
6881 if (!show)
6882 p->object_layers->Show(false);
6883 else
6884 p->m_object_list->part_selection_changed();
6885 p->scrolled->Layout();
6886 return true;
6887}

References p.

◆ show_reslice()

bool Slic3r::GUI::Sidebar::show_reslice ( bool show) const
6708{ return p->btn_reslice->Show(show); }

References p.

◆ show_SEMM_buttons()

void Slic3r::GUI::Sidebar::show_SEMM_buttons ( )
6569{
6570 // ORCA
6571 if (!p || p->combos_filament.empty() || !p->m_bpButton_add_filament || !p->m_bpButton_del_filament || !p->m_flushing_volume_btn)
6572 return;
6573
6574 bool is_multi_material = p->combos_filament.size() > 1;
6575 bool single_or_bbl = should_show_SEMM_buttons();
6576 bool is_single = single_or_bbl && !is_multi_material; // SINGLE EXTRUDER / BBL WITH 1 MATERIAL
6577 bool is_multi = single_or_bbl && is_multi_material; // MULTI MATERIAL WITH SINGLE EXTRUDER
6578 bool is_fixed = !is_single && !is_multi; // MULTI EXTRUDER / TOOLCHANGER / IDEX WITH FIXED MATERIAL
6579
6580 p->m_bpButton_add_filament->Show(single_or_bbl);
6581 p->m_bpButton_del_filament->Show(is_multi);
6582 p->m_flushing_volume_btn->Show( is_multi);
6583
6584 if (is_multi) {
6585 for (auto &c : p->combos_filament)
6586 c->edit_btn->SetBitmap_("menu_filament");
6587 }
6588 else if (is_single || is_fixed) {
6589 for (auto &c : p->combos_filament)
6590 c->edit_btn->SetBitmap_("edit");
6591 }
6592
6593 Layout();
6594}

References p, and should_show_SEMM_buttons().

Referenced by on_filament_count_change(), on_filaments_delete(), and update_all_preset_comboboxes().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ show_send()

bool Slic3r::GUI::Sidebar::show_send ( bool show) const
6710{ return p->btn_send_gcode->Show(show); }

References p.

◆ sync_ams_list()

void Slic3r::GUI::Sidebar::sync_ams_list ( bool is_from_big_sync_btn = false)
6305{
6306 wxBusyCursor cursor;
6307 // Force load ams list
6308 auto obj = wxGetApp().getDeviceManager()->get_selected_machine();
6309 if (!obj)
6310 return;
6311 GUI::wxGetApp().sidebar().load_ams_list(obj);
6312
6313 auto & list = wxGetApp().preset_bundle->filament_ams_list;
6314 if (list.empty()) {
6315 auto printer_name = p->plater->get_selected_printer_name_in_combox();
6316 p->plater->pop_warning_and_go_to_device_page(printer_name, Plater::PrinterWarningType::NOT_CONNECTED, _L("Sync printer information"));
6317 return;
6318 }
6319 bool exist_at_list_one_filament =false;
6320 for (auto &cur : list) {
6321 auto temp_config = cur.second;
6322 auto filament_type = temp_config.opt_string("filament_type", 0u);
6323 auto filament_color = temp_config.opt_string("filament_colour", 0u);
6324 if (!filament_type.empty() || temp_config.opt_bool("filament_exist", 0u)) {
6325 exist_at_list_one_filament = true;
6326 break;
6327 }
6328 }
6329 if (!exist_at_list_one_filament) {
6330 if (!obj->is_filament_installed()) {
6331 p->plater->pop_warning_and_go_to_device_page("", Plater::PrinterWarningType::UNINSTALL_FILAMENT, _L("Sync printer information"));
6332 return;
6333 }
6334 p->plater->pop_warning_and_go_to_device_page("", Plater::PrinterWarningType::EMPTY_FILAMENT, _L("Sync printer information"));
6335 return;
6336 }
6337 if (!wxGetApp().plater()->is_same_printer_for_connected_and_selected()) {
6338 return;
6339 }
6340 std::string ams_filament_ids = wxGetApp().app_config->get("ams_filament_ids", p->ams_list_device);
6341 std::vector<std::string> list2;
6342 if (!ams_filament_ids.empty()) {
6343 boost::algorithm::split(list2, ams_filament_ids, boost::algorithm::is_any_of(","));
6344 }
6345 wxGetApp().plater()->update_all_plate_thumbnails(true);//preview thumbnail for sync_dlg
6346 SyncAmsInfoDialog::SyncInfo temp_info;
6347 temp_info.use_dialog_pos = false;
6348 temp_info.cancel_text_to_later = is_from_big_sync_btn;
6349 if (m_sync_dlg == nullptr) {
6350 m_sync_dlg = new SyncAmsInfoDialog(this, temp_info);
6351 } else {
6352 m_sync_dlg->set_info(temp_info);
6353 }
6354 int dlg_res{(int) wxID_CANCEL};
6355 if (m_sync_dlg->is_need_show()) {
6356 m_sync_dlg->deal_only_exist_ext_spool(obj);
6357 if (m_sync_dlg->is_dirty_filament()) {
6358 wxGetApp().get_tab(Preset::TYPE_FILAMENT)->select_preset(wxGetApp().preset_bundle->filament_presets[0], false, "", false, true);
6359 wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config);
6361 }
6362 m_sync_dlg->set_check_dirty_fialment(false);
6363 dlg_res = m_sync_dlg->ShowModal();
6364 } else {
6365 dlg_res =(int) wxID_YES;
6366 }
6367 if (dlg_res == wxID_CANCEL)
6368 return;
6369 auto sync_result = m_sync_dlg->get_result();
6370 if (!sync_result.is_same_printer) {
6371 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "check error: sync_result.is_same_printer value is false";
6372 return;
6373 }
6374 list2.resize(list.size());
6375 auto iter = list.begin();
6376 for (int i = 0; i < list.size(); ++i, ++iter) {
6377 auto & ams = iter->second;
6378 auto filament_id = ams.opt_string("filament_id", 0u);
6379 ams.set_key_value("filament_changed", new ConfigOptionBool{dlg_res == wxID_YES || list2[i] != filament_id});
6380 list2[i] = filament_id;
6381 }
6382
6383 // BBS:Record consumables information before synchronization
6384 std::vector<std::string> color_before_sync;
6385 std::vector<bool> is_support_before;
6386 DynamicPrintConfig& project_config = wxGetApp().preset_bundle->project_config;
6387 ConfigOptionStrings* color_opt = project_config.option<ConfigOptionStrings>("filament_colour");
6388 for (int i = 0; i < p->combos_filament.size(); ++i) {
6389 is_support_before.push_back(is_support_filament(i));
6390 color_before_sync.push_back(color_opt->values[i]);
6391 }
6392 MergeFilamentInfo merge_info;
6393 std::vector<std::pair<DynamicPrintConfig *,std::string>> unknowns;
6394 auto enable_append = wxGetApp().app_config->get_bool("enable_append_color_by_sync_ams");
6395 auto sync_color_only = wxGetApp().app_config->get("sync_ams_filament_mode") == "1";
6396 auto n = wxGetApp().preset_bundle->sync_ams_list(unknowns, !sync_result.direct_sync, sync_result.sync_maps, enable_append, merge_info, sync_color_only);
6397 wxString detail;
6398 for (auto & uk : unknowns) {
6399 auto tray_name = uk.first->opt_string("tray_name", 0u);
6400 auto filament_type = uk.first->opt_string("filament_type", 0u);
6401 detail += from_u8("\n- " + tray_name + "(" + filament_type + ") ") + _L(uk.second);
6402 }
6403 if (n == 0) {
6404 MessageDialog dlg(this,
6405 _L("There are no compatible filaments, and sync is not performed.") + detail,
6406 _L("Sync filaments with AMS"), wxOK);
6407 dlg.ShowModal();
6408 return;
6409 }
6410 // Replace unknown filament IDs with the resolved preset's filament_id
6411 auto &filaments = wxGetApp().preset_bundle->filaments;
6412 auto &filament_presets = wxGetApp().preset_bundle->filament_presets;
6413 for (size_t i = 0; i < list2.size() && i < filament_presets.size(); ++i) {
6414 if (list2[i] == UNKNOWN_FILAMENT_ID) {
6415 const Preset *resolved = filaments.find_preset(filament_presets[i]);
6416 if (resolved)
6417 list2[i] = resolved->filament_id;
6418 }
6419 }
6420 ams_filament_ids = boost::algorithm::join(list2, ",");
6421 wxGetApp().app_config ->set("ams_filament_ids", p->ams_list_device, ams_filament_ids);
6422 if (!unknowns.empty()) {
6423 MessageDialog dlg(this,
6424 _L("There are some unknown or incompatible filaments mapped to generic preset.\nPlease update Orca Slicer or restart Orca Slicer to check if there is an update to system presets.") + detail,
6425 _L("Sync filaments with AMS"), wxOK);
6426 dlg.ShowModal();
6427 }
6428 if (!sync_color_only) {
6429 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "on_filament_count_change";
6430 wxGetApp().plater()->on_filament_count_change(n);
6431 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "finish on_filament_count_change";
6432 }
6433 for (auto& c : p->combos_filament)
6434 c->update();
6435 // Expand filament list
6437
6438 // BBS:Synchronized consumables information
6439 // auto calculation of flushing volumes
6440 for (int i = 0; i < p->combos_filament.size(); ++i) {
6441 if (i >= color_before_sync.size()) {
6443 }
6444 else if(color_before_sync[i] != color_opt->values[i] && wxGetApp().app_config->get("auto_calculate_flush") != "disabled"){
6446 }
6447 else if(is_support_filament(i) !=is_support_before[i] && wxGetApp().app_config->get("auto_calculate_flush") == "all"){
6449 }
6450 }
6451 Layout();
6452
6453 // For full sync, preset selection/list update may rebuild combo widgets.
6454 // For color-only, keep current presets untouched and refresh colors only.
6455 if (!sync_color_only) {
6456 wxGetApp().get_tab(Preset::TYPE_FILAMENT)->select_preset(wxGetApp().preset_bundle->filament_presets[0]);
6457 wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config);
6459 } else {
6460 wxGetApp().plater()->update_filament_colors_in_full_config();
6461 for (auto &c : p->combos_filament)
6462 c->update();
6465 }
6466
6467 auto badge_combox_filament = [sync_color_only](PlaterPresetComboBox *c) {
6468 auto tip = sync_color_only ? _L("Only filament color information has been synchronized from printer.") :
6469 _L("Filament type and color information have been synchronized, but slot information is not included.");
6470 c->SetToolTip(tip);
6471 c->set_sync_badge(true);
6472 };
6473 { // badge ams filament
6475 if (sync_result.direct_sync) {
6476 // A placeholder contributes a preserved project filament to the
6477 // overwrite result, but it is not AMS-sourced and must not get a
6478 // sync badge. Non-placeholder empty trays are omitted entirely.
6479 size_t combo_index = 0;
6480 for (const auto &entry : wxGetApp().preset_bundle->filament_ams_list) {
6481 const auto &tray = entry.second;
6482 const bool has_filament = !tray.opt_string("filament_id", 0u).empty();
6483 const bool is_placeholder = tray.has("filament_slot_placeholder") &&
6484 tray.opt_bool("filament_slot_placeholder", 0u);
6485 if (!has_filament && !is_placeholder) {
6486 continue;
6487 }
6488 if (combo_index >= p->combos_filament.size()) {
6489 break;
6490 }
6491 if (is_placeholder) {
6492 p->combos_filament[combo_index]->set_sync_badge(false);
6493 } else {
6494 badge_combox_filament(p->combos_filament[combo_index]);
6495 }
6496 ++combo_index;
6497 }
6498 }
6499 }
6500 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "prepare enable_merge_color_by_sync_ams";
6501 if (!merge_info.is_empty() && wxGetApp().app_config->get_bool("enable_merge_color_by_sync_ams")) { // merge same color and preset filament//use same ams
6502 auto reduce_index = [](MergeFilamentInfo &merge_info,int value) {
6503 for (size_t i = 0; i < merge_info.merges.size(); i++) {
6504 auto &cur = merge_info.merges[i];
6505 for (size_t j = 0; j < cur.size(); j++) {
6506 if (value < cur[j]) {
6507 cur[j] = cur[j] - 1;
6508 }
6509 }
6510 }
6511 };
6512 std::vector<bool> sync_ams_badges;
6513 for (auto iter : sync_result.sync_maps) {
6514 sync_ams_badges.push_back(false);
6515 if (iter.second.ams_id == "" || iter.second.slot_id == "") {
6516 continue;
6517 }
6518 sync_ams_badges.back() = true;
6519 }
6520
6521 for (size_t i = 0; i < merge_info.merges.size(); i++) {
6522 auto& cur = merge_info.merges[i];
6523 for (int j = cur.size() -1; j >= 1 ; j--) {
6524 auto last_index = cur[j];
6525 change_filament(last_index, cur[0]);
6526 cur.erase(cur.begin() + j);
6527 sync_ams_badges.erase(sync_ams_badges.begin() + last_index);
6528 reduce_index(merge_info, last_index);
6529 }
6530 }
6531 for (size_t i = 0; i < sync_ams_badges.size(); i++) {
6532 if (sync_ams_badges[i] == true) {
6533 if (i < p->combos_filament.size()) {
6534 auto &c = p->combos_filament[i];
6535 badge_combox_filament(c);
6536 } else {
6537 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << __LINE__ << "check error: p->combos_filament array out of bound";
6538 }
6539 }
6540 }
6541 } else {
6542 for (auto iter : sync_result.sync_maps) {
6543 if (iter.second.ams_id == "" || iter.second.slot_id == "") {
6544 continue;
6545 }
6546 auto temp_index = iter.first;
6547 if (temp_index < p->combos_filament.size() && temp_index >= 0) {
6548 auto &c = p->combos_filament[temp_index];
6549 badge_combox_filament(c);
6550 }
6551 }
6552 }
6553 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "begin pop_finsish_sync_ams_dialog";
6555 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "finish pop_finsish_sync_ams_dialog";
6556}
#define UNKNOWN_FILAMENT_ID
Definition Preset.hpp:72
void update_filament_colors()
Definition GUI_ObjectList.cpp:1088
@ UNINSTALL_FILAMENT
Definition Plater.hpp:692
@ EMPTY_FILAMENT
Definition Plater.hpp:693
@ NOT_CONNECTED
Definition Plater.hpp:690
SyncAmsInfoDialog * m_sync_dlg
Definition Plater.hpp:168
void clear_combos_filament_badge()
Definition Plater.cpp:6896
void change_filament(size_t from_id, size_t to_id)
Definition Plater.cpp:5892
ObjectList * obj_list()
Definition Plater.cpp:6638
wxString from_u8(const std::string &str)
Definition GUI.cpp:544
zaa_minimize_perimeter_height filament_type((ConfigOptionBools, filament_soluble))((ConfigOptionStrings

References _L, auto_calc_flushing_volumes(), Slic3r::GUI::SyncAmsInfoDialog::SyncInfo::cancel_text_to_later, change_filament(), clear_combos_filament_badge(), combos_filament(), Slic3r::GUI::Plater::EMPTY_FILAMENT, Slic3r::Preset::filament_id, Slic3r::filament_type(), Slic3r::GUI::from_u8(), Slic3r::MergeFilamentInfo::is_empty(), Slic3r::GUI::is_support_filament(), m_sync_dlg, Slic3r::MergeFilamentInfo::merges, Slic3r::GUI::Plater::NOT_CONNECTED, obj_list(), Slic3r::ConfigBase::option(), p, Slic3r::GUI::plater(), pop_finsish_sync_ams_dialog(), Slic3r::GUI::DPIAware< P >::ShowModal(), Slic3r::Preset::TYPE_FILAMENT, Slic3r::GUI::Plater::UNINSTALL_FILAMENT, UNKNOWN_FILAMENT_ID, update_dynamic_filament_list(), Slic3r::GUI::ObjectList::update_filament_colors(), update_filaments_area_height(), Slic3r::GUI::SyncAmsInfoDialog::SyncInfo::use_dialog_pos, and Slic3r::ConfigOptionVector< T >::values.

Referenced by Sidebar().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sync_extruder_list()

bool Slic3r::GUI::Sidebar::sync_extruder_list ( )
6165{
6166 bool only_external_material;
6167 return p->sync_extruder_list(only_external_material);
6168}

References p.

Referenced by Slic3r::GUI::MainFrame::update_layout().

Here is the caller graph for this function:

◆ sys_color_changed()

void Slic3r::GUI::Sidebar::sys_color_changed ( )
5591{
5592 wxWindowUpdateLocker noUpdates(this);
5593
5594#if 0
5595 for (wxWindow* win : std::vector<wxWindow*>{ this, p->sliced_info->GetStaticBox(), p->object_info->GetStaticBox(), p->btn_reslice, p->btn_export_gcode })
5596 wxGetApp().UpdateDarkUI(win);
5597 p->object_info->msw_rescale();
5598
5599 for (wxWindow* win : std::vector<wxWindow*>{ p->scrolled, p->presets_panel })
5600 wxGetApp().UpdateAllStaticTextDarkUI(win);
5601#endif
5602 //p->btn_sync_printer->SetIcon("printer_sync");
5603 p->m_printer_bbl_sync->msw_rescale();
5604 p->m_printer_connect->msw_rescale();
5605 // for (wxWindow* btn : std::vector<wxWindow*>{ p->btn_reslice, p->btn_export_gcode })
5606 // wxGetApp().UpdateDarkUI(btn, true);
5607 p->m_printer_icon->msw_rescale();
5608 p->m_printer_setting->msw_rescale();
5609 p->m_printer_setting->msw_rescale();
5610 p->m_filament_icon->msw_rescale();
5611 p->m_bpButton_add_filament->msw_rescale();
5612 p->m_bpButton_del_filament->msw_rescale();
5613 p->m_bpButton_ams_filament->msw_rescale();
5614 p->m_bpButton_set_filament->msw_rescale();
5615 p->m_purge_mode_btn->Rescale();
5616 p->m_flushing_volume_btn->Rescale();
5617 set_flushing_volume_warning(is_flush_config_modified()); // ORCA reapply appearance
5618
5619 // BBS
5620#if 0
5621 if (p->mode_sizer)
5622 p->mode_sizer->msw_rescale();
5623 p->frequently_changed_parameters->sys_color_changed();
5624#endif
5625 p->object_settings->sys_color_changed();
5626
5627 //BBS: remove print related combos
5628#if 0
5629 for (PlaterPresetComboBox* combo : std::vector<PlaterPresetComboBox*>{ p->combo_print,
5630 p->combo_sla_print,
5631 p->combo_sla_material,
5632 p->combo_printer })
5633 combo->sys_color_changed();
5634#endif
5635 p->combo_printer->sys_color_changed();
5636 for (PlaterPresetComboBox* combo : p->combos_filament)
5637 combo->sys_color_changed();
5638
5639 if (p->big_bed_image_popup) // ORCA
5640 p->big_bed_image_popup->sys_color_changed();
5641
5642 p->btn_edit_printer->msw_rescale();
5643 p->image_printer->SetSize(FromDIP(PRINTER_THUMBNAIL_SIZE));
5644 p->image_printer_bed->SetSize(FromDIP(PRINTER_THUMBNAIL_SIZE));
5645
5646 for (ExtruderGroup *ext : {p->left_extruder, p->right_extruder, p->single_extruder})
5647 if (ext)
5648 ext->sys_color_changed();
5649
5650 // call a kill focus event to ensure new colors applied
5651 for (ComboBox* combo : std::vector<ComboBox*>{p->combo_printer, p->combo_nozzle_dia, p->combo_printer_bed}){
5652 wxFocusEvent fakeEvent(wxEVT_KILL_FOCUS);
5653 fakeEvent.SetEventObject(combo);
5654 combo->HandleWindowEvent(fakeEvent);
5655 }
5656
5657 // BBS
5660 // BBS
5661 //p->object_manipulation->sys_color_changed();
5662
5663 // btn...->msw_rescale() updates icon on button, so use it
5664 //p->btn_send_gcode->msw_rescale();
5665// p->btn_eject_device->msw_rescale();
5666 //p->btn_export_gcode_removable->msw_rescale();
5667
5668 p->scrolled->Layout();
5669
5670 // Mixed rows are custom-drawn, so they need rebuilding for the new theme colours.
5672
5673 p->searcher.dlg_sys_color_changed();
5674}
void sys_color_changed()
Definition GUI_ObjectLayers.cpp:317
void sys_color_changed()
Definition GUI_ObjectList.cpp:6600
ObjectLayers * obj_layers()
Definition Plater.cpp:6650

References is_flush_config_modified(), obj_layers(), obj_list(), p, PRINTER_THUMBNAIL_SIZE, set_flushing_volume_warning(), Slic3r::GUI::ObjectLayers::sys_color_changed(), Slic3r::GUI::ObjectList::sys_color_changed(), Slic3r::GUI::PlaterPresetComboBox::sys_color_changed(), and update_mixed_filament_list().

Here is the call graph for this function:

◆ udpate_combos_filament_badge()

void Slic3r::GUI::Sidebar::udpate_combos_filament_badge ( )
6904 {
6905 auto &combos_filament = p->combos_filament;
6906 for (auto &c : combos_filament) {
6907 c->update_badge_according_flag();
6908 }
6909
6910}

References combos_filament(), and p.

Here is the call graph for this function:

◆ update_all_preset_comboboxes()

void Slic3r::GUI::Sidebar::update_all_preset_comboboxes ( )
3796{
3797 PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
3798 const auto print_tech = preset_bundle.printers.get_edited_preset().printer_technology();
3799
3800 bool is_bbl_vendor = preset_bundle.is_bbl_vendor();
3801
3802 auto p_mainframe = wxGetApp().mainframe;
3803 auto cfg = preset_bundle.printers.get_edited_preset().config;
3804 const bool use_printer_agents = wxGetApp().app_config->get_bool("use_printer_agents");
3805 const bool use_native_device_tab = preset_bundle.use_bbl_device_tab() || use_printer_agents;
3806
3807 if (preset_bundle.use_bbl_network()) {
3808 //only show connection button for not-BBL printer
3809 //p->btn_connect_printer->Hide();
3810 p->m_printer_connect->Hide();
3811 //only show sync-ams button for BBL printer
3812 p->m_bpButton_ams_filament->Show();
3813 //update print button default value for bbl or third-party printer
3814 p_mainframe->set_print_button_to_default(MainFrame::PrintSelectType::ePrintPlate);
3815 } else {
3816 //p->btn_connect_printer->Show();
3817 // ORCA: hide the physical-printer connection button when printer agents are enabled
3818 p->m_printer_connect->Show(!use_printer_agents);
3819
3820 // ORCA: show/hide sync-ams button based on filament sync mode
3821 auto agent = wxGetApp().getAgent();
3822 if (agent && agent->get_filament_sync_mode() != FilamentSyncMode::none)
3823 p->m_bpButton_ams_filament->Show();
3824 else
3825 p->m_bpButton_ams_filament->Hide();
3826
3827 // Orca: with "Support 3MF as gcode" (use_3mf) the local export is a .gcode.3mf bundle, so when no
3828 // printer host/IP is configured the default action is "Export plate sliced file" (mirrors the
3829 // print dropdown) instead of "Export G-code file".
3830 auto print_btn_type = cfg.opt_bool("use_3mf") ? MainFrame::PrintSelectType::eExportSlicedFile
3832 wxString url = from_u8(PrintHost::get_print_host_webui(&cfg));
3833 wxString apikey;
3834 if(url.empty())
3835 url = file_url_from_path(boost::filesystem::path(resources_dir()) / "web/orca/missing_connection.html");
3836 else {
3837 const auto host_type = cfg.option<ConfigOptionEnum<PrintHostType>>("host_type")->value;
3838 if (cfg.has("printhost_apikey") && (host_type != htSimplyPrint))
3839 apikey = cfg.opt_string("printhost_apikey");
3840 print_btn_type = (preset_bundle.is_bbl_vendor() || wxGetApp().app_config->get_bool("use_printer_agents"))
3843 }
3844
3845 if (use_printer_agents)
3846 p_mainframe->load_printer_url();
3847 else if (!use_native_device_tab)
3848 p_mainframe->load_printer_url(url, apikey);
3849
3850
3851 p_mainframe->set_print_button_to_default(print_btn_type);
3852
3853 }
3854
3855 if (cfg.opt_bool("pellet_modded_printer")) {
3856 p->m_staticText_filament_settings->SetLabel(_L("Pellets"));
3857 p->m_filament_icon->SetBitmap_("pellets");
3858 } else {
3859 p->m_staticText_filament_settings->SetLabel(_L("Filament"));
3860 p->m_filament_icon->SetBitmap_("filament");
3861 }
3862
3864
3865 //p->m_staticText_filament_settings->Update();
3866
3867 if (is_bbl_vendor || cfg.opt_bool("support_multi_bed_types")) {
3868 p->combo_printer_bed->Enable();
3869 // Orca: don't update bed type if loading project
3870 if (!p->plater->is_loading_project()) {
3871 bool has_changed = reset_bed_type_combox_choices();
3872 bool flag = m_begin_sync_printer_status && !has_changed;
3873 if (!(flag)) {
3874 auto str_bed_type = wxGetApp().app_config->get_printer_setting(wxGetApp().preset_bundle->printers.get_selected_preset_name(),
3875 "curr_bed_type");
3876 if (!str_bed_type.empty()) {
3877 int bed_type_value = atoi(str_bed_type.c_str());
3878 if (bed_type_value <= 0 || bed_type_value >= btCount) {
3879 bed_type_value = preset_bundle.printers.get_edited_preset().get_default_bed_type(&preset_bundle);
3880 }
3881
3882 set_bed_type_accord_combox((BedType) bed_type_value);
3883 } else {
3884 BedType bed_type = preset_bundle.printers.get_edited_preset().get_default_bed_type(&preset_bundle);
3886 }
3887 } else {
3888 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":no need reset_bed_type_combox_choices";
3889 }
3890 }
3891 } else {
3892 // m_bed_type_list->SelectAndNotify(btPEI - 1);
3893 BedType bed_type = preset_bundle.printers.get_edited_preset().get_default_bed_type(&preset_bundle);
3895 p->combo_printer_bed->Disable();
3896 }
3897
3898 // ORCA Hide plate selector if not supported by printer
3899 p->panel_printer_bed->Show(is_bbl_vendor || cfg.opt_bool("support_multi_bed_types"));
3900
3901 // Update the print choosers to only contain the compatible presets, update the dirty flags.
3902 //BBS
3903
3904 // Update the printer choosers, update the dirty flags.
3905 //p->combo_printer->update();
3906 // Update the filament choosers to only contain the compatible presets, update the color preview,
3907 // update the dirty flags.
3908 if (print_tech == ptFFF) {
3909 for (PlaterPresetComboBox* cb : p->combos_filament)
3910 cb->update();
3911 }
3912
3913 if (p->combo_printer) {
3914 p->combo_printer->update();
3916 }
3917
3918 p_mainframe->show_device(use_native_device_tab);
3919 p_mainframe->m_tabpanel->SetSelection(p_mainframe->m_tabpanel->GetSelection());
3920}
@ eSendGcode
Definition MainFrame.hpp:350
@ eExportSlicedFile
Definition MainFrame.hpp:348
@ ePrintPlate
Definition MainFrame.hpp:347
@ eExportGcode
Definition MainFrame.hpp:349
void set_bed_type_accord_combox(BedType bed_type)
Definition Plater.cpp:4220
static std::string get_print_host_webui(DynamicPrintConfig *config)
Definition PrintHost.cpp:98
wxString file_url_from_path(const boost::filesystem::path &path)
Definition GUI.cpp:569
@ ptFFF
Definition Config.hpp:231
@ htSimplyPrint
Definition PrintConfig.hpp:119
const std::string & resources_dir()
Definition utils.cpp:296

References _L, Slic3r::btCount, Slic3r::Preset::config, Slic3r::GUI::MainFrame::eExportGcode, Slic3r::GUI::MainFrame::eExportSlicedFile, Slic3r::GUI::MainFrame::ePrintPlate, Slic3r::GUI::MainFrame::eSendGcode, Slic3r::GUI::file_url_from_path(), Slic3r::GUI::from_u8(), Slic3r::Preset::get_default_bed_type(), Slic3r::PresetCollection::get_edited_preset(), Slic3r::PrintHost::get_print_host_webui(), Slic3r::PresetCollection::get_selected_preset_name(), Slic3r::htSimplyPrint, Slic3r::PresetBundle::is_bbl_vendor(), m_begin_sync_printer_status, Slic3r::none, p, Slic3r::Preset::printer_technology(), Slic3r::PresetBundle::printers, Slic3r::ptFFF, reset_bed_type_combox_choices(), Slic3r::resources_dir(), set_bed_type_accord_combox(), show_SEMM_buttons(), Slic3r::GUI::PlaterPresetComboBox::update(), update_printer_thumbnail(), Slic3r::PresetBundle::use_bbl_device_tab(), and Slic3r::PresetBundle::use_bbl_network().

Referenced by create_printer_preset(), Slic3r::GUI::Plater::normalize_bed_types(), and update_presets().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_dynamic_filament_list()

void Slic3r::GUI::Sidebar::update_dynamic_filament_list ( )
6628{
6631}
void update(bool force=false)
Definition Plater.cpp:1375

References Slic3r::GUI::dynamic_filament_list, and Slic3r::GUI::dynamic_physical_filament_list.

Referenced by Slic3r::anonymous_namespace{PluginHostPresets.cpp}::bind_filament_target(), edit_mixed_filament(), on_filament_count_change(), on_filaments_delete(), sync_ams_list(), and update_presets().

Here is the caller graph for this function:

◆ update_filaments_area_height()

void Slic3r::GUI::Sidebar::update_filaments_area_height ( )
5450{
5451 // ORCA use a height with user preference
5452 auto left_sizer = p->sizer_filaments->GetItem((size_t) 0)->GetSizer();
5453 auto combo_sizer = left_sizer->GetItem((size_t) 0)->GetSizer();
5454 int preferred_rows = std::ceil(0.5 * std::stoi(wxGetApp().app_config->get("filaments_area_preferred_count")));
5455 auto height_with_borders = combo_sizer->GetSize().GetHeight(); // gets height from sizer instead static numbers
5456 p->m_panel_filament_content->SetMaxSize(wxSize{-1, preferred_rows * height_with_borders});
5457
5458 // fixes wxScrolledWindow not shrinks its height to content size
5459 auto min_size = p->m_panel_filament_content->GetSizer()->GetMinSize();
5460 if (min_size.y > p->m_panel_filament_content->GetMaxHeight())
5461 min_size.y = p->m_panel_filament_content->GetMaxHeight();
5462 p->m_panel_filament_content->SetMinSize({-1, min_size.y});
5463
5465}

References p, and update_filaments_counter().

Referenced by Sidebar(), msw_rescale(), on_filament_count_change(), on_filaments_delete(), and sync_ams_list().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_filaments_counter()

void Slic3r::GUI::Sidebar::update_filaments_counter ( bool force_layout = false)
5469{
5470 int current_count = p->combos_filament.size();
5471 int preferred_count = std::stoi(wxGetApp().app_config->get("filaments_area_preferred_count"));
5472 bool isShown = p->m_panel_filament_content->IsShown();
5473 auto counter = p->m_staticText_filament_count;
5474
5475 counter->SetLabel("(" + std::to_string(current_count) + ")"); // update counter on every change
5476 if(current_count > preferred_count || !isShown)
5477 counter->Show();
5478 else if (isShown) // hide when list is visible and short enough
5479 counter->Hide();
5480
5481 if(force_layout)
5482 m_scrolled_sizer->Layout();
5483}

References m_scrolled_sizer, and p.

Referenced by Sidebar(), and update_filaments_area_height().

Here is the caller graph for this function:

◆ update_mixed_filament_list()

void Slic3r::GUI::Sidebar::update_mixed_filament_list ( )
4327{
4328 auto* plater = dynamic_cast<Plater*>(GetParent());
4329 if (!plater) return;
4330
4331 wxWindowUpdateLocker noUpdates(this);
4332
4333 const wxColour mc_bg = StateColor::darkModeColorFor(*wxWHITE);
4334 const wxColour mc_border = StateColor::darkModeColorFor(wxColour("#DBDBDB")); // same color with filament combo box border
4335 const wxColour mc_text = StateColor::darkModeColorFor(wxColour("#262E30"));
4336 const wxColour mc_dim = StateColor::darkModeColorFor(wxColour("#ACACAC"));
4337
4338 auto& project_config = wxGetApp().preset_bundle->project_config;
4339 auto mixed_indices = plater->mixed_filament_config_indices();
4340 size_t num_physical = p->combos_filament.size();
4341
4342 auto* is_mixed_opt = project_config.option<ConfigOptionBools>("filament_is_mixed");
4343 auto* components_opt = project_config.option<ConfigOptionStrings>("filament_mixed_components");
4344 auto* ratios_opt = project_config.option<ConfigOptionStrings>("filament_mixed_sublayer_ratios");
4345 auto* colours_opt = project_config.option<ConfigOptionStrings>("filament_colour");
4346 auto* grad_opt = project_config.option<ConfigOptionBools>("filament_mixed_gradient");
4347 auto* grad_range_opt = project_config.option<ConfigOptionStrings>("filament_mixed_gradient_range");
4348
4349 bool can_mix = (num_physical >= 2);
4350 bool has_mixed = can_mix && !mixed_indices.empty();
4351
4352 // Check integrity of mixed filament component references
4353 std::vector<size_t> broken_slots;
4354 if (is_mixed_opt && components_opt)
4355 broken_slots = check_mixed_filament_integrity(is_mixed_opt->values, components_opt->values, num_physical);
4356 std::set<size_t> broken_set(broken_slots.begin(), broken_slots.end());
4357
4358 // Type consistency check
4359 if (is_mixed_opt && components_opt) {
4360 std::vector<std::string> physical_types;
4361 auto& preset_bundle = *wxGetApp().preset_bundle;
4362 for (size_t i = 0; i < num_physical; ++i) {
4363 std::string ft;
4364 if (i < preset_bundle.filament_presets.size()) {
4365 auto* preset = preset_bundle.filaments.find_preset(preset_bundle.filament_presets[i]);
4366 if (preset) {
4367 std::string display_type;
4368 ft = preset->config.get_filament_type(display_type);
4369 }
4370 }
4371 if (ft.empty()) ft = "PLA";
4372 physical_types.push_back(ft);
4373 }
4374 auto type_mismatch_slots = check_mixed_filament_type_consistency(
4375 is_mixed_opt->values, components_opt->values, physical_types);
4376 for (size_t s : type_mismatch_slots)
4377 broken_set.insert(s);
4378 broken_slots.insert(broken_slots.end(), type_mismatch_slots.begin(), type_mismatch_slots.end());
4379 }
4380
4381 bool at_limit = (wxGetApp().preset_bundle->filament_presets.size() >= size_t(EnforcerBlockerType::ExtruderMax));
4382 p->m_btn_add_mixed_filament->Show(can_mix && !has_mixed && !at_limit);
4383 p->m_panel_mixed_title->Show(has_mixed);
4384 p->m_mixed_scroll_area->Show(has_mixed);
4385 p->m_panel_mixed_content->Show(has_mixed);
4386 if (p->m_btn_mixed_add)
4387 p->m_btn_mixed_add->Enable(!at_limit);
4388 p->m_panel_mixed_warning->Show(false);
4389
4390 // Show/dismiss 3D canvas notification for broken mixed filaments
4391 auto* notify = plater->get_notification_manager();
4392 GLCanvas3D* view3d_canvas = plater->get_view3D_canvas3D();
4393 if(view3d_canvas && view3d_canvas->is_initialized() && notify){
4394 if (has_mixed && !broken_set.empty()) {
4395 notify->push_notification(NotificationType::BBLMixedFilamentBroken,
4397 _u8L("Mixed filament has invalid or mismatched components. Please re-edit affected entries."));
4398 } else {
4399 notify->close_notification_of_type(NotificationType::BBLMixedFilamentBroken);
4400 }
4401 }
4402
4403 if (has_mixed) {
4404 auto* left_col = p->m_sizer_mixed_filaments->GetItem(size_t(0))->GetSizer();
4405 auto* right_col = p->m_sizer_mixed_filaments->GetItem(size_t(1))->GetSizer();
4406 left_col->Clear(true);
4407 right_col->Clear(true);
4408
4409 std::vector<std::string> physical_colors;
4410 if (colours_opt) {
4411 for (size_t i = 0; i < num_physical && i < colours_opt->values.size(); ++i)
4412 physical_colors.push_back(colours_opt->values[i]);
4413 }
4414
4415 auto make_swatch_panel = [this](wxWindow* parent, const wxColour& col, unsigned int num) -> wxPanel* {
4416 int swatch_sz = FromDIP(20);
4417 auto* panel = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(swatch_sz, swatch_sz));
4418 panel->SetMinSize(wxSize(swatch_sz, swatch_sz));
4419 bool is_dark = wxGetApp().dark_mode();
4420 panel->Bind(wxEVT_PAINT, [panel, col, num, is_dark](wxPaintEvent&) {
4421 wxPaintDC dc(panel);
4422 wxSize sz = panel->GetClientSize();
4423 dc.SetBackground(wxBrush(col));
4424 dc.Clear();
4425 if (!is_dark && col.Red() > 224 && col.Green() > 224 && col.Blue() > 224) {
4426 dc.SetPen(wxPen(wxColour(130, 130, 128), 1));
4427 dc.SetBrush(*wxTRANSPARENT_BRUSH);
4428 dc.DrawRectangle(0, 0, sz.GetWidth(), sz.GetHeight());
4429 }
4430 if (is_dark && col.Red() < 45 && col.Green() < 45 && col.Blue() < 45) {
4431 dc.SetPen(wxPen(wxColour(207, 207, 207), 1));
4432 dc.SetBrush(*wxTRANSPARENT_BRUSH);
4433 dc.DrawRectangle(0, 0, sz.GetWidth(), sz.GetHeight());
4434 }
4435 wxString txt = wxString::Format("%u", num);
4436 dc.SetFont(::Label::Body_14);
4437 wxSize txt_sz = dc.GetTextExtent(txt);
4438 dc.SetTextForeground(col.GetLuminance() > 0.5 ? wxColour(50, 58, 61) : *wxWHITE);
4439 dc.DrawText(txt, (sz.GetWidth() - txt_sz.GetWidth()) / 2,
4440 (sz.GetHeight() - txt_sz.GetHeight()) / 2);
4441 });
4442 return panel;
4443 };
4444
4445 for (size_t i = 0; i < mixed_indices.size(); ++i) {
4446 size_t cfg_idx = mixed_indices[i];
4447 auto* combo_and_btn_sizer = new wxBoxSizer(wxHORIZONTAL);
4448
4449 if (i == 0 || i % 2 == 0) // dont add left margin for right column items so all horizontal margins will be equal like on filaments section
4450 combo_and_btn_sizer->AddSpacer(FromDIP(SidebarProps::ContentMargin()));
4451
4452 // Parse components and ratios from config strings (supports 2-N components)
4453 std::vector<unsigned int> comp_ids;
4454 std::vector<int> comp_ratios;
4455 if (components_opt && cfg_idx < components_opt->values.size()) {
4456 std::istringstream iss(components_opt->values[cfg_idx]);
4457 std::string tok;
4458 while (std::getline(iss, tok, ',')) {
4459 unsigned int v = 0;
4460 if (std::sscanf(tok.c_str(), "%u", &v) == 1)
4461 comp_ids.push_back(v);
4462 }
4463 }
4464 if (ratios_opt && cfg_idx < ratios_opt->values.size()) {
4465 CNumericLocalesSetter c_locale_setter;
4466 std::istringstream iss(ratios_opt->values[cfg_idx]);
4467 std::string tok;
4468 while (std::getline(iss, tok, ',')) {
4469 float v = 0;
4470 if (std::sscanf(tok.c_str(), "%f", &v) == 1)
4471 comp_ratios.push_back((int)(v * 100 + 0.5f));
4472 }
4473 }
4474 if (!comp_ids.empty() && comp_ratios.size() != comp_ids.size()) {
4475 BOOST_LOG_TRIVIAL(warning) << "Mixed filament slot " << cfg_idx
4476 << ": ratio count (" << comp_ratios.size()
4477 << ") != component count (" << comp_ids.size()
4478 << "), resetting to even distribution";
4479 int n = (int)comp_ids.size();
4480 comp_ratios.assign(n, 100 / n);
4481 comp_ratios[0] += 100 - (100 / n) * n;
4482 }
4483
4484 bool is_broken = broken_set.count(cfg_idx) > 0;
4485
4486 // Recalculate mixed color based on current physical colors
4487 if (!is_broken && !comp_ids.empty() && comp_ids.size() == comp_ratios.size()) {
4488 std::string new_mixed_color = blend_mixed_color(comp_ids, comp_ratios, physical_colors);
4489
4490 if (colours_opt && cfg_idx < colours_opt->values.size() && colours_opt->values[cfg_idx] != new_mixed_color) {
4491 colours_opt->values[cfg_idx] = new_mixed_color;
4492
4493 auto* multi_colour_opt = project_config.option<ConfigOptionStrings>("filament_multi_colour");
4494 if (multi_colour_opt && cfg_idx < multi_colour_opt->values.size()) {
4495 multi_colour_opt->values[cfg_idx] = new_mixed_color;
4496 }
4497 }
4498 }
4499
4500 bool is_gradient = false;
4501 int gradient_direction = 0;
4502 if (grad_opt && cfg_idx < grad_opt->values.size())
4503 is_gradient = grad_opt->values[cfg_idx];
4504 if (is_gradient && grad_range_opt && cfg_idx < grad_range_opt->values.size()) {
4505 CNumericLocalesSetter c_locale_setter;
4506 float v0 = 0, v1 = 0;
4507 if (std::sscanf(grad_range_opt->values[cfg_idx].c_str(), "%f,%f", &v0, &v1) == 2)
4508 gradient_direction = (v0 > v1) ? 0 : 1;
4509 }
4510
4511 std::string mix_color_str = (colours_opt && cfg_idx < colours_opt->values.size())
4512 ? colours_opt->values[cfg_idx] : "#888888";
4513 wxColour mix_col(mix_color_str);
4514 unsigned int mix_num = (unsigned int)(cfg_idx + 1);
4515
4516 // The swatch fades bottom to top over the model's height, sampled the same way
4517 // the slicer builds the sublayers, so it matches the editor's Effect Preview. The
4518 // ramp comes back empty for every slot that is not a two component gradient mix.
4519 const int swatch_sz = FromDIP(20);
4520 const std::vector<wxColour> gradient_ramp = mixed_gradient_ramp(project_config, cfg_idx, swatch_sz);
4521
4522 if (!gradient_ramp.empty()) {
4523 auto* grad_panel = new wxPanel(p->m_panel_mixed_content, wxID_ANY,
4524 wxDefaultPosition, wxSize(swatch_sz, swatch_sz));
4525 grad_panel->SetMinSize(wxSize(swatch_sz, swatch_sz));
4526 grad_panel->SetBackgroundStyle(wxBG_STYLE_PAINT);
4527 grad_panel->Bind(wxEVT_PAINT, [grad_panel, gradient_ramp, mix_num](wxPaintEvent&) {
4528 wxBufferedPaintDC dc(grad_panel);
4529 wxSize sz = grad_panel->GetClientSize();
4530 fill_gradient_ramp_rect(dc, wxRect(0, 0, sz.GetWidth(), sz.GetHeight()), gradient_ramp);
4531 wxString txt = wxString::Format("%u", mix_num);
4532 dc.SetFont(::Label::Body_14);
4533 wxSize txt_sz = dc.GetTextExtent(txt);
4534 // The number sits at the swatch's middle, so take its contrast from the
4535 // colour printed at mid height rather than from either endpoint.
4536 dc.SetTextForeground(gradient_ramp[gradient_ramp.size() / 2].GetLuminance() > 0.5 ? wxColour(50, 58, 61) : *wxWHITE);
4537 dc.DrawText(txt, (sz.GetWidth() - txt_sz.GetWidth()) / 2,
4538 (sz.GetHeight() - txt_sz.GetHeight()) / 2);
4539 });
4540 grad_panel->Bind(wxEVT_LEFT_UP, [this, i](wxMouseEvent&) { edit_mixed_filament(i); }); // ORCA also open edit color dialog with clicking swatch
4541 combo_and_btn_sizer->Add(grad_panel, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(SidebarProps::ElementSpacing()) - FromDIP(2)); // ElementSpacing - 2 (from combo box))
4542 } else {
4543 auto swatch_panel = make_swatch_panel(p->m_panel_mixed_content, mix_col, mix_num);
4544 swatch_panel->Bind(wxEVT_LEFT_UP, [this, i](wxMouseEvent&) { edit_mixed_filament(i); }); // ORCA also open edit color dialog with clicking swatch
4545 combo_and_btn_sizer->Add(swatch_panel, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(SidebarProps::ElementSpacing()) - FromDIP(2)); // ElementSpacing - 2 (from combo box))
4546 }
4547
4548 auto* content_panel = new wxPanel(p->m_panel_mixed_content, wxID_ANY);
4549 content_panel->SetBackgroundColour(mc_bg);
4550 content_panel->SetBackgroundStyle(wxBG_STYLE_PAINT);
4551
4552 // Pre-compute all values the paint lambda needs (avoid capturing `this` for FromDIP)
4553 int cp_pad = FromDIP(4);
4554 int cp_swatch_sz = FromDIP(20);
4555 int cp_sep_margin = FromDIP(3);
4556 int cp_pct_left = FromDIP(2);
4557 int cp_gap = FromDIP(2);
4558 int cp_pct_gap = FromDIP(4);
4559 bool cp_is_dark = wxGetApp().dark_mode();
4560
4561 // Build per-component colour list for the lambda
4562 std::vector<wxColour> cp_colours;
4563 std::vector<bool> cp_valid;
4564 std::vector<unsigned int> cp_ids = comp_ids;
4565 std::vector<int> cp_ratios = comp_ratios;
4566 bool cp_is_gradient = is_gradient;
4567 int cp_gradient_dir = gradient_direction;
4568 for (size_t ci = 0; ci < comp_ids.size(); ++ci) {
4569 bool valid = (comp_ids[ci] >= 1 && comp_ids[ci] <= physical_colors.size());
4570 cp_valid.push_back(valid);
4571 cp_colours.push_back(valid ? wxColour(physical_colors[comp_ids[ci] - 1]) : wxColour("#D9D9D9"));
4572 }
4573
4574 // Reorder for gradient display: from -> to
4575 std::vector<unsigned int> draw_ids;
4576 std::vector<int> draw_ratios;
4577 std::vector<wxColour> draw_colours;
4578 std::vector<bool> draw_valid;
4579 if (cp_is_gradient && cp_ids.size() == 2) {
4580 int fi = (cp_gradient_dir == 0) ? 0 : 1;
4581 int ti = 1 - fi;
4582 draw_ids = { cp_ids[fi], cp_ids[ti] };
4583 draw_ratios = { cp_ratios.size() > (size_t)fi ? cp_ratios[fi] : 0,
4584 cp_ratios.size() > (size_t)ti ? cp_ratios[ti] : 0 };
4585 draw_colours = { cp_colours[fi], cp_colours[ti] };
4586 draw_valid = { cp_valid[fi], cp_valid[ti] };
4587 } else {
4588 draw_ids = cp_ids;
4589 draw_ratios = cp_ratios;
4590 draw_colours = cp_colours;
4591 draw_valid = cp_valid;
4592 }
4593
4594 content_panel->Bind(wxEVT_PAINT, [content_panel, mc_bg, mc_border, mc_text, mc_dim,
4595 cp_pad, cp_swatch_sz, cp_sep_margin, cp_pct_left,
4596 cp_gap, cp_pct_gap, cp_is_dark,
4597 cp_is_gradient,
4598 draw_ids, draw_ratios, draw_colours, draw_valid](wxPaintEvent&) {
4599 wxBufferedPaintDC dc(content_panel);
4600 wxSize sz = content_panel->GetClientSize();
4601
4602 dc.SetBrush(wxBrush(mc_bg));
4603 dc.SetPen(wxPen(mc_border, 1));
4604 dc.DrawRectangle(0, 0, sz.GetWidth(), sz.GetHeight());
4605
4606 dc.SetFont(::Label::Body_13);
4607 int x = cp_pad;
4608 int y_swatch = (sz.GetHeight() - cp_swatch_sz) / 2;
4609 int text_h = dc.GetTextExtent(wxT("A")).GetHeight();
4610 int y_text = y_swatch + (cp_swatch_sz - text_h) / 2;
4611 int avail = sz.GetWidth() - cp_pad;
4612 wxString ellipsis = wxT("...");
4613 int ellipsis_w = dc.GetTextExtent(ellipsis).GetWidth();
4614
4615 auto fits = [&](int needed) -> bool {
4616 return (x + needed) <= (avail - ellipsis_w);
4617 };
4618
4619 size_t n = draw_ids.size();
4620 for (size_t ci = 0; ci < n; ++ci) {
4621 // Separator: "+" or arrow
4622 if (ci > 0) {
4623 wxString sep = cp_is_gradient ? wxT("\u2192") : wxT("+");
4624 int sep_w = dc.GetTextExtent(sep).GetWidth() + cp_sep_margin * 2;
4625 if (!fits(sep_w + cp_swatch_sz)) {
4626 dc.SetTextForeground(mc_text);
4627 dc.DrawText(ellipsis, x, y_text);
4628 break;
4629 }
4630 dc.SetTextForeground(mc_text);
4631 dc.DrawText(sep, x + cp_sep_margin, y_text);
4632 x += sep_w;
4633 }
4634
4635 // Swatch
4636 if (!fits(cp_swatch_sz)) {
4637 dc.SetTextForeground(mc_text);
4638 dc.DrawText(ellipsis, x, y_text);
4639 break;
4640 }
4641
4642 if (draw_valid[ci]) {
4643 wxColour col = draw_colours[ci];
4644 dc.SetBrush(wxBrush(col));
4645 dc.SetPen(*wxTRANSPARENT_PEN);
4646 dc.DrawRectangle(x, y_swatch, cp_swatch_sz, cp_swatch_sz);
4647 if (!cp_is_dark && col.Red() > 224 && col.Green() > 224 && col.Blue() > 224) {
4648 dc.SetPen(wxPen(wxColour(130, 130, 128), 1));
4649 dc.SetBrush(*wxTRANSPARENT_BRUSH);
4650 dc.DrawRectangle(x, y_swatch, cp_swatch_sz, cp_swatch_sz);
4651 }
4652 if (cp_is_dark && col.Red() < 45 && col.Green() < 45 && col.Blue() < 45) {
4653 dc.SetPen(wxPen(wxColour(207, 207, 207), 1));
4654 dc.SetBrush(*wxTRANSPARENT_BRUSH);
4655 dc.DrawRectangle(x, y_swatch, cp_swatch_sz, cp_swatch_sz);
4656 }
4657 dc.SetFont(::Label::Body_14);
4658 wxString num = wxString::Format("%u", draw_ids[ci]);
4659 wxSize num_sz = dc.GetTextExtent(num);
4660 dc.SetTextForeground(col.GetLuminance() > 0.5 ? wxColour(50, 58, 61) : *wxWHITE);
4661 dc.DrawText(num, x + (cp_swatch_sz - num_sz.GetWidth()) / 2,
4662 y_swatch + (cp_swatch_sz - num_sz.GetHeight()) / 2);
4663 dc.SetFont(::Label::Body_13);
4664 } else {
4665 dc.SetBrush(wxBrush(mc_bg));
4666 dc.SetPen(wxPen(mc_dim, 1));
4667 dc.DrawRectangle(x, y_swatch, cp_swatch_sz, cp_swatch_sz);
4668 wxString dash = wxT("\u2014");
4669 wxSize dash_sz = dc.GetTextExtent(dash);
4670 dc.SetTextForeground(mc_dim);
4671 dc.DrawText(dash, x + (cp_swatch_sz - dash_sz.GetWidth()) / 2,
4672 y_swatch + (cp_swatch_sz - dash_sz.GetHeight()) / 2);
4673 }
4674 x += cp_swatch_sz + cp_gap;
4675
4676 // Ratio text (skip for gradient)
4677 if (!cp_is_gradient) {
4678 int r = (ci < draw_ratios.size()) ? draw_ratios[ci] : 0;
4679 wxString pct = wxString::Format("%d%%", r);
4680 int pct_w = dc.GetTextExtent(pct).GetWidth();
4681 if (!fits(pct_w)) {
4682 dc.SetTextForeground(mc_text);
4683 dc.DrawText(ellipsis, x, y_text);
4684 break;
4685 }
4686 dc.SetTextForeground(mc_text);
4687 dc.DrawText(pct, x + cp_pct_left, y_text);
4688 x += pct_w + cp_pct_gap;
4689 }
4690 }
4691 });
4692
4693 // Tooltip: always show full info
4694 {
4695 wxString tip;
4696 for (size_t ci = 0; ci < draw_ids.size(); ++ci) {
4697 if (ci > 0) tip += cp_is_gradient ? wxT(" \u2192 ") : wxT(" + ");
4698 int r = (ci < draw_ratios.size()) ? draw_ratios[ci] : 0;
4699 tip += wxString::Format("%u (%d%%)", draw_ids[ci], r);
4700 }
4701 content_panel->SetToolTip(tip);
4702 }
4703
4704 // Repaint on resize so truncation updates
4705 content_panel->Bind(wxEVT_SIZE, [content_panel](wxSizeEvent& e) {
4706 content_panel->Refresh();
4707 e.Skip();
4708 });
4709
4710 content_panel->SetCursor(wxCursor(wxCURSOR_HAND));
4711 size_t panel_idx = i;
4712 content_panel->Bind(wxEVT_LEFT_UP, [this, panel_idx](wxMouseEvent&) { edit_mixed_filament(panel_idx); });
4713
4714 combo_and_btn_sizer->Add(content_panel, 1, wxALL | wxEXPAND, FromDIP(2))->SetMinSize({-1, FromDIP(30)});
4715
4716 auto* menu_btn = new ScalableButton(p->m_panel_mixed_content, wxID_ANY,
4717 is_broken ? "error" : "menu_filament");
4718 menu_btn->SetToolTip(is_broken ? _L("Mixed filament has broken component references") : _L("Edit / Delete / Merge"));
4719 menu_btn->Bind(wxEVT_BUTTON, [this, panel_idx, cfg_idx](wxCommandEvent&) {
4720 wxMenu menu;
4721
4722 auto* edit_item = menu.Append(wxID_ANY, _L("Edit"));
4723 menu.Bind(wxEVT_MENU, [this, panel_idx](wxCommandEvent&) {
4724 edit_mixed_filament(panel_idx);
4725 }, edit_item->GetId());
4726
4727 wxMenu* sub_menu = new wxMenu();
4728 std::vector<wxBitmap*> icons = get_extruder_color_icons(true);
4729 int filaments_cnt = icons.size();
4730 for (int j = 0; j < filaments_cnt; ++j) {
4731 if ((size_t)j == cfg_idx)
4732 continue;
4733
4734 wxString item_name;
4735 bool is_target_mixed = wxGetApp().preset_bundle->is_mixed_filament(j);
4736 if (is_target_mixed) {
4737 item_name = wxString::Format(_L("Filament %d"), j + 1);
4738 } else {
4739 auto preset = wxGetApp().preset_bundle->filaments.find_preset(
4740 wxGetApp().preset_bundle->filament_presets[j]);
4741 item_name = preset ? from_u8(preset->label(false))
4742 : wxString::Format(_L("Filament %d"), j + 1);
4743 }
4744
4745 auto* mi = new wxMenuItem(sub_menu, wxID_ANY, item_name);
4746#ifndef __linux__
4747 mi->SetBitmap(*icons[j]);
4748#endif
4749 sub_menu->Append(mi);
4750 sub_menu->Bind(wxEVT_MENU, [this, cfg_idx, j](wxCommandEvent&) {
4751 change_filament(cfg_idx, j);
4752 }, mi->GetId());
4753 }
4754 if (filaments_cnt > 1)
4755 menu.AppendSubMenu(sub_menu, _L("Merge with"));
4756 else
4757 delete sub_menu;
4758
4759 menu.AppendSeparator(); // ORCA use seperator for reducing accidental clicks to delete
4760
4761 // ORCA use delete item on end of menu to prevent accidental clicks. clicking to submenus(merge) already not allowed by OS
4762 auto* del_item = menu.Append(wxID_ANY, _L("Delete"));
4763 menu.Bind(wxEVT_MENU, [this, panel_idx](wxCommandEvent&) {
4764 delete_mixed_filament_at(panel_idx);
4765 }, del_item->GetId());
4766
4767 PopupMenu(&menu);
4768 });
4769 combo_and_btn_sizer->Add(menu_btn, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(SidebarProps::ElementSpacing()) - FromDIP(2)); // ElementSpacing - 2 (from combo box))
4770
4771 combo_and_btn_sizer->Add(FromDIP(SidebarProps::ContentMargin()), 0, 0, 0, 0);
4772
4773 int side = i % 2;
4774 auto* col = (side == 0) ? left_col : right_col;
4775 if (side == 1 && i > 1) col->Remove(i / 2);
4776 col->Add(combo_and_btn_sizer, 1, wxEXPAND);
4777 if (side == 0 && i > 0) {
4778 right_col->AddStretchSpacer(1);
4779 }
4780 }
4781 }
4782
4784
4785 p->m_panel_filament_content->FitInside();
4786 p->m_mixed_scroll_area->FitInside();
4787 p->scrolled->Layout();
4788 m_scrolled_sizer->Layout();
4789 p->scrolled->Layout();
4790
4791 size_t total = wxGetApp().preset_bundle->filament_presets.size();
4793
4794 // Sync mixed filament colors into the config used by 3D view rendering.
4797
4798 // Check if any broken mixed filament is used by objects on current plate.
4799 // Scan raw extruder assignments (object / volume / height-range / painting)
4800 // instead of get_extruders() which expands mixed slots and loses their IDs.
4801 p->m_mixed_filament_broken = false;
4802 if (!broken_slots.empty()) {
4803 std::set<size_t> broken_1based;
4804 for (size_t s : broken_slots) broken_1based.insert(s + 1);
4805
4806 auto* curr_plate = plater->get_partplate_list().get_curr_plate();
4807 if (curr_plate) {
4808 for (auto& obj : plater->model().objects) {
4809 if (!curr_plate->contain_instance_totally(obj, 0))
4810 continue;
4811 // Check object-level extruder
4812 int obj_ext = obj->config.has("extruder") ? obj->config.extruder() : 1;
4813 if (broken_1based.count((size_t)obj_ext)) {
4814 p->m_mixed_filament_broken = true;
4815 break;
4816 }
4817 bool found = false;
4818 for (auto* vol : obj->volumes) {
4819 // Check volume-level extruder
4820 int vol_ext = vol->config.has("extruder") ? vol->config.extruder() : obj_ext;
4821 if (broken_1based.count((size_t)vol_ext)) { found = true; break; }
4822 // Check color painting data (mmu segmentation facets)
4823 if (vol->is_model_part() && !vol->mmu_segmentation_facets.empty()) {
4824 for (size_t broken_slot : broken_1based) {
4825 if (vol->mmu_segmentation_facets.has_facets(*vol, EnforcerBlockerType(broken_slot)))
4826 { found = true; break; }
4827 }
4828 if (found) break;
4829 }
4830 }
4831 if (found) { p->m_mixed_filament_broken = true; break; }
4832 // Check height range modifier extruder overrides
4833 for (auto& [range, cfg] : obj->layer_config_ranges) {
4834 if (cfg.has("extruder")) {
4835 int layer_ext = cfg.option("extruder")->getInt();
4836 if (layer_ext > 0 && broken_1based.count((size_t)layer_ext))
4837 { found = true; break; }
4838 }
4839 }
4840 if (found) { p->m_mixed_filament_broken = true; break; }
4841 }
4842 }
4843 }
4844
4845 if (plater->canvas3D()) {
4848 }
4849
4850 if (p->m_mixed_filament_broken) {
4851 auto* mf = wxGetApp().mainframe;
4852 if (mf)
4853 mf->update_slice_print_status(MainFrame::eEventObjectUpdate, false);
4854 }
4855
4856 if (auto *tab = dynamic_cast<TabPrintPlate *>(wxGetApp().plate_tab))
4857 tab->update_mixed_filament_seq_state();
4858
4859}
static bool is_dark()
Definition TextureImportDialog.cpp:85
static wxFont Body_14
Definition Label.hpp:53
bool empty() const override
Definition Config.hpp:723
void reload_scene(bool refresh_immediately, bool force_full_scene_refresh=false)
Definition GLCanvas3D.cpp:3162
void set_as_dirty()
Definition GLCanvas3D.hpp:984
@ eEventObjectUpdate
Definition MainFrame.hpp:337
@ ErrorNotificationLevel
Definition NotificationManager.hpp:228
void update_objects_list_filament_column(size_t filaments_count)
Definition GUI_ObjectList.cpp:1046
const NotificationManager * get_notification_manager() const
Definition Plater.cpp:23864
bool update_filament_colors_in_full_config()
Definition Plater.cpp:21482
GLCanvas3D * canvas3D()
Definition Plater.cpp:22070
GLCanvas3D * get_view3D_canvas3D()
Definition Plater.cpp:22082
void edit_mixed_filament(size_t idx)
Definition Plater.cpp:5179
static const wxString sep
Definition MainFrame.cpp:2828
void fill_gradient_ramp_rect(wxDC &dc, const wxRect &rect, const std::vector< wxColour > &ramp)
Definition FilamentBitmapUtils.cpp:189
std::vector< wxColour > mixed_gradient_ramp(const Slic3r::DynamicPrintConfig &cfg, size_t slot, int steps)
Definition FilamentBitmapUtils.cpp:163
@ BBLMixedFilamentBroken
Definition NotificationManager.hpp:174
#define _u8L(s)
Definition I18N.hpp:11
std::vector< wxBitmap * > get_extruder_color_icons(bool thin_icon)
Definition wxExtensions.cpp:572

References _L, _u8L, Slic3r::GUI::BBLMixedFilamentBroken, Slic3r::GUI::blend_mixed_color(), Label::Body_13, Label::Body_14, change_filament(), Slic3r::check_mixed_filament_integrity(), Slic3r::check_mixed_filament_type_consistency(), Slic3r::GUI::SidebarProps::ContentMargin(), StateColor::darkModeColorFor(), delete_mixed_filament_at(), edit_mixed_filament(), Slic3r::GUI::MainFrame::eEventObjectUpdate, Slic3r::GUI::SidebarProps::ElementSpacing(), Slic3r::ConfigOptionVector< T >::empty(), Slic3r::GUI::NotificationManager::ErrorNotificationLevel, Slic3r::ExtruderMax, Slic3r::GUI::fill_gradient_ramp_rect(), Slic3r::GUI::from_u8(), get_extruder_color_icons(), is_dark(), Slic3r::GUI::GLCanvas3D::is_initialized(), m_scrolled_sizer, Slic3r::GUI::mixed_gradient_ramp(), obj_list(), p, Slic3r::GUI::plater(), Slic3r::range(), recalc_filament_scroll_sizes(), Slic3r::GUI::sep, Slic3r::ConfigOptionVector< T >::size(), Slic3r::ConfigOptionVector< unsigned char >::size(), Slic3r::GUI::ObjectList::update_filament_colors(), Slic3r::GUI::ObjectList::update_objects_list_filament_column(), Slic3r::ConfigOptionVector< T >::values, Slic3r::ConfigOptionVector< unsigned char >::values, and Slic3r::GUI::wxMouseEvent.

Referenced by Slic3r::GUI::create_mixed_filament_from_result(), edit_mixed_filament(), on_filament_count_change(), on_filaments_delete(), and sys_color_changed().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_mode()

void Slic3r::GUI::Sidebar::update_mode ( )
6834{
6835 m_mode = wxGetApp().get_mode();
6836
6837 //BBS: remove print related combos
6839
6840 wxWindowUpdateLocker noUpdates(this);
6841
6842 // BBS
6843 //obj_list()->get_sizer()->Show(m_mode > comSimple);
6844
6847// obj_list()->update_object_menu();
6848
6849 Layout();
6850}
void update_selections()
Definition GUI_ObjectList.cpp:4932
void unselect_objects()
Definition GUI_ObjectList.cpp:4504
ConfigOptionMode m_mode
Definition Plater.hpp:158
void update_searcher()
Definition Plater.cpp:6828

References m_mode, obj_list(), Slic3r::GUI::ObjectList::unselect_objects(), update_searcher(), and Slic3r::GUI::ObjectList::update_selections().

Here is the call graph for this function:

◆ update_presets()

void Slic3r::GUI::Sidebar::update_presets ( Slic3r::Preset::Type preset_type)
3923{
3924 PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
3925 const auto print_tech = preset_bundle.printers.get_edited_preset().printer_technology();
3926
3927 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": enter, preset_type %1%")%preset_type;
3928 switch (preset_type) {
3930 {
3931 // BBS
3932#if 0
3933 const size_t extruder_cnt = print_tech != ptFFF ? 1 :
3934 dynamic_cast<ConfigOptionFloats*>(preset_bundle.printers.get_edited_preset().config.option("nozzle_diameter"))->values.size();
3935 const size_t filament_cnt = p->combos_filament.size() > extruder_cnt ? extruder_cnt : p->combos_filament.size();
3936#else
3937 const size_t filament_cnt = p->combos_filament.size();
3938#endif
3939 const std::string &name = preset_bundle.filaments.get_selected_preset_name();
3940 if (p->editing_filament >= 0) {
3941 preset_bundle.set_filament_preset(p->editing_filament, name);
3942 } else if (filament_cnt == 1) {
3943 // Single filament printer, synchronize the filament presets.
3944 Preset *preset = preset_bundle.filaments.find_preset(name, false);
3945 if (preset) {
3946 if (preset->is_compatible) preset_bundle.set_filament_preset(0, name);
3947 }
3948
3949 }
3950
3951 for (size_t i = 0; i < filament_cnt; i++)
3952 p->combos_filament[i]->update();
3953
3955 break;
3956 }
3957
3958 case Preset::TYPE_PRINT:
3959 //wxGetApp().mainframe->m_param_panel;
3960 //p->combo_print->update();
3961 {
3962 Tab* print_tab = wxGetApp().get_tab(Preset::TYPE_PRINT);
3963 if (print_tab) {
3964 print_tab->get_combo_box()->update();
3965 }
3966 break;
3967 }
3969 ;// p->combo_sla_print->update();
3970 break;
3971
3973 ;// p->combo_sla_material->update();
3974 break;
3975
3977 {
3979 p->show_preset_comboboxes();
3980
3981 /* update bed shape */
3982 Tab* printer_tab = wxGetApp().get_tab(Preset::TYPE_PRINTER);
3983 if (printer_tab) {
3984 printer_tab->update();
3985 printer_tab->on_preset_loaded();
3986 }
3987
3988 Preset& printer_preset = wxGetApp().preset_bundle->printers.get_edited_preset();
3989
3990 if (auto printer_structure_opt = printer_preset.config.option<ConfigOptionEnum<PrinterStructure>>("printer_structure")) {
3991 wxGetApp().plater()->get_current_canvas3D()->get_arrange_settings().align_to_y_axis = (printer_structure_opt->value == PrinterStructure::psI3);
3992 }
3993 else
3994 wxGetApp().plater()->get_current_canvas3D()->get_arrange_settings().align_to_y_axis = false;
3995
3996 // Update dual extrudes
3997 auto* nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(printer_preset.config.option("nozzle_diameter"));
3998 auto extruder_variants = printer_preset.config.option<ConfigOptionStrings>("extruder_variant_list");
3999 std::string printer_model = printer_preset.config.option<ConfigOptionString>("printer_model")->value;
4000
4001 bool isBBL = preset_bundle.is_bbl_vendor();
4002 bool is_dual_extruder = extruder_variants->size() == 2;
4003 // why: agent mode drives the native device tab, so the sidebar lays out like BBL
4004 // (no physical-printer connect button).
4005 p->layout_printer(preset_bundle.use_bbl_network() || wxGetApp().app_config->get_bool("use_printer_agents"),
4006 isBBL && is_dual_extruder);
4007
4008 // Update nozzle titles from printer config (e.g. "Main Nozzle" / "Auxiliary Nozzle" for N6)
4009 // UI left = DEPUTY_EXTRUDER_ID(1), UI right = MAIN_EXTRUDER_ID(0)
4010 if (is_dual_extruder) {
4011 std::string printer_type = printer_preset.get_printer_type(wxGetApp().preset_bundle);
4014 p->left_extruder->SetTitle(_L(left_title));
4015 p->right_extruder->SetTitle(_L(right_title));
4016 }
4017
4018 auto extruders_def = printer_preset.config.def()->get("extruder_type");
4019 auto extruders = printer_preset.config.option<ConfigOptionEnumsGeneric>("extruder_type");
4020 auto nozzle_volumes_def = wxGetApp().preset_bundle->project_config.def()->get("nozzle_volume_type");
4021 auto nozzle_volumes = wxGetApp().preset_bundle->project_config.option<ConfigOptionEnumsGeneric>("nozzle_volume_type");
4022 auto diameters = wxGetApp().preset_bundle->printers.diameters_of_selected_printer();
4023 auto diameter = printer_preset.config.opt_string("printer_variant");
4024 auto extruder_max_nozzle_count = printer_preset.config.option<ConfigOptionIntsNullable>("extruder_max_nozzle_count");
4025 const bool has_flow_variant = preset_bundle.support_different_extruders();
4026 auto update_extruder_variant = [printer_model, extruders_def, extruders, nozzle_volumes_def, nozzle_volumes, extruder_variants,diameter,extruder_max_nozzle_count,has_flow_variant](ExtruderGroup & extruder, size_t row, int index) {
4027 ComboBox *combo_flow = extruder.rows[row].flow;
4028 combo_flow->Clear();
4029 // A profile may leave the per-extruder lists shorter than the nozzle count (they are
4030 // padded when the printer is loaded, but a hand-written preset need not be).
4031 if (index >= int(extruder_variants->values.size()) || index >= int(extruders->values.size()) ||
4032 index >= int(nozzle_volumes->values.size())) {
4033 combo_flow->Hide();
4034 return;
4035 }
4036 auto type = extruders_def->enum_labels[extruders->values[index]];
4037 int select = -1;
4038 for (size_t i = 0; i < nozzle_volumes_def->enum_labels.size(); ++i) {
4039 // get_at falls back to the first entry when a profile defines no per-extruder value,
4040 // so extruders without an explicit sub-nozzle count never offer Hybrid. A nullable-int
4041 // nil is INT_MAX (> 1) and would otherwise falsely pass the gate, so exclude it too.
4042 if (boost::algorithm::contains(extruder_variants->values[index], type + " " + nozzle_volumes_def->enum_labels[i]) ||
4044 nozzle_volumes_def->enum_keys_map->at(nozzle_volumes_def->enum_values[i]) == nvtHybrid)) {
4045 auto cur_volume_type = nozzle_volumes_def->enum_keys_map->at(nozzle_volumes_def->enum_values[i]);
4046 // Defensive: profiles restrict E3D to 0.4 / 0.6; keep it out elsewhere.
4047 if (cur_volume_type == NozzleVolumeType::nvtE3DHighFlow && diameter != "0.4" && diameter != "0.6")
4048 continue;
4049 if (cur_volume_type == NozzleVolumeType::nvtHighFlow && (diameter == "0.2" ||
4050 is_skip_high_flow_printer(printer_model)))
4051 continue;
4052 // The client data is the enum value, not the label position: E3D High Flow is 5
4053 // but sits at position 4, and a position would write an invalid type.
4054 if (nozzle_volumes->values[index] == cur_volume_type)
4055 select = combo_flow->GetCount();
4056 combo_flow->Append(_L(nozzle_volumes_def->enum_labels[i]), {}, (void*)(intptr_t)cur_volume_type);
4057 }
4058 }
4059 if (select == -1)
4060 select = combo_flow->GetCount() - 1;
4061 combo_flow->SetSelection(select);
4062 // No flow variant for this printer or extruder: the diameter keeps the whole row.
4063 combo_flow->Show(has_flow_variant && combo_flow->GetCount() > 0);
4064 };
4065
4066 auto update_extruder_diameter = [&diameters, &nozzle_diameter, &diameter](int extruder_index,ExtruderGroup & extruder) {
4067 extruder.combo_diameter->Clear();
4068 if (extruder_index >= int(nozzle_diameter->values.size()))
4069 return;
4070 int select = -1;
4071 // ORCA get the actual nozzle diameter from printer config
4072 auto nozzle_dia = get_diameter_string(nozzle_diameter->values[extruder_index]);
4073 // Named variants such as "0.4HS" and "0.4 High Flow" share a physical diameter.
4074 // Retain the variant selection unless the diameter was customized.
4075 const bool keep_variant = diameter.substr(0, diameter.find_first_not_of("0123456789.")) == nozzle_dia &&
4076 std::find(diameters.begin(), diameters.end(), diameter) != diameters.end();
4077 const std::string &selected_variant = keep_variant ? diameter : nozzle_dia;
4078 // ORCA try to add nozzle diameter from config if list is empty. fixes blank nozzle combo box when preset has no alias
4079 if(!diameters.empty() && diameters[0].empty() && !nozzle_dia.empty()){
4080 diameters[0] = nozzle_dia;
4081 }
4082 // Orca: Check if the actual nozzle diameter exists in the list, if not add it as a custom option
4083 if (std::find(diameters.begin(), diameters.end(), nozzle_dia) == diameters.end() && !nozzle_dia.empty()) {
4084 diameters.push_back(nozzle_dia);
4085 }
4086 for (size_t i = 0; i < diameters.size(); ++i) {
4087 if (diameters[i] == selected_variant)
4088 select = extruder.combo_diameter->GetCount();
4089 extruder.combo_diameter->Append(diameters[i], {});
4090 }
4091 extruder.combo_diameter->SetSelection(select);
4092 extruder.diameter = nozzle_dia;
4093 };
4094 auto image_path = get_cur_select_bed_image();
4095 const bool multi_extruder_rows = p->single_extruder->NozzleRowCount() > 1;
4096 if (is_dual_extruder && !multi_extruder_rows) {
4097 std::string printer_type = printer_preset.get_printer_type(wxGetApp().preset_bundle);
4100 AMSCountPopupWindow::UpdateAMSCount(0, p->left_extruder);
4101 AMSCountPopupWindow::UpdateAMSCount(1, p->right_extruder);
4102 update_extruder_variant(*p->left_extruder, 0, 0);
4103 update_extruder_variant(*p->right_extruder, 0, 1);
4104 //if (!p->is_switching_diameter) {
4105 update_extruder_diameter(0, *p->left_extruder);
4106 update_extruder_diameter(1, *p->right_extruder);
4107 //}
4108 p->image_printer_bed->SetBitmap(create_scaled_bitmap(image_path, this, PRINTER_THUMBNAIL_SIZE.GetHeight()));
4109 } else {
4110 AMSCountPopupWindow::UpdateAMSCount(0, p->single_extruder);
4111 for (size_t row = 0; row < p->single_extruder->NozzleRowCount(); ++row)
4112 update_extruder_variant(*p->single_extruder, row, int(row));
4113 //if (!p->is_switching_diameter)
4114 update_extruder_diameter(0, *p->single_extruder);
4115 // The card reads the nozzles out, the variant box above is what switches the machine.
4116 p->single_extruder->SetRowDiameters(nozzle_diameter->values);
4117 if (multi_extruder_rows) {
4118 // The hidden left/right cards keep mirroring the first extruders' diameters: the
4119 // device sync path (a connected Bambu printer or a printer agent) still reads them.
4120 update_extruder_diameter(0, *p->left_extruder);
4121 update_extruder_diameter(1, *p->right_extruder);
4122 }
4123
4124 // ORCA sync unified nozzle combo box
4125 p->combo_nozzle_dia->Clear();
4126 for (size_t i = 0; i < diameters.size(); ++i)
4127 p->combo_nozzle_dia->Append(diameters[i], {});
4128 // Prefer the variant the preset names: a mixed-nozzle machine reads "0.4+0.6", which is
4129 // no single extruder's diameter.
4130 const int variant = p->combo_nozzle_dia->FindString(diameter);
4131 p->combo_nozzle_dia->SetSelection(variant != wxNOT_FOUND ? variant : (*p->single_extruder).combo_diameter->GetSelection());
4132
4133 // ORCA update nozzle type
4134 const auto& full_config = wxGetApp().preset_bundle->full_config();
4135 wxString nozzle_type = "-";
4136 const ConfigOptionEnumsGenericNullable* cfg_nozzle_type = full_config.option<ConfigOptionEnumsGenericNullable>("nozzle_type");
4137 if(cfg_nozzle_type != nullptr){
4138 std::vector<NozzleType> nozzle_types(cfg_nozzle_type->size());
4139 for (size_t idx = 0; idx < cfg_nozzle_type->size(); ++idx)
4140 nozzle_types[idx] = NozzleType(cfg_nozzle_type->values[idx]);
4141 // NEEDFIX this part can be replaced with shorter names
4142 nozzle_type = nozzle_types[0] == ntHardenedSteel ? _L("Hardened Steel") :
4143 nozzle_types[0] == ntStainlessSteel ? _L("Stainless Steel") :
4144 nozzle_types[0] == ntTungstenCarbide ? _L("Tungsten Carbide") :
4145 nozzle_types[0] == ntBrass ? _L("Brass")
4146 : wxString("-"); // Undefined
4147 }
4148 p->label_nozzle_type->SetLabel(nozzle_type);
4149 p->label_nozzle_type->SetToolTip(nozzle_type == "-" ? "" : nozzle_type);
4150
4151 p->image_printer_bed->SetBitmap(create_scaled_bitmap(image_path, this, PRINTER_THUMBNAIL_SIZE.GetHeight()));
4152 }
4153
4154 if (GUI::wxGetApp().plater())
4155 GUI::wxGetApp().plater()->update_machine_sync_status();
4156
4157 Layout();
4158
4159 break;
4160 }
4161
4162 default: break;
4163 }
4164
4165 // Synchronize config.ini with the current selections.
4166 wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config);
4167
4168 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": exit.");
4169}
#define DEPUTY_EXTRUDER_ID
Definition DevDefs.h:102
#define MAIN_EXTRUDER_ID
Definition DevDefs.h:101
void SetSelection(int n) override
Definition ComboBox.cpp:102
int Append(const wxString &item, const wxBitmap &bitmap=wxNullBitmap, int item_style=0)
Definition ComboBox.cpp:227
unsigned int GetCount() const override
Definition ComboBox.cpp:311
static int nil_value()
Definition Config.hpp:1083
static std::string get_toolhead_display_name(const std::string &type_str, int ext_id, ToolHeadComponent component, ToolHeadNameCase name_case=ToolHeadNameCase::TitleCase, bool short_name=false)
Definition DevConfigUtil.cpp:379
static void UpdateAMSCount(int index, ExtruderGroup *extruder)
Definition Plater.cpp:1514
@ TYPE_SLA_PRINT
Definition Preset.hpp:247
@ TYPE_SLA_MATERIAL
Definition Preset.hpp:249
static bool is_skip_high_flow_printer(const std::string &printer)
Definition Plater.cpp:1939
static std::string get_diameter_string(float diameter)
Definition Plater.cpp:366
zaa_minimize_perimeter_height nozzle_diameter((ConfigOptionBool, reduce_infill_retraction))((ConfigOptionBool
@ nvtE3DHighFlow
Definition PrintConfig.hpp:626
@ nvtHybrid
Definition PrintConfig.hpp:621
@ nvtHighFlow
Definition PrintConfig.hpp:620
@ Nozzle
Definition DevConfigUtil.h:35
ConfigOptionEnumsGenericTempl< false > ConfigOptionEnumsGeneric
Definition Config.hpp:2311
NozzleType
Definition CommonDefs.hpp:13
@ ntTungstenCarbide
Definition CommonDefs.hpp:17
@ ntStainlessSteel
Definition CommonDefs.hpp:16
@ ntBrass
Definition CommonDefs.hpp:18
@ ntHardenedSteel
Definition CommonDefs.hpp:15
zaa_minimize_perimeter_height ConfigOptionString
Definition PrintConfig.hpp:1702
@ psI3
Definition PrintConfig.hpp:560
ConfigOptionEnumsGenericTempl< true > ConfigOptionEnumsGenericNullable
Definition Config.hpp:2312
zaa_minimize_perimeter_height extruder_max_nozzle_count((ConfigOptionBool, support_fast_purge_mode))((ConfigOptionStrings
zaa_minimize_perimeter_height nozzle_type((ConfigOptionInt, nozzle_hrc))((ConfigOptionBool
@ TitleCase
Definition DevConfigUtil.h:41

References _L, ComboBox::Append(), Slic3r::Preset::config, create_scaled_bitmap(), Slic3r::DynamicPrintConfig::def(), DEPUTY_EXTRUDER_ID, Slic3r::ConfigOptionVector< int >::empty(), Slic3r::extruder_max_nozzle_count(), Slic3r::PresetBundle::filaments, Slic3r::PresetCollection::find_preset(), Slic3r::ConfigDef::get(), Slic3r::GUI::Tab::get_combo_box(), get_cur_select_bed_image(), Slic3r::GUI::get_diameter_string(), Slic3r::PresetCollection::get_edited_preset(), Slic3r::Preset::get_printer_type(), Slic3r::PresetCollection::get_selected_preset_name(), Slic3r::DevPrinterConfigUtil::get_toolhead_display_name(), ComboBox::GetCount(), Slic3r::PresetBundle::is_bbl_vendor(), Slic3r::Preset::is_compatible, Slic3r::GUI::is_skip_high_flow_printer(), MAIN_EXTRUDER_ID, Slic3r::ConfigOptionIntsTempl< true >::nil_value(), Slic3r::Nozzle, Slic3r::nozzle_diameter(), Slic3r::nozzle_type(), Slic3r::ntBrass, Slic3r::ntHardenedSteel, Slic3r::ntStainlessSteel, Slic3r::ntTungstenCarbide, Slic3r::nvtE3DHighFlow, Slic3r::nvtHighFlow, Slic3r::nvtHybrid, Slic3r::GUI::Tab::on_preset_loaded(), Slic3r::DynamicConfig::opt_string(), Slic3r::ConfigBase::option(), p, Slic3r::GUI::plater(), Slic3r::Preset::printer_technology(), PRINTER_THUMBNAIL_SIZE, Slic3r::PresetBundle::printers, Slic3r::psI3, Slic3r::ptFFF, Slic3r::PresetBundle::set_filament_preset(), ComboBox::SetSelection(), Slic3r::ConfigOptionVector< int >::size(), Slic3r::PresetBundle::support_different_extruders(), Slic3r::TitleCase, Slic3r::Preset::TYPE_FILAMENT, Slic3r::Preset::TYPE_PRINT, Slic3r::Preset::TYPE_PRINTER, Slic3r::Preset::TYPE_SLA_MATERIAL, Slic3r::Preset::TYPE_SLA_PRINT, Slic3r::GUI::Tab::update(), Slic3r::GUI::TabPresetComboBox::update(), update_all_preset_comboboxes(), update_dynamic_filament_list(), Slic3r::GUI::AMSCountPopupWindow::UpdateAMSCount(), Slic3r::PresetBundle::use_bbl_network(), and Slic3r::ConfigOptionVector< int >::values.

Referenced by Slic3r::GUI::TabPrinter::build_unregular_pages(), and Slic3r::GUI::Plater::load_gcode().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_presets_from_to()

void Slic3r::GUI::Sidebar::update_presets_from_to ( Slic3r::Preset::Type preset_type,
std::string from,
std::string to )
4173{
4174 PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
4175
4176 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": enter, preset_type %1%, from %2% to %3%")%preset_type %from %to;
4177
4178 switch (preset_type) {
4180 {
4181 const size_t filament_cnt = p->combos_filament.size();
4182 for (auto it = preset_bundle.filament_presets.begin(); it != preset_bundle.filament_presets.end(); it++)
4183 {
4184 if ((*it).compare(from) == 0) {
4185 (*it) = to;
4186 }
4187 }
4188 for (size_t i = 0; i < filament_cnt; i++)
4189 p->combos_filament[i]->update();
4190 break;
4191 }
4192
4193 default: break;
4194 }
4195
4196 // Synchronize config.ini with the current selections.
4197 wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config);
4198
4199 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": exit!");
4200}

References Slic3r::PresetBundle::filament_presets, p, and Slic3r::Preset::TYPE_FILAMENT.

◆ update_printer_thumbnail()

void Slic3r::GUI::Sidebar::update_printer_thumbnail ( )
6930{
6931 auto& preset_bundle = wxGetApp().preset_bundle;
6932 Preset & selected_preset = preset_bundle->printers.get_edited_preset();
6933 std::string printer_type = selected_preset.get_current_printer_type(preset_bundle);
6934 if (printer_thumbnails.find(printer_type) != printer_thumbnails.end()) // Use known cache first
6935 p->image_printer->SetBitmap(create_scaled_bitmap(printer_thumbnails[printer_type], this, PRINTER_THUMBNAIL_SIZE.GetHeight()));
6936 else {
6937 /* ORCA this part check images folder for BBL covers but not checks file existence and causes crash on Linux
6938 * BBL covers already exist on profile folder so no need to use this section
6939 try {
6940 // No cache, try dedicated printer preview
6941 p->image_printer->SetBitmap(create_scaled_bitmap("printer_preview_" + printer_type, this, 48));
6942 // Success, cache it
6943 printer_thumbnails[printer_type] = "printer_preview_" + printer_type;
6944 return;
6945 } catch (...) {}
6946 */
6947
6948 // Orca: try to use the printer model cover as the thumbnail
6949 const auto model_name = selected_preset.config.opt_string("printer_model");
6950 std::string cover_file = model_name + "_cover.png";
6951 for (auto vendor_profile : preset_bundle->vendors) {
6952 for (auto vendor_model : vendor_profile.second.models) {
6953 if (vendor_model.name == model_name) {
6954 // Try to find the printer cover
6955 boost::filesystem::path cover_path = boost::filesystem::absolute(boost::filesystem::path(resources_dir()) /
6956 "/profiles/" / vendor_profile.second.id / cover_file)
6957 .make_preferred();
6958 if (boost::filesystem::exists(cover_path)) {
6959 try {
6960 p->image_printer->SetBitmap(create_scaled_bitmap(cover_path.string(), this, PRINTER_THUMBNAIL_SIZE.GetHeight()));
6961 printer_thumbnails[printer_type] = cover_path.string(); // Cache the path so we don't look up again
6962 return;
6963 } catch (...) {}
6964 }
6965 }
6966 }
6967 }
6968 p->image_printer->SetBitmap(create_scaled_bitmap("printer_placeholder", this, PRINTER_THUMBNAIL_SIZE.GetHeight()));
6969 printer_thumbnails[printer_type] = "printer_placeholder"; // Avoid unnecessary try
6970 }
6971}
static std::map< std::string, std::string > printer_thumbnails
Definition Plater.cpp:6927

References Slic3r::Preset::config, create_scaled_bitmap(), Slic3r::Preset::get_current_printer_type(), Slic3r::DynamicConfig::opt_string(), p, PRINTER_THUMBNAIL_SIZE, Slic3r::GUI::printer_thumbnails, and Slic3r::resources_dir().

Referenced by msw_rescale(), and update_all_preset_comboboxes().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_searcher()

void Slic3r::GUI::Sidebar::update_searcher ( )
6829{
6830 p->searcher.init(get_search_inputs(m_mode));
6831}
static std::vector< Search::InputInfo > get_search_inputs(ConfigOptionMode mode)
Definition Plater.cpp:6815

References Slic3r::GUI::get_search_inputs(), m_mode, and p.

Referenced by update_mode().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_sync_ams_btn_enable()

void Slic3r::GUI::Sidebar::update_sync_ams_btn_enable ( wxUpdateUIEvent & e)
private
2758 {
2759 if (m_last_slice_state != p->plater->is_background_process_slicing()) {
2760 m_last_slice_state = p->plater->is_background_process_slicing();
2761 //btn_sync->Enable(!m_last_slice_state);
2762 p->m_printer_bbl_sync->Enable(!m_last_slice_state);
2763 ams_btn->Enable(!m_last_slice_state);
2764 Refresh();
2765 }
2766 }
bool m_last_slice_state
Definition Plater.hpp:161

References ams_btn, m_last_slice_state, and p.

Referenced by Sidebar().

Here is the caller graph for this function:

◆ update_sync_status()

void Slic3r::GUI::Sidebar::update_sync_status ( const MachineObject * obj)
6199{
6200 p->update_sync_status(obj);
6201}

References p.

Referenced by Slic3r::GUI::MonitorPanel::on_machine_selected().

Here is the caller graph for this function:

◆ update_ui_from_settings()

void Slic3r::GUI::Sidebar::update_ui_from_settings ( )
6864{
6865 // BBS
6866 //p->object_manipulation->update_ui_from_settings();
6867 // update Cut gizmo, if it's open
6868 p->plater->canvas3D()->update_gizmos_on_off_state();
6869 p->plater->set_current_canvas_as_dirty();
6870 p->plater->get_current_canvas3D()->request_extra_frame();
6871#if 0
6872 p->object_list->apply_volumes_order();
6873#endif
6874}

References p.

Referenced by create_printer_preset(), on_filament_count_change(), and on_filaments_delete().

Here is the caller graph for this function:

Member Data Documentation

◆ ams_btn

ScalableButton* Slic3r::GUI::Sidebar::ams_btn {nullptr}
private

◆ m_begin_sync_printer_status

bool Slic3r::GUI::Sidebar::m_begin_sync_printer_status {false}
private
167{false};

Referenced by deal_btn_sync(), and update_all_preset_comboboxes().

◆ m_cur_combox_bed_types

std::vector<BedType> Slic3r::GUI::Sidebar::m_cur_combox_bed_types
private

◆ m_cur_image_bed_type

std::string Slic3r::GUI::Sidebar::m_cur_image_bed_type
private

◆ m_fna_dialog

FinishSyncAmsDialog* Slic3r::GUI::Sidebar::m_fna_dialog {nullptr}
private

◆ m_last_combo_bedtype_count

int Slic3r::GUI::Sidebar::m_last_combo_bedtype_count {0}
private
166{0};

Referenced by reset_bed_type_combox_choices().

◆ m_last_slice_state

bool Slic3r::GUI::Sidebar::m_last_slice_state = false
private

◆ m_mode

ConfigOptionMode Slic3r::GUI::Sidebar::m_mode
private

Referenced by update_mode(), and update_searcher().

◆ m_need_auto_sync_after_connect_printer

bool Slic3r::GUI::Sidebar::m_need_auto_sync_after_connect_printer {false}
private

◆ m_scrolled_sizer

wxBoxSizer* Slic3r::GUI::Sidebar::m_scrolled_sizer = nullptr
private

◆ m_sna_dialog

SyncNozzleAndAmsDialog* Slic3r::GUI::Sidebar::m_sna_dialog {nullptr}
private

◆ m_sync_dlg

SyncAmsInfoDialog* Slic3r::GUI::Sidebar::m_sync_dlg {nullptr}
private
168{nullptr};

Referenced by sync_ams_list().

◆ p

std::unique_ptr<priv> Slic3r::GUI::Sidebar::p
private

Referenced by Sidebar(), add_custom_filament(), add_filament(), add_mixed_filament(), auto_calc_flushing_volumes(), can_search(), change_top_border_for_mode_sizer(), clear_combos_filament_badge(), collapse(), collect_physical_filament_info(), combos_filament(), create_printer_preset(), deal_btn_sync(), decompose_filament_color(), delete_filament(), edit_filament(), enable_buttons(), enable_nozzle_count_edit(), enable_purge_mode_btn(), ensure_mixed_filament(), filament_panel(), finish_param_edit(), get_big_btn_sync_pos_size(), get_cur_select_bed_type(), get_search_line(), get_searcher(), get_wiping_dialog_button(), has_broken_mixed_filament(), init_filament_combo(), is_collapsed(), is_fila_switch_ready(), is_multifilament(), is_new_project_in_gcode3mf(), jump_to_object(), jump_to_option(), load_ams_list(), msw_rescale(), obj_layers(), obj_list(), obj_settings(), og_freq_chng_params(), on_bed_type_change(), on_enter_image_printer_bed(), on_filament_count_change(), on_filaments_delete(), on_leave_image_printer_bed(), print_panel(), printer_combox(), recalc_filament_scroll_sizes(), remove_unused_filament_combos(), reset_bed_type_combox_choices(), reset_fila_switch(), scrolled_panel(), search(), set_bed_type_accord_combox(), set_btn_label(), set_extruder_nozzle_count(), set_flushing_volume_warning(), settings_index(), show_export(), show_export_removable(), show_object_list(), show_reslice(), show_SEMM_buttons(), show_send(), sync_ams_list(), sync_extruder_list(), sys_color_changed(), udpate_combos_filament_badge(), update_all_preset_comboboxes(), update_filaments_area_height(), update_filaments_counter(), update_mixed_filament_list(), update_presets(), update_presets_from_to(), update_printer_thumbnail(), update_searcher(), update_sync_ams_btn_enable(), update_sync_status(), and update_ui_from_settings().


The documentation for this class was generated from the following files:
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/GUI/Plater.hpp
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/GUI/Plater.cpp