Change some search actions and results text. Force repaint for when resizing and show happens

This commit is contained in:
Lam Wei Lun
2026-09-24 10:41:55 +08:00
parent b46916a8be
commit 54c32a54b4
6 changed files with 95 additions and 47 deletions
+3 -3
View File
@@ -390,7 +390,7 @@ function favDigitFromEvent(e) {
function resultCountText(total, shown, query) { function resultCountText(total, shown, query) {
return (query || "").trim() ? return (query || "").trim() ?
T("sd_result_count", "Showing %s of %s actions", shown, total) : T("sd_result_count", "Showing %s actions", shown) :
T("sd_result_count_all", "%s actions", total); T("sd_result_count_all", "%s actions", total);
} }
@@ -711,7 +711,7 @@ window.HandleStudio = function (payload) {
builtKey = ""; builtKey = "";
if (qEl) { if (qEl) {
qEl.value = ""; qEl.value = "";
qEl.placeholder = T("sd_search_n", "Search %s actions", ACTIONS.length); qEl.placeholder = T("sd_search", "Search actions");
syncClearButton(); syncClearButton();
} }
render({ resize: true, resetScroll: true }); render({ resize: true, resetScroll: true });
@@ -1376,7 +1376,7 @@ function exitPhase() {
// It survives a second-phase exit (which never goes through exitPhase from the commands view), // It survives a second-phase exit (which never goes through exitPhase from the commands view),
// so without a reset the cached empty-query key would skip the rebuild and leave stale content. // so without a reset the cached empty-query key would skip the rebuild and leave stale content.
builtKey = ""; builtKey = "";
qEl.placeholder = T("sd_search_n", "Search %s actions", ACTIONS.length); qEl.placeholder = T("sd_search", "Search actions");
render({ resize: true, resetScroll: true }); render({ resize: true, resetScroll: true });
qEl.focus(); qEl.focus();
} }
@@ -436,4 +436,9 @@ assert.equal(ctx.stateFromPayload({}).tooltipExpanded, true, "expansion defaults
assert.equal(ctx.stateFromPayload({ tooltip_expanded: false }).tooltipExpanded, false, "a collapsed payload is honored"); assert.equal(ctx.stateFromPayload({ tooltip_expanded: false }).tooltipExpanded, false, "a collapsed payload is honored");
assert.equal(ctx.stateFromPayload({ tooltip_expanded: true }).tooltipExpanded, true, "an expanded payload is honored"); assert.equal(ctx.stateFromPayload({ tooltip_expanded: true }).tooltipExpanded, true, "an expanded payload is honored");
// resultCountText: a search counts the shown matches only ("Showing N actions"); the total is used
// solely for the empty-query count.
assert.equal(ctx.resultCountText(100, 3, "lay"), "Showing 3 actions", "a search reports the shown match count only");
assert.equal(ctx.resultCountText(100, 100, ""), "100 actions", "an empty query reports the total");
console.log("ok"); console.log("ok");
+36 -12
View File
@@ -9,6 +9,8 @@
#include "Plater.hpp" #include "Plater.hpp"
#include "Widgets/WebViewHostDialog.hpp" #include "Widgets/WebViewHostDialog.hpp"
#include "slic3r/Utils/MacDarkMode.hpp"
#include <algorithm> #include <algorithm>
#include <wx/dcmemory.h> #include <wx/dcmemory.h>
@@ -84,7 +86,6 @@ nlohmann::json speed_dial_ui_strings()
{"sd_search", _u8L("Search actions")}, {"sd_search", _u8L("Search actions")},
{"sd_clear", _u8L("Clear")}, {"sd_clear", _u8L("Clear")},
{"sd_search_n", _u8L("Search %s actions")},
{"sd_recent", _u8L("Recent")}, {"sd_recent", _u8L("Recent")},
{"sd_plugins", _u8L("Plugins")}, {"sd_plugins", _u8L("Plugins")},
{"sd_other", _u8L("Other")}, {"sd_other", _u8L("Other")},
@@ -92,7 +93,7 @@ nlohmann::json speed_dial_ui_strings()
{"sd_no_actions", _u8L("No actions yet")}, {"sd_no_actions", _u8L("No actions yet")},
{"sd_no_tabs_match", _u8L("No tabs match")}, {"sd_no_tabs_match", _u8L("No tabs match")},
{"sd_no_tabs", _u8L("No tabs")}, {"sd_no_tabs", _u8L("No tabs")},
{"sd_result_count", _u8L("Showing %s of %s actions")}, {"sd_result_count", _u8L("Showing %s actions")},
{"sd_result_count_all", _u8L("%s actions")}, {"sd_result_count_all", _u8L("%s actions")},
{"sd_tab_count", _u8L("%s tabs")}, {"sd_tab_count", _u8L("%s tabs")},
{"sd_tab_match_count", _u8L("%s matches")}, {"sd_tab_match_count", _u8L("%s matches")},
@@ -178,6 +179,7 @@ void SpeedDialWebDialog::request_show()
if (IsShown()) { if (IsShown()) {
Raise(); Raise();
focus_webview(browser(), m_page_ready); focus_webview(browser(), m_page_ready);
repaint_webview();
return; return;
} }
@@ -189,6 +191,7 @@ void SpeedDialWebDialog::request_show()
// Grab focus now and again on wxEVT_ACTIVATE; grabbing directly on the WebKit widget is // Grab focus now and again on wxEVT_ACTIVATE; grabbing directly on the WebKit widget is
// what makes typing reach the search field immediately on open. // what makes typing reach the search field immediately on open.
focus_webview(browser(), m_page_ready); focus_webview(browser(), m_page_ready);
repaint_webview();
} }
void SpeedDialWebDialog::on_script_message(const nlohmann::json& payload) void SpeedDialWebDialog::on_script_message(const nlohmann::json& payload)
@@ -265,14 +268,36 @@ void SpeedDialWebDialog::resize_to_content(int height)
Layout(); Layout();
#ifdef __WXOSX__ #ifdef __WXOSX__
// WKWebView can lag the dialog's new client size; force the viewport to match so the page is // WKWebView can lag the dialog's new client size; force the viewport to match so the page is
// never painted (and clipped by the rounded layer) below the footer. // never painted (and clipped by the rounded layer) below the footer. Unconditional: on a
if (wxWebView* wv = browser()) { // re-open the size is often unchanged, and skipping the sync leaves the fresh render unpainted.
const wxSize client = GetClientSize(); if (wxWebView* wv = browser())
if (wv->GetSize() != client) wv->SetSize(GetClientSize());
wv->SetSize(client);
}
#endif #endif
apply_rounded_shape(); apply_rounded_shape();
// A re-open re-renders at (usually) the same size, so nothing above may generate damage.
// Repaint explicitly so the newly rendered list is shown without needing user input.
repaint_webview();
}
void SpeedDialWebDialog::repaint_webview()
{
wxWebView* wv = browser();
if (!wv)
return;
// Portable invalidate; the platform blocks below reach the widget/layer that actually paints.
wv->Refresh();
#ifdef __WXOSX__
if (void* nb = wv->GetNativeBackend())
WKWebView_force_display(nb);
wv->Update();
#elif defined(__linux__)
// WebKitGTK's WebKitWebView owns its own GdkWindow, so invalidating the wxWebView wrapper
// (the GtkScrolledWindow) does not redraw it.
if (void* nb = wv->GetNativeBackend())
gtk_widget_queue_draw((GtkWidget*) nb);
#else
wv->Update();
#endif
} }
// Rounded corners: the webview paints an opaque rectangle, so round the whole top-level window. // Rounded corners: the webview paints an opaque rectangle, so round the whole top-level window.
@@ -341,16 +366,15 @@ void SpeedDialWebDialog::run_action(const std::string& id, const std::string& ti
const wxString setting = title.empty() ? from_u8(atitle) : from_u8(title); const wxString setting = title.empty() ? from_u8(atitle) : from_u8(title);
if (required == comDevelop) { if (required == comDevelop) {
RichMessageDialog dlg(wxGetApp().mainframe, RichMessageDialog dlg(wxGetApp().mainframe,
wxString::Format(_L("\"%s\" is a Developer setting. Enable Developer mode to edit it?"), wxString::Format(_L("\"%s\" is a Developer setting. Enable Developer mode to edit it?"), setting),
setting),
_L("Developer setting"), wxOK | wxCANCEL); _L("Developer setting"), wxOK | wxCANCEL);
if (dlg.ShowModal() != wxID_OK) if (dlg.ShowModal() != wxID_OK)
return; return;
wxGetApp().enable_developer_mode(); wxGetApp().enable_developer_mode();
} else { } else {
RichMessageDialog dlg(wxGetApp().mainframe, RichMessageDialog dlg(wxGetApp().mainframe,
wxString::Format(_L("\"%s\" is a %s setting. Switch from %s mode to %s mode to edit it?"), wxString::Format(_L("\"%s\" is a %s setting. Switch from %s mode to %s mode to edit it?"), setting,
setting, mode_label(required), mode_label(wxGetApp().get_mode()), mode_label(required)), mode_label(required), mode_label(wxGetApp().get_mode()), mode_label(required)),
_L("Switch settings mode"), wxOK | wxCANCEL); _L("Switch settings mode"), wxOK | wxCANCEL);
if (dlg.ShowModal() != wxID_OK) if (dlg.ShowModal() != wxID_OK)
return; return;
+4
View File
@@ -28,6 +28,10 @@ private:
void send_actions(); void send_actions();
void search_tabs(); void search_tabs();
void apply_rounded_shape(); void apply_rounded_shape();
// Forces the webview to repaint after it is mapped / re-rendered. The popup is transparent and
// chrome-less, so a missed frame leaves it blank until input; platform-specific because the
// widget that actually paints is not always the wxWebView wrapper.
void repaint_webview();
void on_dpi_changed(const wxRect& suggested_rect) override; void on_dpi_changed(const wxRect& suggested_rect) override;
bool m_page_ready{false}; bool m_page_ready{false};
+1
View File
@@ -12,6 +12,7 @@ extern double mac_max_scaling_factor();
extern void set_miniaturizable(void * window); extern void set_miniaturizable(void * window);
void WKWebView_evaluateJavaScript(void * web, wxString const & script, void (*callback)(wxString const &)); void WKWebView_evaluateJavaScript(void * web, wxString const & script, void (*callback)(wxString const &));
void WKWebView_setTransparentBackground(void * web); void WKWebView_setTransparentBackground(void * web);
void WKWebView_force_display(void * web);
void set_tag_when_enter_full_screen(bool isfullscreen); void set_tag_when_enter_full_screen(bool isfullscreen);
void set_title_colour_after_set_title(void * window); void set_title_colour_after_set_title(void * window);
void initGestures(void * view, wxEvtHandler * handler); void initGestures(void * view, wxEvtHandler * handler);
+14
View File
@@ -100,6 +100,20 @@ void WKWebView_setTransparentBackground(void * web)
[webView registerForDraggedTypes: @[NSFilenamesPboardType]]; [webView registerForDraggedTypes: @[NSFilenamesPboardType]];
} }
// Force a WKWebView to re-lay-out and repaint. Needed for chrome-less popups: the window is
// transparent, so a WKWebView whose layer has no pending frame leaves the whole window invisible
// until the user generates input (scroll/arrow). setNeedsDisplay alone does not always reach the
// web-content layer, so flag layout and both the view and its layer.
void WKWebView_force_display(void * web)
{
WKWebView * webView = (WKWebView*)web;
if (!webView)
return;
[webView setNeedsLayout:YES];
[webView setNeedsDisplay:YES];
[[webView layer] setNeedsDisplay];
}
void openFolderForFile(wxString const & file) void openFolderForFile(wxString const & file)
{ {
NSArray *fileURLs = [NSArray arrayWithObjects:wxCFStringRef(file).AsNSString(), /* ... */ nil]; NSArray *fileURLs = [NSArray arrayWithObjects:wxCFStringRef(file).AsNSString(), /* ... */ nil];