mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-08 00:01:09 +00:00
* Remove Unused Project Includes and Forward-Declare Where a Type Is Only Referenced Generated with include-what-you-use and applied conservatively. Only OrcaSlicer's own headers, the ones under src/ and tests/, are removed or forward-declared; standard-library and third-party includes are left alone. An include is removed only when both the Release and the Debug configuration leave it unused, never from inside a conditional block, and never from a file with platform-specific blocks, which only gain includes. Files whose only use of a header sits behind a feature or debug macro (libvgcode's OpenGL ES and marker code, the ARACHNE/TESTS_EXPORT_SVGS debug output) keep their includes. clonable_ptr.hpp gains #pragma once; it had no include guard and was only safe while Config.hpp was its sole includer. * Remove Unused Project Includes From Files With Platform-Specific Code A Linux include-what-you-use run cannot see the code inside _WIN32, __APPLE__ or __linux__ blocks, so its verdict is only taken where nothing the removed header declares, directly or through what it includes, is named inside those blocks. Removals also have to hold in both the Release and Debug configuration and never touch a line inside a conditional block. * Restore the libslic3r Precompiled Header and Direct Includes Lost in the Platform Pass The platform-file pass treated pchheader.hpp as an ordinary header and emptied it, and left GUI_Preview.hpp and 14 other files relying on headers they no longer reached directly. * Restore MainFrame.hpp in ParamsDialog.cpp for the Windows-Only Reparent Call * Include Headers That Files Reached Through Ones the Cleanup Removed * Drop Includes Duplicated by the Cleanup or by Main's Own Additions * Leave PreciseSeam.cpp as Main Has It After the Precise Seam Rework
752 lines
26 KiB
C++
752 lines
26 KiB
C++
#ifndef SLIC3R_GUI_FIELD_HPP
|
|
#define SLIC3R_GUI_FIELD_HPP
|
|
|
|
#include <string>
|
|
#include <wx/string.h>
|
|
#include "libslic3r/Point.hpp"
|
|
#include <vector>
|
|
#include <wx/colour.h>
|
|
#include <wx/sizer.h>
|
|
#include <wx/event.h>
|
|
#include <climits>
|
|
#include <wx/arrstr.h>
|
|
#include <cstddef>
|
|
#include <wx/wxprec.h>
|
|
#ifndef WX_PRECOMP
|
|
#include <wx/wx.h>
|
|
#endif
|
|
|
|
#include <memory>
|
|
#include <cstdint>
|
|
#include <functional>
|
|
#include <boost/any.hpp>
|
|
#include "I18N.hpp"
|
|
|
|
#include <wx/colourdata.h>
|
|
#include <wx/spinctrl.h>
|
|
#include <wx/bmpcbox.h>
|
|
#include <wx/clrpicker.h>
|
|
|
|
#include "libslic3r/libslic3r.h"
|
|
#include "libslic3r/Config.hpp"
|
|
|
|
#include "wxExtensions.hpp"
|
|
#include "Widgets/SpinInput.hpp"
|
|
|
|
class ComboBox;
|
|
class TextInput;
|
|
class wxBitmap;
|
|
class wxBoxSizer;
|
|
class wxCommandEvent;
|
|
class wxEvent;
|
|
class wxSizer;
|
|
|
|
#ifdef __WXMSW__
|
|
#define wxMSW true
|
|
#else
|
|
#define wxMSW false
|
|
#endif
|
|
|
|
// Orca's styled button (Widgets/Button.hpp), used by PluginConfigField. It lives at global scope.
|
|
class Button;
|
|
|
|
namespace Slic3r { namespace GUI {
|
|
|
|
class Field;
|
|
using t_field = std::unique_ptr<Field>;
|
|
using t_kill_focus = std::function<void(const std::string&)>;
|
|
using t_change = std::function<void(const t_config_option_key&, const boost::any&)>;
|
|
using t_back_to_init = std::function<void(const std::string&)>;
|
|
|
|
wxString double_to_string(double const value, const int max_precision = 4);
|
|
wxString get_thumbnail_string(const Vec2d& value);
|
|
wxString get_thumbnails_string(const std::vector<Vec2d>& values);
|
|
wxString get_formatted_tooltip_text(const ConfigOptionDef& opt, const t_config_option_key& id);
|
|
|
|
class UndoValueUIManager
|
|
{
|
|
struct UndoValueUI {
|
|
// Bitmap and Tooltip text for m_Undo_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
|
|
const ScalableBitmap* undo_bitmap{ nullptr };
|
|
const wxString* undo_tooltip{ nullptr };
|
|
// Bitmap and Tooltip text for m_Undo_to_sys_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
|
|
const ScalableBitmap* undo_to_sys_bitmap{ nullptr };
|
|
const wxString* undo_to_sys_tooltip{ nullptr };
|
|
// Color for Label. The wxColour will be updated only if the new wxColour pointer differs from the currently rendered one.
|
|
const wxColour* label_color{ nullptr };
|
|
// State of the blinker icon
|
|
bool blink{ false };
|
|
|
|
bool set_undo_bitmap(const ScalableBitmap* bmp) {
|
|
if (undo_bitmap != bmp) {
|
|
undo_bitmap = bmp;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool set_undo_to_sys_bitmap(const ScalableBitmap* bmp) {
|
|
if (undo_to_sys_bitmap != bmp) {
|
|
undo_to_sys_bitmap = bmp;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool set_label_colour(const wxColour* clr) {
|
|
if (label_color != clr) {
|
|
label_color = clr;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool set_undo_tooltip(const wxString* tip) {
|
|
if (undo_tooltip != tip) {
|
|
undo_tooltip = tip;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool set_undo_to_sys_tooltip(const wxString* tip) {
|
|
if (undo_to_sys_tooltip != tip) {
|
|
undo_to_sys_tooltip = tip;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
UndoValueUI m_undo_ui;
|
|
|
|
struct EditValueUI {
|
|
// Bitmap and Tooltip text for m_Edit_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
|
|
const ScalableBitmap* bitmap{ nullptr };
|
|
wxString tooltip { wxEmptyString };
|
|
|
|
bool set_bitmap(const ScalableBitmap* bmp) {
|
|
if (bitmap != bmp) {
|
|
bitmap = bmp;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool set_tooltip(const wxString& tip) {
|
|
if (tooltip != tip) {
|
|
tooltip = tip;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
EditValueUI m_edit_ui;
|
|
|
|
public:
|
|
UndoValueUIManager() {}
|
|
~UndoValueUIManager() {}
|
|
|
|
bool set_undo_bitmap(const ScalableBitmap* bmp) { return m_undo_ui.set_undo_bitmap(bmp); }
|
|
bool set_undo_to_sys_bitmap(const ScalableBitmap* bmp) { return m_undo_ui.set_undo_to_sys_bitmap(bmp); }
|
|
bool set_label_colour(const wxColour* clr) { return m_undo_ui.set_label_colour(clr); }
|
|
bool set_undo_tooltip(const wxString* tip) { return m_undo_ui.set_undo_tooltip(tip); }
|
|
bool set_undo_to_sys_tooltip(const wxString* tip) { return m_undo_ui.set_undo_to_sys_tooltip(tip); }
|
|
|
|
bool set_edit_bitmap(const ScalableBitmap* bmp) { return m_edit_ui.set_bitmap(bmp); }
|
|
bool set_edit_tooltip(const wxString& tip) { return m_edit_ui.set_tooltip(tip); }
|
|
|
|
// ui items used for revert line value
|
|
bool has_undo_ui() const { return m_undo_ui.undo_bitmap != nullptr; }
|
|
const ScalableBitmap* undo_bitmap() const { return m_undo_ui.undo_bitmap; }
|
|
const wxString* undo_tooltip() const { return m_undo_ui.undo_tooltip; }
|
|
const ScalableBitmap* undo_to_sys_bitmap() const { return m_undo_ui.undo_to_sys_bitmap; }
|
|
const wxString* undo_to_sys_tooltip() const { return m_undo_ui.undo_to_sys_tooltip; }
|
|
const wxColour* label_color() const { return m_undo_ui.label_color; }
|
|
|
|
// Extentions
|
|
|
|
// Search blinker
|
|
const bool blink() const { return m_undo_ui.blink; }
|
|
bool* get_blink_ptr() { return &m_undo_ui.blink; }
|
|
|
|
// Edit field button
|
|
bool has_edit_ui() const { return !m_edit_ui.tooltip.IsEmpty(); }
|
|
const wxBitmap* edit_bitmap() const { return &m_edit_ui.bitmap->bmp(); }
|
|
const wxString* edit_tooltip() const { return &m_edit_ui.tooltip; }
|
|
};
|
|
|
|
class Field : public UndoValueUIManager {
|
|
protected:
|
|
// factory function to defer and enforce creation of derived type.
|
|
virtual void PostInitialize();
|
|
|
|
/// Finish constructing the Field's wxWidget-related properties, including setting its own sizer, etc.
|
|
virtual void BUILD() = 0;
|
|
|
|
/// Call the attached on_kill_focus method.
|
|
//! It's important to use wxEvent instead of wxFocusEvent,
|
|
//! in another case we can't unfocused control at all
|
|
void on_kill_focus();
|
|
/// Call the attached on_change method.
|
|
void on_change_field();
|
|
|
|
class EnterPressed {
|
|
public:
|
|
EnterPressed(Field* field) :
|
|
m_parent(field){ m_parent->set_enter_pressed(true); }
|
|
~EnterPressed() { m_parent->set_enter_pressed(false); }
|
|
private:
|
|
Field* m_parent;
|
|
};
|
|
|
|
public:
|
|
/// Call the attached m_back_to_initial_value method.
|
|
void on_back_to_initial_value();
|
|
/// Call the attached m_back_to_sys_value method.
|
|
void on_back_to_sys_value();
|
|
/// Call the attached m_fn_edit_value method.
|
|
void on_edit_value();
|
|
|
|
virtual void propagate_value(){}
|
|
public:
|
|
/// parent wx item, opportunity to refactor (probably not necessary - data duplication)
|
|
wxWindow* m_parent {nullptr};
|
|
|
|
/// Function object to store callback passed in from owning object.
|
|
t_kill_focus m_on_kill_focus {nullptr};
|
|
|
|
/// Function object to store callback passed in from owning object.
|
|
t_change m_on_change {nullptr};
|
|
|
|
/// Function object to store callback passed in from owning object.
|
|
t_back_to_init m_back_to_initial_value{ nullptr };
|
|
t_back_to_init m_back_to_sys_value{ nullptr };
|
|
|
|
/// Callback function to edit field value
|
|
t_back_to_init m_fn_edit_value{ nullptr };
|
|
|
|
// This is used to avoid recursive invocation of the field change/update by wxWidgets.
|
|
bool m_disable_change_event {false};
|
|
bool m_is_modified_value {false};
|
|
bool m_is_nonsys_value {true};
|
|
|
|
/// Copy of ConfigOption for deduction purposes
|
|
const ConfigOptionDef m_opt {ConfigOptionDef()};
|
|
const t_config_option_key m_opt_id;//! {""};
|
|
int m_opt_idx = 0;
|
|
|
|
double opt_height{ 0.0 };
|
|
bool parent_is_custom_ctrl{ false };
|
|
|
|
/// Sets a value for this control.
|
|
/// subclasses should overload with a specific version
|
|
/// Postcondition: Method does not fire the on_change event.
|
|
virtual void set_value(const boost::any& value, bool change_event) = 0;
|
|
virtual void set_last_meaningful_value() {}
|
|
virtual void set_na_value() {}
|
|
|
|
virtual void update_na_value(const boost::any& value) {}
|
|
|
|
/// Gets a boost::any representing this control.
|
|
/// subclasses should overload with a specific version
|
|
virtual boost::any& get_value() = 0;
|
|
|
|
virtual void enable() = 0;
|
|
virtual void disable() = 0;
|
|
|
|
/// Fires the enable or disable function, based on the input.
|
|
void toggle(bool en);
|
|
|
|
virtual wxString get_tooltip_text(const wxString& default_string);
|
|
|
|
void field_changed() { on_change_field(); }
|
|
|
|
Field(const ConfigOptionDef& opt, const t_config_option_key& id) : m_opt(opt), m_opt_id(id) {}
|
|
Field(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : m_parent(parent), m_opt(opt), m_opt_id(id) {}
|
|
virtual ~Field();
|
|
|
|
/// If you don't know what you are getting back, check both methods for nullptr.
|
|
virtual wxSizer* getSizer() { return nullptr; }
|
|
virtual wxWindow* getWindow() { return nullptr; }
|
|
|
|
bool is_matched(const std::string& string, const std::string& pattern);
|
|
void get_value_by_opt_type(wxString& str, const bool check_value = true);
|
|
|
|
/// Factory method for generating new derived classes.
|
|
template<class T>
|
|
static t_field Create(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id)// interface for creating shared objects
|
|
{
|
|
auto p = Slic3r::make_unique<T>(parent, opt, id);
|
|
p->PostInitialize();
|
|
return std::move(p); //!p;
|
|
}
|
|
|
|
virtual void msw_rescale();
|
|
virtual void sys_color_changed();
|
|
|
|
bool get_enter_pressed() const { return bEnterPressed; }
|
|
void set_enter_pressed(bool pressed) { bEnterPressed = pressed; }
|
|
|
|
// Values of width to alignments of fields
|
|
static int def_width() ;
|
|
static int def_width_wider() ;
|
|
static int def_width_thinner() ;
|
|
|
|
const bool combine_side_text() { return m_combine_side_text; } // BBS: new param style
|
|
|
|
protected:
|
|
// current value
|
|
boost::any m_value;
|
|
// last maeningful value
|
|
boost::any m_last_meaningful_value;
|
|
|
|
int m_em_unit;
|
|
bool m_combine_side_text = false;
|
|
|
|
bool bEnterPressed = false;
|
|
|
|
wxString m_na_value = _(L("N/A"));
|
|
|
|
friend class OptionsGroup;
|
|
};
|
|
|
|
/// Convenience function, accepts a const reference to t_field and checks to see whether
|
|
/// or not both wx pointers are null.
|
|
inline bool is_bad_field(const t_field& obj) { return obj->getSizer() == nullptr && obj->getWindow() == nullptr; }
|
|
|
|
/// Covenience function to determine whether this field is a valid window field.
|
|
inline bool is_window_field(const t_field& obj) { return !is_bad_field(obj) && obj->getWindow() != nullptr && obj->getSizer() == nullptr; }
|
|
|
|
/// Covenience function to determine whether this field is a valid sizer field.
|
|
inline bool is_sizer_field(const t_field& obj) { return !is_bad_field(obj) && obj->getSizer() != nullptr; }
|
|
|
|
class TextCtrl : public Field {
|
|
using Field::Field;
|
|
#ifdef __WXGTK__
|
|
bool bChangedValueEvent = true;
|
|
void change_field_value(wxEvent& event);
|
|
#endif //__WXGTK__
|
|
|
|
public:
|
|
TextCtrl(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {}
|
|
TextCtrl(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {}
|
|
~TextCtrl() {}
|
|
|
|
void BUILD() override;
|
|
bool value_was_changed();
|
|
// Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER
|
|
virtual void propagate_value() override;
|
|
wxWindow* window {nullptr};
|
|
|
|
void set_value(const std::string& value, bool change_event = false) {
|
|
m_disable_change_event = !change_event;
|
|
dynamic_cast<wxTextCtrl*>(window)->SetValue(wxString(value));
|
|
m_disable_change_event = false;
|
|
}
|
|
void set_value(const boost::any& value, bool change_event = false) override;
|
|
void set_last_meaningful_value() override;
|
|
void set_na_value() override;
|
|
|
|
void update_na_value(const boost::any& value) override;
|
|
|
|
boost::any& get_value() override;
|
|
|
|
void msw_rescale() override;
|
|
|
|
void enable() override;
|
|
void disable() override;
|
|
wxWindow* getWindow() override { return window; }
|
|
wxTextCtrl * text_ctrl();
|
|
};
|
|
|
|
class CheckBox : public Field {
|
|
using Field::Field;
|
|
bool m_is_na_val {false};
|
|
public:
|
|
CheckBox(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {}
|
|
CheckBox(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {}
|
|
~CheckBox() {}
|
|
|
|
wxWindow* window{ nullptr };
|
|
void BUILD() override;
|
|
|
|
void set_value(const bool value, bool change_event = false);
|
|
void set_value(const boost::any& value, bool change_event = false) override;
|
|
void set_last_meaningful_value() override;
|
|
void set_na_value() override;
|
|
boost::any& get_value() override;
|
|
|
|
void msw_rescale() override;
|
|
|
|
void enable() override { window->Enable(); }
|
|
void disable() override { window->Disable(); }
|
|
wxWindow* getWindow() override { return window; }
|
|
};
|
|
|
|
class SpinCtrl : public Field {
|
|
using Field::Field;
|
|
private:
|
|
static const int UNDEF_VALUE = INT_MIN;
|
|
|
|
bool suppress_propagation {false};
|
|
public:
|
|
SpinCtrl(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id), tmp_value(UNDEF_VALUE) {}
|
|
SpinCtrl(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id), tmp_value(UNDEF_VALUE) {}
|
|
~SpinCtrl() {}
|
|
|
|
int tmp_value;
|
|
|
|
wxWindow* window{ nullptr };
|
|
void BUILD() override;
|
|
/// Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER
|
|
void propagate_value() override;
|
|
|
|
void set_value(const std::string& value, bool change_event = false) {
|
|
m_disable_change_event = !change_event;
|
|
dynamic_cast<SpinInput*>(window)->SetValue(value);
|
|
m_disable_change_event = false;
|
|
}
|
|
void set_value(const boost::any& value, bool change_event = false) override;
|
|
|
|
boost::any& get_value() override {
|
|
int value = static_cast<SpinInput*>(window)->GetValue();
|
|
return m_value = value;
|
|
}
|
|
|
|
void msw_rescale() override;
|
|
|
|
void enable() override { dynamic_cast<SpinInput*>(window)->Enable(); }
|
|
void disable() override { dynamic_cast<SpinInput*>(window)->Disable(); }
|
|
wxWindow* getWindow() override { return window; }
|
|
};
|
|
|
|
class Choice;
|
|
|
|
class DynamicList
|
|
{
|
|
public:
|
|
virtual ~DynamicList() {}
|
|
virtual void apply_on(Choice * choice) = 0;
|
|
virtual wxString get_value(int index) = 0;
|
|
virtual int index_of(wxString value) = 0;
|
|
|
|
protected:
|
|
void update();
|
|
|
|
std::vector<Choice*> m_choices;
|
|
|
|
private:
|
|
friend class Choice;
|
|
void add_choice(Choice *choice);
|
|
void remove_choice(Choice *choice);
|
|
};
|
|
|
|
class Choice : public Field {
|
|
using Field::Field;
|
|
DynamicList * m_list = nullptr;
|
|
public:
|
|
Choice(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {}
|
|
Choice(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {}
|
|
~Choice();
|
|
|
|
static void register_dynamic_list(std::string const &optname, DynamicList *list);
|
|
|
|
wxWindow* window{ nullptr };
|
|
void BUILD() override;
|
|
// Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER
|
|
void propagate_value() override;
|
|
|
|
/* Under OSX: wxBitmapComboBox->GetWindowStyle() returns some weard value,
|
|
* so let use a flag, which has TRUE value for a control without wxCB_READONLY style
|
|
*/
|
|
bool m_is_editable { false };
|
|
bool m_is_dropped { false };
|
|
bool m_suppress_scroll { false };
|
|
int m_last_selected { wxNOT_FOUND };
|
|
|
|
void set_selection();
|
|
void set_value(const std::string& value, bool change_event = false);
|
|
void set_value(const boost::any& value, bool change_event = false) override;
|
|
void set_values(const std::vector<std::string> &values);
|
|
void set_values(const wxArrayString &values);
|
|
boost::any& get_value() override;
|
|
|
|
void set_last_meaningful_value() override;
|
|
void set_na_value() override;
|
|
|
|
void msw_rescale() override;
|
|
|
|
void enable() override ;//{ dynamic_cast<wxBitmapComboBox*>(window)->Enable(); };
|
|
void disable() override;//{ dynamic_cast<wxBitmapComboBox*>(window)->Disable(); };
|
|
wxWindow* getWindow() override { return window; }
|
|
|
|
void suppress_scroll();
|
|
};
|
|
|
|
// printer_agent is a coString whose choices come from the live agent registry.
|
|
// PrinterAgentChoice uses a ComboBox directly because Choice expects static config enums.
|
|
// Real rows carry the stored agent id in the row alias (SetItemAlias/GetItemAlias).
|
|
class PrinterAgentChoice : public Field
|
|
{
|
|
using Field::Field;
|
|
|
|
public:
|
|
PrinterAgentChoice(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id)
|
|
{
|
|
}
|
|
|
|
PrinterAgentChoice(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(
|
|
parent, opt, id)
|
|
{
|
|
}
|
|
|
|
~PrinterAgentChoice()
|
|
{
|
|
}
|
|
|
|
wxWindow* window{nullptr};
|
|
|
|
void BUILD() override;
|
|
// Clear and repopulate rows from the live registry (grouped System agents / Plugins).
|
|
// Does not change selection; the caller follows with set_value(stored id).
|
|
void reload_rows();
|
|
|
|
void set_value(const std::string& value, bool change_event = false);
|
|
void set_value(const boost::any& value, bool change_event = false) override;
|
|
boost::any& get_value() override;
|
|
|
|
void enable() override;
|
|
void disable() override;
|
|
void msw_rescale() override;
|
|
wxWindow* getWindow() override { return window; }
|
|
};
|
|
|
|
class PluginField : public Field {
|
|
using Field::Field;
|
|
public:
|
|
PluginField(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {}
|
|
PluginField(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {}
|
|
~PluginField() {}
|
|
|
|
void BUILD() override;
|
|
|
|
void set_selector(std::function<std::string()> selector);
|
|
|
|
void set_value(const boost::any& value, bool change_event = false) override;
|
|
boost::any& get_value() override;
|
|
|
|
void enable() override;
|
|
void disable() override;
|
|
|
|
// The rows live in one container panel (the base `window`), so the field exposes a window instead
|
|
// of a bare sizer and focus, sizing and teardown apply to the whole field.
|
|
wxWindow* getWindow() override { return window; }
|
|
|
|
void msw_rescale() override;
|
|
|
|
private:
|
|
struct PluginRow {
|
|
ComboBox* display { nullptr };
|
|
ScalableButton* remove_btn { nullptr };
|
|
wxBoxSizer* sizer { nullptr };
|
|
};
|
|
|
|
void rebuild_ui();
|
|
void add_empty_state_row();
|
|
void add_plugin_row(const wxString& value = wxEmptyString, bool is_last = false);
|
|
wxString display_name_for_value(const std::string& value) const;
|
|
void on_select_clicked(size_t index);
|
|
void on_add_clicked();
|
|
void on_remove_clicked(size_t index);
|
|
wxString get_row_value(size_t index) const;
|
|
void set_row_value(size_t index, const wxString& value);
|
|
|
|
wxWindow* window { nullptr }; // container panel that hosts m_main_sizer
|
|
wxBoxSizer* m_main_sizer { nullptr };
|
|
std::vector<PluginRow> m_rows;
|
|
std::vector<std::string> m_values;
|
|
Button* m_standalone_add_btn { nullptr };
|
|
std::function<std::string()> m_selector;
|
|
};
|
|
|
|
// A settings row whose value is a raw JSON document nobody types by hand: the button opens
|
|
// PluginsConfigDialog and the document it hands back becomes the field's value. The edit goes through
|
|
// the ordinary Field value/on_change_field path, so the row gets the same dirty state and revert arrow
|
|
// as any other setting — the dialog never touches the preset.
|
|
class PluginConfigField : public Field {
|
|
using Field::Field;
|
|
public:
|
|
PluginConfigField(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {}
|
|
PluginConfigField(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {}
|
|
~PluginConfigField() {}
|
|
|
|
void BUILD() override;
|
|
|
|
// Which preset's capabilities the dialog lists; set by the option group. An int for the same
|
|
// reason OptionsGroup::m_config_type is one: it keeps Preset.hpp out of this header.
|
|
void set_preset_type(int type) { m_preset_type = type; }
|
|
|
|
void set_value(const boost::any& value, bool change_event = false) override;
|
|
boost::any& get_value() override;
|
|
|
|
void enable() override;
|
|
void disable() override;
|
|
|
|
// The button is the whole field, so it is the window the option group sizes and positions (the
|
|
// ColourPicker idiom). A container panel would be sized but never laid out, collapsing the row.
|
|
wxWindow* getWindow() override { return window; }
|
|
|
|
void msw_rescale() override;
|
|
|
|
private:
|
|
void open_dialog();
|
|
void update_button_label();
|
|
|
|
wxWindow* window { nullptr }; // == m_button; the base class hands this to the option group
|
|
::Button* m_button { nullptr };
|
|
std::string m_json; // the option's raw text; "" when the preset overrides nothing
|
|
int m_preset_type { -1 };
|
|
};
|
|
|
|
class ColourPicker : public Field {
|
|
using Field::Field;
|
|
|
|
void set_undef_value(wxColourPickerCtrl* field);
|
|
void draw_bmp_btn(wxColourPickerCtrl* field, wxColour color);
|
|
public:
|
|
ColourPicker(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {}
|
|
ColourPicker(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {}
|
|
~ColourPicker() {}
|
|
|
|
wxWindow* window{ nullptr };
|
|
void BUILD() override;
|
|
|
|
void set_value(const std::string& value, bool change_event = false) {
|
|
m_disable_change_event = !change_event;
|
|
dynamic_cast<wxColourPickerCtrl*>(window)->SetColour(value);
|
|
m_disable_change_event = false;
|
|
}
|
|
void set_value(const boost::any& value, bool change_event = false) override;
|
|
boost::any& get_value() override;
|
|
void msw_rescale() override;
|
|
void sys_color_changed() override;
|
|
|
|
void enable() override { dynamic_cast<wxColourPickerCtrl*>(window)->Enable(); }
|
|
void disable() override{ dynamic_cast<wxColourPickerCtrl*>(window)->Disable(); }
|
|
wxWindow* getWindow() override { return window; }
|
|
|
|
private:
|
|
void convert_to_picker_widget(wxColourPickerCtrl *widget);
|
|
void on_button_click(wxCommandEvent &WXUNUSED(ev));
|
|
void save_colors_to_config();
|
|
private:
|
|
#if !defined(__linux__) && !defined(__LINUX__)
|
|
wxColourData* m_clrData{nullptr};
|
|
wxColourPickerWidget* m_picker_widget{nullptr};
|
|
#endif
|
|
};
|
|
|
|
class PointCtrl : public Field {
|
|
using Field::Field;
|
|
public:
|
|
PointCtrl(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {}
|
|
PointCtrl(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {}
|
|
~PointCtrl() {}
|
|
|
|
wxSizer* sizer{ nullptr };
|
|
wxTextCtrl* x_textctrl{ nullptr };
|
|
wxTextCtrl* y_textctrl{ nullptr };
|
|
TextInput* x_input{nullptr};
|
|
TextInput* y_input{nullptr};
|
|
|
|
wxWindow* window{nullptr};
|
|
void BUILD() override;
|
|
bool value_was_changed(wxTextCtrl* win);
|
|
// Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER
|
|
void propagate_input_value(wxTextCtrl* win);
|
|
void set_value(const Vec2d& value, bool change_event = false);
|
|
void set_value(const boost::any& value, bool change_event = false) override;
|
|
boost::any& get_value() override;
|
|
|
|
void msw_rescale() override;
|
|
void sys_color_changed() override;
|
|
|
|
void enable() override {
|
|
x_textctrl->Enable();
|
|
y_textctrl->Enable(); }
|
|
void disable() override{
|
|
x_textctrl->Disable();
|
|
y_textctrl->Disable(); }
|
|
wxSizer* getSizer() override { return sizer; }
|
|
wxWindow* getWindow() override { return window; }
|
|
};
|
|
|
|
class StaticText : public Field {
|
|
using Field::Field;
|
|
public:
|
|
StaticText(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {}
|
|
StaticText(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {}
|
|
~StaticText() {}
|
|
|
|
wxWindow* window{ nullptr };
|
|
void BUILD() override;
|
|
|
|
void set_value(const std::string& value, bool change_event = false) {
|
|
m_disable_change_event = !change_event;
|
|
dynamic_cast<wxStaticText*>(window)->SetLabel(wxString::FromUTF8(value.data()));
|
|
m_disable_change_event = false;
|
|
}
|
|
void set_value(const boost::any& value, bool change_event = false) override {
|
|
m_disable_change_event = !change_event;
|
|
dynamic_cast<wxStaticText*>(window)->SetLabel(boost::any_cast<wxString>(value));
|
|
m_disable_change_event = false;
|
|
}
|
|
|
|
boost::any& get_value()override { return m_value; }
|
|
|
|
void msw_rescale() override;
|
|
|
|
void enable() override { dynamic_cast<wxStaticText*>(window)->Enable(); }
|
|
void disable() override{ dynamic_cast<wxStaticText*>(window)->Disable(); }
|
|
wxWindow* getWindow() override { return window; }
|
|
};
|
|
|
|
class SliderCtrl : public Field {
|
|
using Field::Field;
|
|
public:
|
|
SliderCtrl(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {}
|
|
SliderCtrl(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {}
|
|
~SliderCtrl() {}
|
|
|
|
wxSizer* m_sizer{ nullptr };
|
|
wxTextCtrl* m_textctrl{ nullptr };
|
|
wxSlider* m_slider{ nullptr };
|
|
|
|
int m_scale = 10;
|
|
|
|
void BUILD() override;
|
|
|
|
void set_value(const int value, bool change_event = false);
|
|
void set_value(const boost::any& value, bool change_event = false) override;
|
|
boost::any& get_value() override;
|
|
|
|
void enable() override {
|
|
m_slider->Enable();
|
|
m_textctrl->Enable();
|
|
m_textctrl->SetEditable(true);
|
|
}
|
|
void disable() override{
|
|
m_slider->Disable();
|
|
m_textctrl->Disable();
|
|
m_textctrl->SetEditable(false);
|
|
}
|
|
wxSizer* getSizer() override { return m_sizer; }
|
|
wxWindow* getWindow() override { return dynamic_cast<wxWindow*>(m_slider); }
|
|
};
|
|
|
|
} // GUI
|
|
} // Slic3r
|
|
|
|
#endif /* SLIC3R_GUI_FIELD_HPP */
|