Files
OrcaSlicer/src/slic3r/GUI/PublishSettingsDialog.hpp
T
HanifKoh 1a5f91d727 Add Missing Includes Across src/slic3r/GUI (#16048)
* Add Missing Includes Across src/slic3r/GUI

Every GUI source and header now directly includes the headers declaring what it uses, rather than relying on the precompiled header or transitive includes. Generated with clang-tidy misc-include-cleaner, plus one hand edit making CalibrationPanel.hpp self-contained.

* Drop the OS-Specific Includes Added Outside Their Platform Guards

GLib, GTK, D-Bus and POSIX headers are only used inside platform #if blocks, which already include them. Added unconditionally at the top of the file they broke the Windows build.

* Add the clang-tidy Configuration That Generated These Includes

Only misc-include-cleaner's missing-include check, with the headers it must never suggest: per-platform, internal and OS-specific ones that would break other platforms or are not meant to be included directly.

* Match Windows Paths in the clang-tidy Ignore List

Header paths use backslashes on Windows, so every / in a pattern is now [/\\]. The Windows SDK headers are ignored alongside the other OS-specific ones, and the list is one pattern per line. Suggested by @raistlin7447 from a Windows clang-cl run.
2026-10-02 14:56:56 +08:00

297 lines
14 KiB
C++

#pragma once
#include "GUI_Utils.hpp"
#include "wxExtensions.hpp"
#include "Widgets/TabCtrl.hpp"
#include "libslic3r/PublishSettings.hpp"
#include <cstddef>
#include <wx/string.h>
#include <wx/sizer.h>
#include <wx/panel.h>
#include <wx/gdicmn.h>
#include <wx/event.h>
#include <wx/wx.h>
#include <wx/colour.h>
#include <wx/scrolwin.h>
#include <wx/menu.h>
#include <utility>
#include <vector>
#include <string>
// Forward declarations (all are global classes, see Widgets/TextInput.hpp and
// Widgets/StaticLine.hpp).
class TextInput;
class StaticLine;
class CheckBox;
namespace Slic3r { namespace GUI {
struct PublishMaterialIdentity
{
std::string type;
std::string vendor;
std::string id;
};
// One unmet dependency of an enabled mixed-filament slot: the component filament the mix uses
// would ship without its material (either the component slot is not enabled at all, or it is
// enabled with neither "Full Publish" nor the "Type" requirement checked). Slots are 0-based.
struct MixedDependencyIssue
{
enum class Reason { Disabled, MaterialNotPublished };
size_t mixed_slot{0};
size_t component_slot{0};
Reason reason{Reason::Disabled};
};
// Dialog letting a model author select which settings get embedded in a 3MF. Nested tab layout
// mirroring the Process settings (Printer / Filament / Process outer tabs, category or material
// tabs inside each). Dirty settings are pre-checked and shown bold; on OK the print rows become
// "orca_published_keys" and the material rows become "orca_published_material_keys".
class PublishSettingsDialog : public DPIDialog
{
public:
// Optional published selection (Feature A/B): when the caller supplies one (either a
// remembered session selection or the payload of a freshly loaded published 3MF) the dialog
// is seeded from it, overriding the dirty-default pre-check. A non-null pointer to an empty
// selection means "publish nothing" (an intentional empty state); a null pointer means "no
// remembered selection" (keep the dirty defaults).
PublishSettingsDialog(wxWindow* parent = nullptr,
const std::vector<std::string>* published_keys = nullptr,
const std::vector<Slic3r::PublishedMaterialEntry>* material_keys = nullptr);
~PublishSettingsDialog();
// The selected print/printer setting keys (in display order); printer keys carry a '#N'
// per-extruder suffix.
std::vector<std::string> GetPublishedKeys() const;
// The selected keys grouped per material section (base keys, no '#N' suffix).
std::vector<Slic3r::PublishedMaterialEntry> GetPublishedMaterialKeys() const;
protected:
void on_dpi_changed(const wxRect& suggested_rect) override;
void on_sys_color_changed() override;
private:
void fit_to_content();
void refresh_mixed_tab_bitmaps();
// Which part of the settings the row/category came from.
enum class Section { Print, Printer, Material };
// One selectable setting row: a checkbox (setting name) plus a value label and an optional
// grey unit label. key is the full config key, possibly with a "#N" variant suffix
// (print/printer rows); material rows carry the base key.
enum class RowKind {
Setting, // a regular setting key
Color, // material colour requirement (filament_colour)
Type, // material type requirement (read-only text)
};
struct Row
{
std::string key;
wxString category;
wxString subcategory;
wxString label;
wxString value;
wxString unit;
wxString section_title; // outer tab title, for filter matching
Section section{Section::Print};
RowKind kind{RowKind::Setting};
size_t outer_index{0};
size_t inner_index{0};
bool dirty{false}; // matches a dirty base key: pre-checked + bold
bool matches_filter{false}; // survives the active filter (computed by apply_filter)
::CheckBox* check{nullptr};
wxStaticText* check_label{nullptr};
wxStaticText* value_label{nullptr};
wxStaticText* unit_label{nullptr};
wxStaticBitmap* color_chip{nullptr}; // Color rows only; swatch next to the value
wxSizerItem* item{nullptr}; // sizer item of this row's h-sizer in its tab list sizer
};
// An optgroup heading. Rows store indices into m_rows.
struct Subcategory
{
wxString title;
::StaticLine* header{nullptr}; // null when the title is empty
wxSizerItem* item{nullptr};
std::vector<size_t> rows;
};
// An inner TabCtrl page with its material controls and content.
struct Category
{
wxString title;
Section section{Section::Print};
size_t group{0}; // index into m_sections / outer page
size_t source_index{0}; // stable source page or material slot index
wxPanel* page{nullptr};
wxScrolledWindow* scroll{nullptr};
wxBoxSizer* list_sizer{nullptr};
wxStaticText* info{nullptr};
wxPoint scroll_pos{0, 0};
wxStaticBitmap* filament_color_chip{nullptr};
wxStaticText* title_label{nullptr}; // material title (static text; Full Publish carries the label elsewhere)
// "Enable": while unchecked nothing of this slot is exported and everything below the
// header row is hidden. For physical slots the Full Publish toggle sits on a second
// line (full_line_item) visible only when enabled; for mixed slots Enable alone implies
// publishing the mix definition, so no Full Publish widget exists at all.
::CheckBox* enable_check{nullptr};
wxStaticText* enable_label{nullptr};
wxSizerItem* full_line_item{nullptr}; // sizer item of the Full Publish line (physical slots only)
// "Full Publish": while checked, the whole slot preset is serialized and its rows
// (incl. Color/Type) are disabled.
::CheckBox* full_check{nullptr};
wxStaticText* full_label{nullptr};
// True for a mixed-color filament slot: no Material/Retraction rows; Enable publishes
// the slot's gradient/ratio definition as a whole.
bool is_mixed{false};
// Material identity, only for Section::Material categories.
std::string filament_type;
std::string filament_vendor;
std::string filament_id;
// The author's 0-based filament slot this material section represents.
size_t filament_slot{0};
std::vector<Subcategory> subs;
std::vector<size_t> rows; // flattened rows of this category
};
// Frozen snapshot of a mixed filament slot's definition for the read-only visualization
// painted on the slot's page. Plain data only: the paint handler must never touch the
// config. For gradient slots the curve is pre-sampled (t, ratio) pairs, where ratio is the
// first component's share over model height; anchors carry the raw control points.
struct MixedVisualSpec
{
bool valid{false};
bool is_gradient{false};
std::vector<wxColour> component_colours; // colour per component, in config order
std::vector<double> ratios; // sublayer shares summing to ~1 (non-gradient)
std::vector<double> tri_weights; // 3-component mixes: barycentric shares
std::vector<std::pair<double, double>> gradient_samples;
std::vector<std::pair<double, double>> gradient_anchors;
};
// One outer TabCtrl page. Category entries are its inner tabs.
struct SectionGroup
{
wxString title; // _L("Printer") / _L("Filament") / _L("Process")
Section kind{Section::Print}; // maps 1:1 to the display group
std::string icon_name; // "printer" / "filament" / "process"
ScalableBitmap icon_bmp; // tab icon next to the title; rescaled on DPI change
wxPanel* page{nullptr};
TabCtrl* tabs{nullptr};
// Second tab strip, below the main one, listing only the mixed-color filament slots.
// Present on the Material section only (null elsewhere).
TabCtrl* mixed_tabs{nullptr};
wxPanel* page_host{nullptr};
wxBoxSizer* page_host_sizer{nullptr};
int selected_inner{-1};
// Selected mixed tab (index into mixed_categories), valid while a mixed slot page is shown.
int selected_mixed{-1};
std::vector<size_t> categories; // indices into m_categories (physical slots)
std::vector<size_t> mixed_categories; // indices into m_categories (mixed slots)
};
void build_option_model();
// Seed the dialog from a published selection (print/printer keys + per-slot material keys):
// the supplied selection is authoritative - it is applied after the dirty pre-check and
// overrides it, so deselected dirty keys stay off. Rows/slots not present in the selection
// are left unselected. Unknown or out-of-range entries are skipped gracefully.
void apply_selection(const std::vector<std::string>& published_keys,
const std::vector<Slic3r::PublishedMaterialEntry>& material_keys);
// Frozen snapshot of a mixed slot's definition for the page visualization, resolved from
// the full config once at dialog-build time. Gradient slots pre-sample exactly what the
// slicer will print: the custom curve wins over the gradient_range endpoints over the
// 0.10 -> 0.90 default (the resolution FilamentBitmapUtils::mixed_gradient_curve mirrors).
static MixedVisualSpec make_mixed_visual_spec(const Slic3r::DynamicPrintConfig& full, size_t slot);
void apply_filter(const wxString& filter_text);
// Menu-only pseudo filters: show only the checked ("Filter selected") or only the
// unchecked ("Filter non-selected") rows. The search box keeps the user's text.
void apply_pseudo_filter(bool selected_only);
// Recompute row matches and visibility for the active filter mode. filter is the lowered
// search text; it is ignored by the pseudo modes.
void refresh_filter(const wxString& filter);
void select_all(bool value);
void select_visible(bool value);
void show_menu(wxMouseEvent& evt);
void set_row_bold(Row& row, bool bold);
// "Full Publish" toggled: disables/enables the material's rows.
void on_full_toggle(size_t category_index);
// "Enable" toggled on a material slot: reveals/hides everything below the header and, for a
// mixed slot, auto-selects its component filaments' "Enable" + "Full Publish" toggles.
void on_enable_toggle(size_t category_index);
// Whether a category currently publishes something, driving its tab's indicator dot.
// Print/Printer: any row checked. Material: the slot's "Enable" is on.
bool category_has_selection(const Category& cat) const;
// Recompute the indicator dot on every outer/inner tab from the current selection state.
void refresh_tab_indicators();
// Unmet dependencies of enabled mixed-filament slots, one record per (mix, component) pair:
// "Enable" not checked on the component, or enabled with neither "Full Publish" nor the
// "Type" requirement row checked. Colour is deliberately ignored (the receiver renders the
// mix from its own components' colours). Sorted by mixed slot, then component slot.
std::vector<MixedDependencyIssue> unpublished_mixed_components() const;
// Read-only visualization of a mixed slot's definition (a stacked ratio bar, or the
// Material Ratio vs Model Height graph for a gradient), inserted above the info hint
// inside the category's scroll area.
void add_mixed_visual(size_t category_index, const MixedVisualSpec& spec);
// Return/create the fixed outer page for a Section kind.
size_t section_group_for(Section kind);
size_t category_index_for(const wxString& title,
Section section,
size_t group,
size_t source_index,
const PublishMaterialIdentity& identity = PublishMaterialIdentity(),
bool is_mixed = false);
size_t subcategory_index_for(size_t category_index, const wxString& title, const wxString& icon);
void add_row_ui(const std::string& key,
const wxString& label,
const wxString& value,
const wxString& unit,
size_t category_index,
size_t subcategory_index,
RowKind kind = RowKind::Setting);
// The non-structural filament keys of a slot's preset, for a "Full Publish" entry.
std::vector<std::string> full_keys_for_slot() const;
void save_scroll_position(Category& category);
void show_outer_page(size_t section_index);
void show_inner_page(size_t section_index, int inner_index);
void show_mixed_page(size_t section_index, int mixed_index);
void on_outer_tab_changed(wxCommandEvent& event);
void on_inner_tab_changed(size_t section_index, wxCommandEvent& event);
void on_mixed_tab_changed(size_t section_index, wxCommandEvent& event);
bool row_is_visible(const Row& row) const;
void apply_visibility();
void bind_tab_events();
TabCtrl* m_outer_tabs{nullptr};
wxPanel* m_outer_host{nullptr};
wxBoxSizer* m_outer_host_sizer{nullptr};
int m_selected_outer{-1};
wxBoxSizer* m_fb_sizer{nullptr}; // "All"/"None" buttons sizer
// Active filter mode: free text from the search box, or one of the menu's pseudo filters.
enum class FilterMode { Text, SelectedOnly, UnselectedOnly };
FilterMode m_filter_mode{FilterMode::Text};
TextInput* m_filter_box{nullptr};
wxTextCtrl* m_filter_ctrl{nullptr};
wxStaticBitmap* m_menu_button{nullptr};
// Shown while a pseudo filter is active (the search box keeps the user's text, so the chip
// carries the visible state); clicking it returns to text filtering.
wxStaticText* m_pseudo_chip{nullptr};
wxString m_info_nonsel;
wxString m_info_allsel;
wxString m_info_empty;
wxString m_info_mix; // body hint shown for a mixed slot (published as a whole)
ScalableBitmap m_search;
ScalableBitmap m_menu;
std::vector<Row> m_rows;
std::vector<Category> m_categories;
std::vector<SectionGroup> m_sections;
};
}} // namespace Slic3r::GUI