mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 18:43:51 +00:00
feat(slices): per-pan дисплей — палитра/gamma/уровни на пан («◑»-поповер)
Кнопка «◑» в шапке каждого пана открывает компактный поповер настроек отображения (палитра, gamma, ref/range спектра, авто-уровень водопада + offset/ручные min-max). Модель «глобальный дефолт + override на пан»: пан 0 правит глобальные поля рендера (зеркалятся в контроллер), паны N ставят DisplayOverride и персистятся в воркспейс раздельно КВ/трансвертер. - PanDisplayPopup.pas (new): borderless fsStayOnTop форма, гаснет по OnDeactivate; Flat*-контролы; крестик «×» закрытия; дим-хинт «правки применяются и сохраняются сами»; кнопки «⟳ Reset»/«⇄ Copy to all». - TPanafallPanel: FBtnDisplay + OnDisplayClick + DisplayOverride; PositionHeaderChildren каскадит [×][⧉][◑] справа по Visible. - MainForm: OnPanDisplayClick/Applied/Reset/ApplyAll + ApplyGlobalRenderToView + MarkPanDisplayDirty. При смене палитры/сбросе чистим историю GL-водопада (TSpectrumView.ClearWaterfall) — GL хранит уже раскрашенные пиксели. - Settings/TPanCfg: под-объект 'display' (палитра/gamma/ref/range/wf-уровни), пишется только при override. Глобальными осознанно оставлены разрешение анализатора, MSAA, скорость водопада, детектор/усреднение (движок/перф, не косметика). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+52
-3
@@ -110,6 +110,17 @@ type
|
||||
StackShare: Double; // доля высоты в стеке панов
|
||||
ColShare: Double; // доля ширины в грид-раскладке
|
||||
SplitRatio: Double; // доля высоты спектра (сплиттер спектр/водопад)
|
||||
// Per-pan дисплей (3.6): override глобального рендера. HasDisplay=False ⇒
|
||||
// пан наследует глобальный дефолт (поля игнорируются).
|
||||
HasDisplay: Boolean;
|
||||
DPalette: Integer; // 0=Classic/1=Inferno/2=Turbo
|
||||
DGamma: Double;
|
||||
DSpecRef: Double; // верх шкалы спектра, dBm
|
||||
DSpecRange: Double; // диапазон шкалы, dB
|
||||
DWfAGC: Boolean; // авто-уровень водопада
|
||||
DWfOffset: Double; // яркость водопада при AGC, dB
|
||||
DWfHigh: Double; // ручной верх водопада, dBm
|
||||
DWfLow: Double; // ручной низ водопада, dBm
|
||||
Slices: array of TSliceCfg;
|
||||
end;
|
||||
|
||||
@@ -1608,6 +1619,15 @@ begin
|
||||
P.Pans[i].StackShare := 1.0;
|
||||
P.Pans[i].ColShare := 1.0;
|
||||
P.Pans[i].SplitRatio := 0.40; // = TPanafallPanel дефолт
|
||||
P.Pans[i].HasDisplay := False;
|
||||
P.Pans[i].DPalette := 0;
|
||||
P.Pans[i].DGamma := 1.0;
|
||||
P.Pans[i].DSpecRef := -20.0;
|
||||
P.Pans[i].DSpecRange := 110.0;
|
||||
P.Pans[i].DWfAGC := True;
|
||||
P.Pans[i].DWfOffset := 0.0;
|
||||
P.Pans[i].DWfHigh := -60.0;
|
||||
P.Pans[i].DWfLow := -120.0;
|
||||
SetLength(P.Pans[i].Slices, 0);
|
||||
end;
|
||||
end;
|
||||
@@ -1615,7 +1635,7 @@ end;
|
||||
procedure TSettingsManager.SavePans(const MAC: array of Byte; const Ctx: string;
|
||||
const P: TPansConfig);
|
||||
var
|
||||
Root, PanObj, SliceObj: TJSONObject;
|
||||
Root, PanObj, SliceObj, DispObj: TJSONObject;
|
||||
PanArr, SliceArr: TJSONArray;
|
||||
i, j, Idx: Integer;
|
||||
begin
|
||||
@@ -1643,6 +1663,20 @@ begin
|
||||
PanObj.Add('stack_share', P.Pans[i].StackShare);
|
||||
PanObj.Add('col_share', P.Pans[i].ColShare);
|
||||
PanObj.Add('split_ratio', P.Pans[i].SplitRatio);
|
||||
// Per-pan дисплей: пишем блок только при override (иначе пан = глоб. дефолт).
|
||||
if P.Pans[i].HasDisplay then
|
||||
begin
|
||||
DispObj := TJSONObject.Create;
|
||||
PanObj.Add('display', DispObj);
|
||||
DispObj.Add('palette', P.Pans[i].DPalette);
|
||||
DispObj.Add('gamma', P.Pans[i].DGamma);
|
||||
DispObj.Add('spec_ref', P.Pans[i].DSpecRef);
|
||||
DispObj.Add('spec_range', P.Pans[i].DSpecRange);
|
||||
DispObj.Add('wf_agc', P.Pans[i].DWfAGC);
|
||||
DispObj.Add('wf_offset', P.Pans[i].DWfOffset);
|
||||
DispObj.Add('wf_high', P.Pans[i].DWfHigh);
|
||||
DispObj.Add('wf_low', P.Pans[i].DWfLow);
|
||||
end;
|
||||
SliceArr := TJSONArray.Create;
|
||||
PanObj.Add('slices', SliceArr);
|
||||
for j := 0 to High(P.Pans[i].Slices) do
|
||||
@@ -1667,8 +1701,8 @@ function TSettingsManager.LoadPans(const MAC: array of Byte; const Ctx: string;
|
||||
out P: TPansConfig): Boolean;
|
||||
var
|
||||
MacStr: string;
|
||||
DevObj, PansObj, Root, PanObj, SliceObj: TJSONObject;
|
||||
ListData, SlData: TJSONData;
|
||||
DevObj, PansObj, Root, PanObj, SliceObj, DispObj: TJSONObject;
|
||||
ListData, SlData, DispData: TJSONData;
|
||||
Arr, SArr: TJSONArray;
|
||||
i, id, k, n: Integer;
|
||||
begin
|
||||
@@ -1701,6 +1735,21 @@ begin
|
||||
P.Pans[id].StackShare := JD(PanObj, 'stack_share', 1.0);
|
||||
P.Pans[id].ColShare := JD(PanObj, 'col_share', 1.0);
|
||||
P.Pans[id].SplitRatio := EnsureRange(JD(PanObj, 'split_ratio', 0.40), 0.05, 0.95);
|
||||
// Per-pan дисплей: присутствие блока 'display' = override.
|
||||
DispData := PanObj.Find('display');
|
||||
if (DispData <> nil) and (DispData is TJSONObject) then
|
||||
begin
|
||||
DispObj := TJSONObject(DispData);
|
||||
P.Pans[id].HasDisplay := True;
|
||||
P.Pans[id].DPalette := EnsureRange(JI(DispObj, 'palette', 0), 0, 2);
|
||||
P.Pans[id].DGamma := EnsureRange(JD(DispObj, 'gamma', 1.0), 0.30, 3.00);
|
||||
P.Pans[id].DSpecRef := JD(DispObj, 'spec_ref', -20.0);
|
||||
P.Pans[id].DSpecRange := JD(DispObj, 'spec_range', 110.0);
|
||||
P.Pans[id].DWfAGC := JB(DispObj, 'wf_agc', True);
|
||||
P.Pans[id].DWfOffset := JD(DispObj, 'wf_offset', 0.0);
|
||||
P.Pans[id].DWfHigh := JD(DispObj, 'wf_high', -60.0);
|
||||
P.Pans[id].DWfLow := JD(DispObj, 'wf_low', -120.0);
|
||||
end;
|
||||
SlData := PanObj.Find('slices');
|
||||
if (SlData = nil) or not (SlData is TJSONArray) then Continue;
|
||||
SArr := TJSONArray(SlData);
|
||||
|
||||
Reference in New Issue
Block a user