fix: 🐛 wxWidgets text ellipsis
This commit is contained in:
parent
4418fd3792
commit
5f02608a91
4 changed files with 141 additions and 1 deletions
|
|
@ -186,6 +186,7 @@ all: minimal_test.html \
|
|||
$(S)/coroutine-pthread/nested_repro_ex.html \
|
||||
$(S)/coroutine-pthread/vcall_repro.html \
|
||||
$(S)/textctrl-reentry/textctrl-reentry_test.html \
|
||||
$(S)/stattext-ellipsize/stattext-ellipsize_test.html \
|
||||
$(S)/tooltip-lifetime/tooltip-lifetime_test.html \
|
||||
$(S)/warp-pointer/warp-pointer_test.html
|
||||
|
||||
|
|
@ -208,6 +209,15 @@ $(S)/textctrl-reentry/textctrl-reentry_test.html: $(S)/textctrl-reentry/textctrl
|
|||
|
||||
textctrl-reentry: $(S)/textctrl-reentry/textctrl-reentry_test.html
|
||||
|
||||
# wxStaticText ellipsize-on-resize repro: re-ellipsize the label on wxEVT_SIZE.
|
||||
$(S)/stattext-ellipsize/stattext-ellipsize_test.o: $(S)/stattext-ellipsize/stattext-ellipsize_test.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||
|
||||
$(S)/stattext-ellipsize/stattext-ellipsize_test.html: $(S)/stattext-ellipsize/stattext-ellipsize_test.o $(WX_CORE_LIB) $(JS_FILES)
|
||||
$(CXX) $< $(LDFLAGS_NOGL) --pre-js $(JS) --shell-file $(HTML) -o $@
|
||||
|
||||
stattext-ellipsize: $(S)/stattext-ellipsize/stattext-ellipsize_test.html
|
||||
|
||||
# wxToolTip hover-window lifetime repro (relies on wxWasmTooltipDebugHoverWindow).
|
||||
$(S)/tooltip-lifetime/tooltip-lifetime_test.o: $(S)/tooltip-lifetime/tooltip-lifetime_test.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
// wxStaticText ellipsize-on-resize regression (DOM port).
|
||||
//
|
||||
// Bug (src/wasm/stattext.cpp): the label was ellipsized only inside SetLabel(),
|
||||
// using the control's client size AT THAT MOMENT. A wxStaticText placed in a
|
||||
// growable sizer cell (e.g. KiCad's gerbview Layers Manager, which uses
|
||||
// WX_ELLIPSIZED_STATIC_TEXT) is constructed narrow and only widened later by
|
||||
// layout. The DOM-port wxStaticText had no wxEVT_SIZE handler, so the visible
|
||||
// label stayed truncated to the early (tiny) width — rendering "1..." instead of
|
||||
// "1 tinytapeout-demo-User_2.gbr (Other, User)". Native ports re-ellipsize on
|
||||
// resize via wxStaticTextBase::UpdateLabel(); the fix binds wxEVT_SIZE to do the
|
||||
// same.
|
||||
//
|
||||
// This repro drives the exact sequence without a sizer (so the width changes are
|
||||
// unambiguous): the label is set while the control is narrow (ellipsized away),
|
||||
// then a button widens the control. wxST_NO_AUTORESIZE keeps our explicit width
|
||||
// so the only thing that can lengthen the visible text is the resize handler.
|
||||
//
|
||||
// RED (bug present): after widening, the visible text is still the narrow
|
||||
// ellipsization — the full name never appears.
|
||||
// GREEN (fixed): widening re-ellipsizes; the full label becomes visible.
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten/emscripten.h>
|
||||
#endif
|
||||
|
||||
// Long enough that it must be ellipsized at 60px but fits fully at >600px.
|
||||
static const char* const LONG_LABEL =
|
||||
"1 tinytapeout-demo-User_2.gbr (Other, User)";
|
||||
|
||||
enum { ID_GROW = wxID_HIGHEST + 1 };
|
||||
|
||||
class EllipsizeFrame : public wxFrame
|
||||
{
|
||||
public:
|
||||
EllipsizeFrame()
|
||||
: wxFrame(nullptr, wxID_ANY, "stattext ellipsize repro",
|
||||
wxDefaultPosition, wxSize(700, 200))
|
||||
{
|
||||
wxButton* grow = new wxButton(this, ID_GROW, "Grow",
|
||||
wxPoint(10, 10), wxSize(120, 30));
|
||||
grow->Bind(wxEVT_BUTTON, &EllipsizeFrame::OnGrow, this);
|
||||
|
||||
m_text = new wxStaticText(this, wxID_ANY, wxEmptyString,
|
||||
wxPoint(10, 60), wxSize(60, 24),
|
||||
wxST_ELLIPSIZE_MIDDLE | wxST_NO_AUTORESIZE);
|
||||
// Establish a valid (but small) client width, THEN set the label, so the
|
||||
// first ellipsization happens at the narrow width.
|
||||
m_text->SetSize(60, 24);
|
||||
m_text->SetLabel(LONG_LABEL);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
CallAfter([] { EM_ASM({ console.log('[REPRO] stattext ready'); }); });
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
void OnGrow(wxCommandEvent&)
|
||||
{
|
||||
// Widen past the label's natural width: the fix re-ellipsizes here (the
|
||||
// full label now fits); the bug leaves the old truncation in place.
|
||||
m_text->SetSize(640, 24);
|
||||
}
|
||||
|
||||
wxStaticText* m_text = nullptr;
|
||||
};
|
||||
|
||||
class EllipsizeApp : public wxApp
|
||||
{
|
||||
public:
|
||||
bool OnInit() override
|
||||
{
|
||||
if (!wxApp::OnInit())
|
||||
return false;
|
||||
|
||||
(new EllipsizeFrame())->Show(true);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
wxIMPLEMENT_APP(EllipsizeApp);
|
||||
|
|
@ -70,4 +70,49 @@ test.describe('wx DOM-port bug reproductions', () => {
|
|||
const line = reproLine(testLogger.consoleLogs, name)!;
|
||||
expect(line, `repro line was: ${line}`).toContain(`[REPRO] ${name}: PASS`);
|
||||
});
|
||||
|
||||
// stattext.cpp ellipsized the label only inside SetLabel(), at the control's
|
||||
// client size at that moment. A wxStaticText in a growable sizer cell (e.g.
|
||||
// gerbview's Layers Manager) is constructed narrow and widened later by layout,
|
||||
// but the DOM-port wxStaticText had no wxEVT_SIZE handler — so the label stayed
|
||||
// truncated to the early tiny width ("1..." instead of the layer name). The fix
|
||||
// re-ellipsizes on resize via UpdateLabel(). The app sets the long label while
|
||||
// narrow, then a button widens the control.
|
||||
test('wxStaticText: an ellipsized label must re-expand when the control is widened', async ({
|
||||
page,
|
||||
testLogger,
|
||||
}) => {
|
||||
await page.goto('/standalone/stattext-ellipsize/stattext-ellipsize_test.html');
|
||||
expect(await tryLoadApp(page, 30000), 'repro app should load').toBe(true);
|
||||
|
||||
await expect
|
||||
.poll(() => testLogger.consoleLogs.some((l) => l.includes('[REPRO] stattext ready')), {
|
||||
timeout: 30000,
|
||||
message: 'repro app should finish setup',
|
||||
})
|
||||
.toBe(true);
|
||||
|
||||
// The middle of the label only renders when the control is wide enough; this
|
||||
// exact substring is ellipsized away at the narrow width.
|
||||
const fullNameVisible = () =>
|
||||
page.evaluate(() =>
|
||||
Array.from(document.querySelectorAll('span, div')).some((el) =>
|
||||
(el.textContent || '').includes('tinytapeout-demo-User_2'),
|
||||
),
|
||||
);
|
||||
|
||||
// Narrow: the long name is ellipsized away.
|
||||
expect(await fullNameVisible(), 'label starts ellipsized at the narrow width').toBe(false);
|
||||
|
||||
await page.getByRole('button', { name: 'Grow' }).click();
|
||||
|
||||
// Widening must re-ellipsize so the full label shows. RED before the wasm fix:
|
||||
// nothing re-ran ellipsization on resize, so the label stayed truncated.
|
||||
await expect
|
||||
.poll(fullNameVisible, {
|
||||
timeout: 10000,
|
||||
message: 'widening the control must re-ellipsize so the full label becomes visible',
|
||||
})
|
||||
.toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit d8d3b49d5730ae3488480dd38613b29d3b8eacfc
|
||||
Subproject commit c299d716aac59de6f86c6711213d4ced3338b4c8
|
||||
Loading…
Reference in a new issue