Skip to content

Commit 00ea44f

Browse files
committed
feat(gui): auto-save, fine arrow-key steps (0.1/0.01 mm) and dark-mode contrast fix
Rebased onto current master and reduced to the feature's own source changes; removed translation catalogs and unrelated files carried over from the branch base.
1 parent 3f126b7 commit 00ea44f

11 files changed

Lines changed: 137 additions & 25 deletions

src/slic3r/GUI/AMSMaterialsSetting.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1990,13 +1990,41 @@ ColorPickerPopup::ColorPickerPopup(wxWindow* parent)
19901990
m_clrData->SetChooseAlpha(false);
19911991

19921992

1993+
// Hex colour input field
1994+
auto hex_sizer = new wxBoxSizer(wxHORIZONTAL);
1995+
auto hex_label = new wxStaticText(m_def_color_box, wxID_ANY, wxT("#"), wxDefaultPosition, wxDefaultSize, 0);
1996+
hex_label->SetFont(::Label::Body_12);
1997+
m_hex_input = new TextInput(m_def_color_box, wxEmptyString, wxEmptyString, wxEmptyString,
1998+
wxDefaultPosition, wxSize(FromDIP(80), FromDIP(24)), wxTE_PROCESS_ENTER);
1999+
m_hex_input->GetTextCtrl()->SetMaxLength(6);
2000+
m_hex_input->SetFont(::Label::Body_12);
2001+
m_hex_input->SetToolTip(_L("Enter a hex colour code (e.g. FF8800)"));
2002+
hex_sizer->Add(hex_label, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(4));
2003+
hex_sizer->Add(m_hex_input, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(2));
2004+
2005+
m_hex_input->GetTextCtrl()->Bind(wxEVT_TEXT_ENTER, [this](wxCommandEvent&) {
2006+
wxString hex = m_hex_input->GetTextCtrl()->GetValue().Trim().Upper();
2007+
if (hex.Length() == 6) {
2008+
unsigned long rgb = 0;
2009+
if (hex.ToULong(&rgb, 16)) {
2010+
wxColour col((rgb >> 16) & 0xff, (rgb >> 8) & 0xff, rgb & 0xff);
2011+
set_def_colour(col);
2012+
wxCommandEvent evt(EVT_SELECTED_COLOR);
2013+
unsigned long g_col = ((col.Red() & 0xff) << 24) | ((col.Green() & 0xff) << 16) | ((col.Blue() & 0xff) << 8) | 0xff;
2014+
evt.SetInt(g_col);
2015+
wxPostEvent(GetParent(), evt);
2016+
}
2017+
}
2018+
});
2019+
19932020
m_sizer_box->Add(0, 0, 0, wxTOP, FromDIP(10));
19942021
m_sizer_box->Add(m_sizer_ams, 1, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(10));
19952022
m_sizer_box->Add(m_ams_fg_sizer, 0, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(10));
19962023
m_sizer_box->Add(m_sizer_other, 1, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(10));
19972024
m_sizer_box->Add(fg_sizer, 0, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(10));
19982025
m_sizer_box->Add(m_sizer_custom, 0, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(10));
19992026
m_sizer_box->Add(m_custom_cp, 0, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(16));
2027+
m_sizer_box->Add(hex_sizer, 0, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(10));
20002028
m_sizer_box->Add(0, 0, 0, wxTOP, FromDIP(10));
20012029

20022030

@@ -2113,10 +2141,17 @@ void ColorPickerPopup::set_def_colour(wxColour col)
21132141

21142142
if (m_def_col.Alpha() == 0) {
21152143
m_ts_stbitmap_custom->Show();
2144+
if (m_hex_input)
2145+
m_hex_input->GetTextCtrl()->ChangeValue(wxEmptyString);
21162146
}
21172147
else {
21182148
m_ts_stbitmap_custom->Hide();
21192149
m_custom_cp->SetBackgroundColor(m_def_col);
2150+
if (m_hex_input) {
2151+
wxString hex = wxString::Format("%02X%02X%02X",
2152+
m_def_col.Red(), m_def_col.Green(), m_def_col.Blue());
2153+
m_hex_input->GetTextCtrl()->ChangeValue(hex);
2154+
}
21202155
}
21212156

21222157
Dismiss();

src/slic3r/GUI/AMSMaterialsSetting.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class ColorPickerPopup : public PopupWindow
7777
std::vector<wxColour> m_ams_colors;
7878
std::vector<ColorPicker*> m_color_pickers;
7979
std::vector<ColorPicker*> m_ams_color_pickers;
80+
TextInput* m_hex_input{nullptr};
8081

8182
public:
8283
ColorPickerPopup(wxWindow* parent);

src/slic3r/GUI/GLCanvas3D.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4330,7 +4330,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
43304330
class TranslationProcessor
43314331
{
43324332
using UpAction = std::function<void(void)>;
4333-
using DownAction = std::function<void(const Vec3d&, bool, bool)>;
4333+
using DownAction = std::function<void(const Vec3d&, bool, bool, bool)>;
43344334

43354335
UpAction m_up_action{ nullptr };
43364336
DownAction m_down_action{ nullptr };
@@ -4408,7 +4408,7 @@ class TranslationProcessor
44084408

44094409
if (apply) {
44104410
m_running = true;
4411-
m_down_action(m_direction, evt.ShiftDown(), evt.CmdDown());
4411+
m_down_action(m_direction, evt.ShiftDown(), evt.CmdDown(), evt.AltDown());
44124412
}
44134413
}
44144414
}
@@ -4434,12 +4434,12 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
44344434
refresh_camera_scene_box();
44354435
m_dirty = true;
44364436
},
4437-
[this](const Vec3d& direction, bool slow, bool camera_space) {
4437+
[this](const Vec3d& direction, bool slow, bool camera_space, bool fine) {
44384438
if (m_gizmos.is_ban_move_glvolume()) {
44394439
return;
44404440
}
44414441
m_selection.setup_cache();
4442-
double multiplier = slow ? 1.0 : 10.0;
4442+
double multiplier = fine ? (slow ? 0.01 : 0.1) : (slow ? 1.0 : 10.0);
44434443

44444444
Vec3d displacement;
44454445
if (camera_space) {

src/slic3r/GUI/GUI_App.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2061,10 +2061,14 @@ void GUI_App::init_networking_callbacks()
20612061
GUI::wxGetApp().CallAfter([this] {
20622062
static bool is_showing = false;
20632063
if (is_showing) return;
2064+
if (app_config && app_config->get("suppress_cloud_warnings") == "1") return;
20642065
is_showing = true;
20652066
BOOST_LOG_TRIVIAL(trace) << "static: server connection failed";
2066-
MessageDialog msg_dlg(nullptr, _L("Failed to connect to the cloud device server. Please check your network and firewall."), "", wxOK);
2067+
RichMessageDialog msg_dlg(nullptr, _L("Failed to connect to the cloud device server. Please check your network and firewall."), "", wxOK);
2068+
msg_dlg.ShowCheckBox(_L("Don't show this warning again"));
20672069
msg_dlg.ShowModal();
2070+
if (msg_dlg.IsCheckBoxChecked() && app_config)
2071+
app_config->set("suppress_cloud_warnings", "1");
20682072
is_showing = false;
20692073
});
20702074
return;
@@ -3019,11 +3023,18 @@ bool GUI_App::on_init_inner()
30193023
load_language(wxString(), true);
30203024
#ifdef _MSW_DARK_MODE
30213025

3022-
#ifndef __WINDOWS__
3023-
wxSystemAppearance app = wxSystemSettings::GetAppearance();
3024-
GUI::wxGetApp().app_config->set("dark_color_mode", app.IsDark() ? "1" : "0");
3025-
GUI::wxGetApp().app_config->save();
3026-
#endif // __APPLE__
3026+
{
3027+
wxSystemAppearance app = wxSystemSettings::GetAppearance();
3028+
#ifdef __WINDOWS__
3029+
if (app_config->get("dark_mode_follow_system") == "1") {
3030+
app_config->set("dark_color_mode", app.IsDark() ? "1" : "0");
3031+
app_config->save();
3032+
}
3033+
#else
3034+
GUI::wxGetApp().app_config->set("dark_color_mode", app.IsDark() ? "1" : "0");
3035+
GUI::wxGetApp().app_config->save();
3036+
#endif
3037+
}
30273038

30283039

30293040
bool init_dark_color_mode = dark_mode();
@@ -3649,7 +3660,9 @@ bool GUI_App::dark_mode()
36493660
// proper dark mode was first introduced.
36503661
return wxPlatformInfo::Get().CheckOSVersion(10, 14) && mac_dark_mode();
36513662
#else
3652-
return wxGetApp().app_config->get("dark_color_mode") == "1" ? true : check_dark_mode();
3663+
if (wxGetApp().app_config->get("dark_mode_follow_system") == "1")
3664+
return check_dark_mode();
3665+
return wxGetApp().app_config->get("dark_color_mode") == "1";
36533666
//const unsigned luma = get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
36543667
//return luma < 128;
36553668
#endif

src/slic3r/GUI/GUI_ObjectLayers.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,10 @@ LayerRangeEditor::LayerRangeEditor( ObjectLayers* parent,
351351
{
352352
this->SetFont(wxGetApp().normal_font());
353353
wxGetApp().UpdateDarkUI(this);
354+
if (wxGetApp().dark_mode()) {
355+
SetBackgroundColour(wxGetApp().get_window_default_clr());
356+
SetForegroundColour(wxGetApp().get_label_clr_default());
357+
}
354358

355359
// Reset m_enter_pressed flag to _false_, when value is editing
356360
this->Bind(wxEVT_TEXT, [this](wxEvent&) { m_enter_pressed = false; }, this->GetId());

src/slic3r/GUI/GUI_Utils.hpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,12 +201,17 @@ template<class P> class DPIAware : public P
201201

202202
this->Bind(wxEVT_SYS_COLOUR_CHANGED, [this](wxSysColourChangedEvent& event)
203203
{
204-
#ifndef __WINDOWS__
204+
#ifdef __WINDOWS__
205+
if (GUI::wxGetApp().app_config &&
206+
GUI::wxGetApp().app_config->get("dark_mode_follow_system") == "1") {
205207
update_dark_config();
206208
on_sys_color_changed();
207-
event.Skip();
208-
#endif // __WINDOWS__
209-
209+
}
210+
#else
211+
update_dark_config();
212+
on_sys_color_changed();
213+
#endif
214+
event.Skip();
210215
});
211216

212217
if (std::is_same<wxDialog, P>::value) {

src/slic3r/GUI/KBShortcutsDialog.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,8 @@ void KBShortcutsDialog::fill_shortcuts()
240240
{L("Arrow Left"), L("Move selection 10 mm in negative X direction")},
241241
{L("Arrow Right"), L("Move selection 10 mm in positive X direction")},
242242
{L("Shift+Any arrow"), L("Movement step set to 1 mm")},
243+
{L("Alt+Any arrow"), L("Movement step set to 0.1 mm")},
244+
{L("Alt+Shift+Any arrow"), L("Movement step set to 0.01 mm")},
243245
{"Esc", L("Deselect all")},
244246
{"1-9", L("keyboard 1-9: set filament for object/part")},
245247
{ctrl + "0", L("Camera view - Default")},

src/slic3r/GUI/MainFrame.cpp

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,19 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
295295
});
296296
#endif
297297

298+
// Auto-save timer: silently saves the open project every 5 minutes when enabled
299+
m_autosave_timer = new wxTimer(this);
300+
Bind(wxEVT_TIMER, [this](wxTimerEvent& e) {
301+
if (e.GetTimer().GetId() != m_autosave_timer->GetId()) { e.Skip(); return; }
302+
if (!wxGetApp().app_config || wxGetApp().app_config->get("autosave_enabled") != "1") return;
303+
if (!m_plater) return;
304+
if (!m_plater->is_project_dirty()) return;
305+
if (m_plater->get_project_filename(".3mf").IsEmpty()) return;
306+
BOOST_LOG_TRIVIAL(info) << "auto-save: saving project";
307+
m_plater->save_project(false);
308+
});
309+
m_autosave_timer->Start(5 * 60 * 1000); // every 5 minutes
310+
298311
#ifdef __APPLE__
299312
// Initialize the docker task bar icon.
300313
switch (wxGetApp().get_app_mode()) {
@@ -762,6 +775,15 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
762775
return;
763776
}
764777

778+
// F1–F4: switch main tabs; F5: reslice
779+
if (!evt.HasAnyModifiers()) {
780+
if (key_code == WXK_F1) { select_tab(size_t(tp3DEditor)); return; }
781+
if (key_code == WXK_F2) { select_tab(size_t(tpPreview)); return; }
782+
if (key_code == WXK_F3) { select_tab(size_t(tpMonitor)); return; }
783+
if (key_code == WXK_F4) { select_tab(size_t(tpProject)); return; }
784+
if (key_code == WXK_F5) { if (can_reslice()) reslice_now(); return; }
785+
}
786+
765787
// Pass 3D view preset shortcuts directly to the current canvas. (Only 0-7 currently used but reserve 8 & 9 anyway.)
766788
if (evt.CmdDown() && ((key_code >= '0' && key_code <= '9') || (key_code >= WXK_NUMPAD0 && key_code <= WXK_NUMPAD9)) && m_plater) {
767789
if (auto *canvas = m_plater->canvas3D()) {
@@ -789,6 +811,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
789811
m_topbar->EnableSaveItem(can_save());
790812
m_topbar->EnableUndoItem(m_plater->can_undo());
791813
m_topbar->EnableRedoItem(m_plater->can_redo());
814+
update_title();
792815
}
793816
}));
794817
#ifdef _MSW_DARK_MODE
@@ -1135,7 +1158,20 @@ void MainFrame::update_filament_tab_ui()
11351158

11361159
void MainFrame::update_title()
11371160
{
1138-
return;
1161+
#ifndef __APPLE__
1162+
if (!m_topbar) return;
1163+
wxString title = wxString(SLIC3R_APP_FULL_NAME) + " " + SLIC3R_VERSION;
1164+
if (m_plater) {
1165+
wxString proj = m_plater->get_project_filename();
1166+
if (!proj.IsEmpty()) {
1167+
wxFileName fn(proj);
1168+
title = fn.GetName() + " - " + title;
1169+
}
1170+
if (m_plater->is_project_dirty())
1171+
title = "* " + title;
1172+
}
1173+
m_topbar->SetTitle(title);
1174+
#endif
11391175
}
11401176

11411177
void MainFrame::show_calibration_button(bool show, bool is_BBL)
@@ -2614,10 +2650,8 @@ void MainFrame::on_sys_color_changed()
26142650
// update label colors in respect to the system mode
26152651
wxGetApp().init_label_colours();
26162652

2617-
#ifndef __WINDOWS__
26182653
wxGetApp().force_colors_update();
26192654
wxGetApp().update_ui_from_settings();
2620-
#endif //__APPLE__
26212655

26222656
#ifdef __WXMSW__
26232657
wxGetApp().UpdateDarkUI(m_tabpanel);

src/slic3r/GUI/MainFrame.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ class MainFrame : public DPIFrame
9696
#endif
9797
bool m_loaded {false};
9898
wxTimer* m_reset_title_text_colour_timer{ nullptr };
99+
wxTimer* m_autosave_timer{ nullptr };
99100

100101
wxString m_qs_last_input_file = wxEmptyString;
101102
wxString m_qs_last_output_file = wxEmptyString;

src/slic3r/GUI/Preferences.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ class PreferencesDialog : public DPIDialog
9595
// debug mode
9696
::CheckBox * m_developer_mode_ckeckbox = {nullptr};
9797
::CheckBox * m_internal_developer_mode_ckeckbox = {nullptr};
98-
::CheckBox * m_dark_mode_ckeckbox = {nullptr};
98+
::CheckBox * m_dark_mode_ckeckbox = {nullptr};
99+
::CheckBox * m_dark_mode_follow_system_checkbox = {nullptr};
99100
::TextInput *m_backup_interval_textinput = {nullptr};
100101

101102
wxString m_developer_mode_def;

0 commit comments

Comments
 (0)