feat(slices): non-overlapping flag packing + per-slice colored letters

Flags (A + B+) now lay out in one pass: each sits beside its own filter
band as before, but a left neighbour pushes the next flag right so they
never cross (forward pack + backward pull-in on right-edge overflow).
LayoutFlags replaces the per-flag positioning; PositionVfoOverlay/
PositionSliceFlags are thin wrappers.

Identity is shown by a letter drawn at the top of each filter band in
the spectrum (both CPU + GL renderers), so a flag pushed away from its
band is still traceable. Letters and the flag letter-badge share one
per-slice palette (SliceColor); F is violet, not red, to avoid clashing
with the TX indicator.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-02 13:19:50 +03:00
co-authored by Claude Opus 4.8
parent 3fbde19b9f
commit 30a6616dbe
4 changed files with 177 additions and 102 deletions
+24 -1
View File
@@ -23,6 +23,21 @@ const
VFO_OVERLAY_ALPHA = 210;
OVL_W = 280; // ширина карточки
// Палитра слайсов (TColor = $00BBGGRR): одна на букву — общий цвет для
// бейджа-карточки во флаге и для буквы на полосе фильтра в спектре.
SLICE_COLORS: array[0..7] of TColor = (
TColor($0060E040), // A — зелёный
TColor($0010A8FF), // B — оранжевый
TColor($00F0D030), // C — голубой
TColor($00E070F0), // D — розовый/маджента
TColor($0030E0F0), // E — жёлтый
TColor($00F050B0), // F — фиолетовый (не красный — чтобы не путать с TX)
TColor($00E0C060), // G — бирюзовый
TColor($00C0C0C0)); // H — серый
// Цвет слайса по его букве (A..). За пределами таблицы — по кругу.
function SliceColor(L: Char): TColor;
type
TModeFilterEvent = procedure(Mode: Integer; FilterBW: Integer) of object;
TDSPChangeEvent = procedure(NRMode, NBMode: Integer; SNBOn, ANFOn: Boolean) of object;
@@ -146,6 +161,7 @@ type
procedure SetSliceInfo(ASliceId: Integer; ALetter: Char; AIsMain: Boolean);
property SliceId: Integer read FSliceId;
property IsMain: Boolean read FIsMain;
property SliceLetter: Char read FSlice; // буква слайса (A/B/…) для меток на полосе фильтра
// Для маркера фильтра слайса на спектре (читает GL-вьюха).
property DisplayVfoHz: Double read FVfoHz;
property DisplayMode: Integer read FMode;
@@ -173,6 +189,13 @@ type
implementation
function SliceColor(L: Char): TColor;
var idx: Integer;
begin
if (L >= 'A') and (L <= 'Z') then idx := Ord(L) - Ord('A') else idx := 0;
Result := SLICE_COLORS[idx mod (High(SLICE_COLORS) + 1)];
end;
const
KEY_COLOR = TColor($00FF00FF);
@@ -886,7 +909,7 @@ begin
CurY := PAD;
{ --- Шапка: [A] BW ... [×] SPLIT [TX] --- }
DrawBadge(C, Rect(X, CurY, X+16, CurY+HDR_BADGE_H), FSlice, CLR_ACCENT, CLR_CARD_BG);
DrawBadge(C, Rect(X, CurY, X+16, CurY+HDR_BADGE_H), FSlice, SliceColor(FSlice), CLR_CARD_BG);
RegisterHit(Rect(X, CurY, X+16, CurY+HDR_BADGE_H), HIT_SLICE_SEL); // бейдж = выбор слайса
// Кнопка закрытия × — только у неглавных слайсов (главный приёмник не закрыть).
if not FIsMain then