Found by tracing the app with a fake skimmer feed, a fake rigctld and
eight tool windows open (about 3,500 spots on the bandmap).
- Drop expired spots from the one-second spot timer instead of from each
window's refresh on the UI thread.
- Bandmap keeps the lists On and All return until the spots change, and
Near searches only the band the frequency is in.
- The Available window replaces its rows at most every two seconds, the
Score window redraws at most once a second, and the Telnet list takes
new lines four times a second at most (RateLimited).
- The bandmap leader line pen is made once.
Idle CPU in that setup went from about 33-70% of one core to about 16-25%.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Redraws:
- Merge bursts of session and bandmap events into one redraw
(Coalesced). Closed Bandmap and Available windows now unsubscribe.
- Grayline and Voice Keyer no longer subscribe to the session twice.
- Available summary, Score table and Log rows redraw only when their
contents change. Telnet lines are added in batches.
- Bandmap view reuses its layout, shaped text and brushes. Grayline
draws the coastlines as one cached shape.
Threads:
- Available, Bandmap colours, Check and Statistics do their judging
and counting on the thread pool and draw the result on the UI thread.
- ContestLog takes a lock in Judge and in each method that changes the
log, so a background Judge cannot read the indexes mid-edit.
Refresh rate:
- Statistics refreshes every 30 seconds and when the QSO count changes.
- Grayline refreshes at most every 15 seconds on session events.
Publish with ReadyToRun to cut startup JIT time.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A contest opening and contacts arriving from the other stations, a
resync included, spot the contacts logged in the last few minutes (a
setting on the telnet Filters tab, 0 for none). A station the bandmap
already holds on that band keeps its spot. Nothing is sent out. Spots
that come from the log are drawn in italics.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Starting Run stores the frequency in the position. The bandmap draws a
purple, bold "CQ Frequency" pseudospot there, which is not added to the
shared bandmap, and a click on it tunes back and sets Run. A move of more
than 3 kHz (a setting on the telnet Filters tab) while running switches
to search and pounce.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The zoom list gains 60 kHz and a "mode" level that shows the CW, digital
or phone part of the band the receiver is in, before "band". For views
from 40 to 200 kHz wide, the scale picks the smallest round step that
keeps three lines of text between ticks. The font size buttons are
removed; Ctrl with the wheel or plus and minus still change the size.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A spot an operator put on a bandmap, here or on another computer, is
drawn in bold. Its hover text names the computer instead of the
spotter's callsign. A spot from another computer carries the name from
the ADDSPOT message.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The tool tip has no show delay and the theme's fade is removed. The
carrier tick reaches 30 px further to the right.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Remove the status bar and the band name, add the 75 and 150 kHz spans,
add buttons for the callsign size (saved in the settings), draw the scale
in the form's text colour so it shows in the dark theme, mark the carrier
on the VFO bar and place a sideband bar on its side of the carrier, and
show who spotted a station, when, and the comment when the pointer is on it.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The generic name only resolves through fontconfig, so on Windows the
windows fell back to the proportional default.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The wheel steps along the span list and keeps the frequency under the
pointer in place. With Centre on VFO off, the slice stays put until the
receiver nears an edge. The span and the toggle are saved in the settings.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Behind the bandmap scale, the CW part of the band is one shade and the phone
part another, with a third for a digital block. That is what N1MM's graphical
bandmap does: ResizeBandPanels puts a CW, a Digi and an SSB panel behind the
scale, sized from its CWBands, DigiBands and SSBBands tables. Anything past a
band edge is shaded red, which is the only place the edges themselves show, and
it only appears now that the slice can reach past an edge.
The defaults are N1MM's: CW ends at 1840, 3600, 7125, 14150 and so on, and the
digital pair is empty until somebody fills it in, exactly as N1MM ships. They
are one worldwide set rather than one per ITU region, which is also N1MM's
answer — the reason recorded for leaving this out, that the segments differ by
region, was wrong about what N1MM holds. 60M and everything above 2M get no
entry, because N1MM's own numbers there contradict themselves: its 1.25M CW top
is below its phone start, and its 70CM CW top is above the band.
Config ▸ Sub bands edits them, one row per band in kilohertz, with a Defaults
button. Only the rows that differ are written to the settings file, so a plan
nobody has touched leaves nothing behind. BandPlan is an object rather than a
static table, so the stored changes layer over the defaults and the bandmap
picks up a save without a restart.
The numbers are a drawing aid, not a licence. Nothing stops a contact being
logged either side of a boundary.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The bandmap was a list of frequencies and callsigns. It is now a frequency
scale with the stations written out beside it and a leader line from each
callsign back to where the station really is.
BandmapLayout does the placing and has no UI reference, so the rule is unit
tested: put the label centred on its frequency, and if it would cover the one
above, push it below instead. That is N1MM's CalculateOffset, and it is what
keeps three stations a hundred hertz apart readable.
The scale stops short of the top and bottom edges, or the first and last
frequency numbers come out cut in half.
VfoMarker draws the receiver as a bar as wide as the mode passes, rather than a
line. Only the receiver is fed: the radio does not report a transmit VFO or a
second radio yet, so VfoRole has the other two roles ready and nothing draws
them. Band-plan colouring of the scale is left out because the segments differ
by ITU region and there is no band-plan table to read them from.
Checked by running the program against a fake cluster node under Xvfb and
looking at the result: twelve spots, three of them stacked with fanned leaders.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>