Skip to content

fix(gui): render the log views with wxStyledTextCtrl (Scintilla) - #548

Merged
got3nks merged 1 commit into
amule-org:masterfrom
got3nks:fix/amulegui-log-render
Jul 22, 2026
Merged

fix(gui): render the log views with wxStyledTextCtrl (Scintilla)#548
got3nks merged 1 commit into
amule-org:masterfrom
got3nks:fix/amulegui-log-render

Conversation

@got3nks

@got3nks got3nks commented Jul 22, 2026

Copy link
Copy Markdown

The amuleGUI log panes used a wxTE_RICH2 (RichEdit) control, which holds the entire document and reflows O(n) on scroll. A remote-GUI first sync can deliver tens of thousands of daemon-log lines at once, so scrolling the "aMule Log" tab crawled, and the view mispainted — only the tail was visible until a manual one-line scroll (#547, follow-up to the #445 / #451 / #471 / #477 RichEdit repaint saga).

What changed

  • New CMuleLogCtrl backed by wxStyledTextCtrl (Scintilla) replaces the three log/info panes: aMule Log, aMuleGUI Log, and server info. Scintilla renders only the visible lines, so scrolling and full-history retention stay O(visible) at any size, and — unlike a virtual list — it keeps character-level selection and find. Lines word-wrap as the old pane did; critical lines are bold via per-line Scintilla styles.
  • The view tail-scrolls after new content only when it was already at the bottom, so scrolling up to read history isn't disturbed. When lines arrive while a pane is hidden — its notebook page or sub-tab isn't selected (e.g. the first-sync backlog before the Networks tab is opened, or the aMuleGUI Log / server info sub-tabs before you switch to them) — the control has no laid-out geometry and can't be scrolled reliably, so the tail-scroll is deferred and applied on the first idle once the pane is on screen. This lives in the base CMuleLogCtrl, so all three panes share it.
  • This removes the whole RichEdit workaround stack — the per-poll append batching and the Freeze/Thaw lineage from perf(remote-gui): batch remote log delivery + rendering #451/fix(remote-gui): don't blank the log view on each new line (Windows) (#445) #471/fix(remote-gui): Windows repaint fixes — log-view blanking (#445) + list rows blanking on scroll/keyboard (#478) #477 — none of which Scintilla needs.
  • wxStyledTextCtrl (the stc component) ships with the wxWidgets packages every platform already builds against (verified: Ubuntu libwxgtk3.2-dev, Homebrew wxwidgets, MSYS2 wxwidgets3.2, and the AppImage/flatpak source builds have wxUSE_STC on by default). No new dependency; stc is requested only for the GUI library that owns the log views, and the Windows packaging bundles its DLL automatically via the existing GET_RUNTIME_DEPENDENCIES install step.

Test plan

Verified on all three GUI platforms against a live remote daemon with a large multi-day log (~16k lines):

macOS (Cocoa, wx 3.3)

  • First-sync backlog loads fast; scrolling the full history is instant (was crawling before).
  • Backlog arriving while on the Networks tab → lands exactly at the bottom, then follows live lines.
  • Backlog arriving while on another tab, then switching to Networks → lands exactly at the bottom (deferred-scroll path).
  • aMuleGUI Log and server-info panes also land at the bottom when first opened (deferral is in the base control).
  • Scroll up to read history → stays put as new lines arrive; switching tabs and back does not yank to the bottom.
  • Critical (error/warning) lines render bold; normal lines normal.
  • Text selection / copy works.

Linux (GTK3, wx 3.2)

  • Same scenarios as above; scroll-to-bottom correct in both visible and hidden-during-load cases.

Windows (wxMSW, wx 3.2)

  • Same scenarios; hidden-during-load deferred scroll lands at the bottom (matches macOS/GTK).
  • Portable bundles wxmsw32u_stc_*.dll and launches cleanly.

Lint: clang-format clean; clang-tidy Tier-1 and Tier-2 diff checks both clean.

The amuleGUI log panes used a wxTE_RICH2 (RichEdit) control, which holds the
whole document and reflows O(n) on scroll. A remote-GUI first sync can dump
tens of thousands of daemon-log lines at once, so scrolling crawled and the
view mispainted -- only the tail visible until a manual one-line scroll
(issues amule-project#445, amule-project#547).

Replace the three log/info panes (aMule Log, aMuleGUI Log, server info) with a
new CMuleLogCtrl backed by wxStyledTextCtrl. Scintilla renders only the
visible lines, so scrolling and full-history retention stay O(visible) at any
size, and unlike a virtual list it keeps character-level selection and find.
Lines word-wrap as the old pane did; critical lines are bold via per-line
Scintilla styles.

The view tail-scrolls after new content only when it was already at the
bottom, so scrolling up to read history sticks. When lines arrive while a pane
is hidden (its notebook page or sub-tab is not selected -- e.g. the first-sync
backlog before the Networks tab is opened) the control has no laid-out geometry
and cannot be scrolled reliably, so the tail-scroll is deferred and applied on
the first idle once the pane is on screen. This lives in CMuleLogCtrl, so all
three panes share it.

This removes the whole RichEdit workaround stack -- the per-poll append
batching and the Freeze/Thaw lineage from amule-project#451/amule-project#471/amule-project#477 -- none of which
Scintilla needs.

wxStyledTextCtrl (the stc component) ships with the wxWidgets packages every
platform already builds against, so it adds no new dependency; it is requested
only for the GUI library that owns the log views.
@got3nks
got3nks force-pushed the fix/amulegui-log-render branch from 7a518cc to 413e88d Compare July 22, 2026 09:48
@got3nks
got3nks merged commit 2c5a8ec into amule-org:master Jul 22, 2026
13 checks passed
@got3nks
got3nks deleted the fix/amulegui-log-render branch July 22, 2026 09:58
got3nks added a commit that referenced this pull request Jul 22, 2026
…549)

Follow-up to #548 (Scintilla log panes). The tail-scroll landed short when log
lines wrap, because Scintilla lays out wrapped lines incrementally over several
idles, so a one-shot ScrollToEnd() ran against a display-line count that did
not yet include the still-unwrapped tail. Switching in mid-load made it worse:
each poll's batch also scrolled directly and the idle re-scroll loop misread
its own batch scroll as a manual scroll and gave up (~90%).

Make OnInternalIdle() the sole scroller: ScrollToBottom() only flags a pending
scroll, and the idle loop re-applies ScrollToEnd() until the first-visible line
stops moving (wrap settled at the true bottom), bailing only on a genuine
manual scroll. Appends never move the first-visible line, so it follows the
whole replay. In the base CMuleLogCtrl, so all three panes share it. Also
corrects a few #548 comments the rework left inaccurate. Reported in #547.
got3nks added a commit that referenced this pull request Jul 24, 2026
)

The log views migrated to wxStyledTextCtrl (Scintilla) in #548 paint
their colours from the system theme once, in the constructor. The native
wxTextCtrl they replaced followed the platform appearance automatically;
Scintilla does not, so a live light/dark switch left the three log panes
(aMule Log, aMuleGUI Log, Server Info) stuck in the previous theme's
colours while the rest of the UI re-themed. Re-apply the styles on
wxEVT_SYS_COLOUR_CHANGED so the panes track the appearance.

Also guard against a foreground/background that resolve with too little
contrast to read: on macOS the window/text system colours are
appearance-aware and, on some wx builds, come back near-identical, which
paints the whole log invisible (#569). When the pair is unreadable, keep
the theme's background and force a legible foreground from its
brightness. Windows/GTK return static, well-contrasted colours and are
unaffected.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant