add gradient

This commit is contained in:
2026-03-09 22:14:04 +03:00
parent 01de71c60f
commit e131af9ae5
+102 -33
View File
@@ -318,6 +318,8 @@ type
BtnSNB: TFlatButton;
BtnANF: TFlatButton;
BtnMute: TFlatButton;
BtnWfAGC: TFlatButton;
BtnWfNF: TFlatButton;
PanelSMeterRight: TPanel; // контейнер S-метра справа
PbSMeterRight: TPaintBox;// новый большой S-метр справа
@@ -342,8 +344,6 @@ type
BtnSpan384k: TFlatButton;
BtnSpan768k: TFlatButton;
BtnSpan1536k: TFlatButton;
BtnWfAGC: TFlatButton;
BtnWfNF: TFlatButton;
BtnHidePanel: TFlatButton; // скрыть/показать левую панель
PbSpectrum: TPaintBox;
PbRuler: TPaintBox; // полоса частотных меток между спектром и водопадом
@@ -1161,7 +1161,7 @@ begin
// RX controls
PanelRX := TPanel.Create(Self);
PanelRX.Parent := PanelLeft;
PanelRX.SetBounds(0, Y, LEFT_W, 120);
PanelRX.SetBounds(0, Y, LEFT_W, 150);
PanelRX.BevelOuter := bvNone;
// AGC mode — 5 кнопок в ряд
@@ -1207,8 +1207,10 @@ begin
BtnSNB := MakeBtn(PanelRX, 'SNB', 2*W+6, 96, W, BTN_SM, BtnSNBClick);
BtnANF := MakeBtn(PanelRX, 'ANF', 3*W+8, 96, W, BTN_SM, BtnANFClick);
BtnMute:= MakeBtn(PanelRX, 'MUTE', 4*W+10, 96, W, BTN_SM, BtnMuteClick);
BtnWfAGC := MakeBtn(PanelRX, 'WF AGC', 2, 122, (LEFT_W - 6) div 2, BTN_SM, BtnWfAGCClick);
BtnWfNF := MakeBtn(PanelRX, 'WF NF', 4 + (LEFT_W - 6) div 2, 122, (LEFT_W - 6) div 2, BTN_SM, BtnWfNFClick);
Inc(Y, 124);
Inc(Y, 154);
// S-Meter
@@ -1294,10 +1296,15 @@ begin
StyleSpanButton(BtnSpan768k, False);
StyleSpanButton(BtnSpan1536k, False);
// Waterfall AGC + Noise Floor кнопки справа в той же панели
BtnWfAGC := MakeBtn(PanelSpanButtons, 'WF AGC', 379, 3, 62, BTN_SM, BtnWfAGCClick);
BtnWfNF := MakeBtn(PanelSpanButtons, 'WF NF', 445, 3, 58, BTN_SM, BtnWfNFClick);
BtnHidePanel := MakeBtn(PanelSpanButtons, '◀ HIDE', 510, 3, 64, BTN_SM, BtnHidePanelClick);
BtnHidePanel := MakeBtn(PanelRight, '◀', 0, 0, 28, 28, BtnHidePanelClick);
BtnHidePanel.Font.Size := 10;
BtnHidePanel.ClrNorm := TColor($00543F18);
BtnHidePanel.ClrHot := TColor($00624B1D);
BtnHidePanel.ClrActive := TColor($00624B1D);
BtnHidePanel.ClrBorder := TColor($00685624);
BtnHidePanel.ClrText := TColor($00D8E6EE);
BtnHidePanel.ClrTextAct := TColor($00F0FAFF);
BtnHidePanel.BringToFront;
// Большой S-метр — на главной форме поверх двух панелей
// S-метр: Parent=Self, перекрывает Toolbar+SpanButtons вертикально
@@ -1359,7 +1366,6 @@ procedure TMainForm.ResizeSMeter;
// По Y: от самого верха формы до низа PanelSpanButtons (Toolbar+Span = 66px).
// По X: 40% ширины PanelRight, прижат к правому краю.
const
LEFT_PANEL_W = 232; // ширина левой панели (LEFT_W)
MARGIN = 3;
var
FW, FH: Integer;
@@ -1370,11 +1376,11 @@ var
SMBot: Integer;
begin
if (PanelSMeterRight = nil) or (PanelToolbar = nil) or
(PanelSpanButtons = nil) then Exit;
(PanelSpanButtons = nil) or (PanelLeft = nil) then Exit;
FW := ClientWidth;
// Ширина зоны спектра (PanelRight)
RightW := FW - LEFT_PANEL_W;
RightW := FW - PanelLeft.Width;
if RightW < 200 then Exit;
// Ширина S-метра = 40% от PanelRight
@@ -1499,12 +1505,12 @@ end;
procedure TMainForm.StyleSpanButton(B: TFlatButton; Active: Boolean);
begin
B.Active := Active;
B.ClrNorm := TColor($0013191B);
B.ClrActive := TColor($001E3C1E);
B.ClrHot := TColor($001E2D1E);
B.ClrBorder := TColor($005A7A5A);
B.ClrText := TColor($0090B890);
B.ClrTextAct := TColor($00AAFFAA);
B.ClrNorm := TColor($00543F18);
B.ClrActive := TColor($00624B1D);
B.ClrHot := TColor($00624B1D);
B.ClrBorder := TColor($00685624);
B.ClrText := TColor($00D8E6EE);
B.ClrTextAct := TColor($00F0FAFF);
B.Font.Name := 'Courier New';
B.Font.Size := 7;
end;
@@ -1545,6 +1551,8 @@ begin
BtnSpan384k.SetBounds(X, BaseY + BTN_TOP, W384, HBTN); Inc(X, W384 + GAP);
BtnSpan768k.SetBounds(X, BaseY + BTN_TOP, W768, HBTN); Inc(X, W768 + GAP);
BtnSpan1536k.SetBounds(X, BaseY + BTN_TOP, W1536, HBTN);
if BtnHidePanel <> nil then
BtnHidePanel.SetBounds(BaseX, BaseY + BTN_TOP, 28, HBTN);
BtnSpan48k.Visible := True;
BtnSpan96k.Visible := True;
@@ -1559,6 +1567,7 @@ begin
BtnSpan384k.BringToFront;
BtnSpan768k.BringToFront;
BtnSpan1536k.BringToFront;
if BtnHidePanel <> nil then BtnHidePanel.BringToFront;
end;
// ===========================================================================
@@ -1728,6 +1737,58 @@ begin
Desc.AlphaShift := 24; Desc.AlphaPrec := 8;
end;
function MixColorBGR(C1, C2: TColor; T: Double): TColor;
var
B1, G1, R1: Integer;
B2, G2, R2: Integer;
B, G, R: Integer;
begin
if T < 0.0 then T := 0.0 else
if T > 1.0 then T := 1.0;
B1 := (C1 shr 16) and $FF; G1 := (C1 shr 8) and $FF; R1 := C1 and $FF;
B2 := (C2 shr 16) and $FF; G2 := (C2 shr 8) and $FF; R2 := C2 and $FF;
B := Round(B1 + (B2 - B1) * T);
G := Round(G1 + (G2 - G1) * T);
R := Round(R1 + (R2 - R1) * T);
Result := TColor((B shl 16) or (G shl 8) or R);
end;
procedure PaintVerticalGradient(C: TCanvas; W, H: Integer; TopColor, BottomColor: TColor);
var
Y: Integer;
T: Double;
begin
if (W <= 0) or (H <= 0) then Exit;
C.Pen.Style := psClear;
C.Brush.Style := bsSolid;
for Y := 0 to H - 1 do
begin
T := Y / Max(1, H - 1);
C.Brush.Color := MixColorBGR(TopColor, BottomColor, T);
C.FillRect(Rect(0, Y, W, Y + 1));
end;
C.Pen.Style := psSolid;
end;
procedure PaintHorizontalFade(C: TCanvas; X1, X2, H: Integer; LeftColor, RightColor: TColor);
var
X: Integer;
T: Double;
begin
if (H <= 0) or (X2 <= X1) then Exit;
C.Pen.Style := psClear;
C.Brush.Style := bsSolid;
for X := X1 to X2 - 1 do
begin
T := (X - X1) / Max(1, X2 - X1 - 1);
C.Brush.Color := MixColorBGR(LeftColor, RightColor, T);
C.FillRect(Rect(X, 0, X + 1, H));
end;
C.Pen.Style := psSolid;
end;
procedure TMainForm.DrawSpectrumGradient(const SpPts: array of TPoint; W, H: Integer);
// ═══════════════════════════════════════════════════════════════════════
// Попиксельный градиент через кэшированный FSpecGradImg.
@@ -1815,6 +1876,7 @@ var
SrcF, Frac, dBv: Double;
S0, S1: Integer;
InvRange: Double;
LabelBandW: Integer;
begin
if FSpectrumBitmap = nil then Exit;
W := FSpectrumBitmap.Width;
@@ -1832,16 +1894,22 @@ begin
FGridBitmapH := H;
FGridBitmap.SetSize(W, H);
GC := FGridBitmap.Canvas;
GC.Brush.Color := TColor($00050505);
GC.FillRect(Rect(0, 0, W, H));
PaintVerticalGradient(GC, W, H, TColor($0020160B), TColor($006C4F1F));
LabelBandW := 28;
GC.Pen.Style := psClear;
GC.Brush.Style := bsSolid;
GC.Brush.Color := TColor($00543F18);
GC.FillRect(Rect(0, 0, LabelBandW, H));
GC.Pen.Style := psSolid;
GC.Font.Size := 7;
GC.Font.Name := 'Courier New';
GC.Font.Color := CLR_TEXTDIM;
dB := -30.0;
GC.Font.Color := TColor($00A8C9D9);
GC.Brush.Style := bsClear;
dB := -40.0;
while dB >= DBmin do
begin
Yp := Round((DBmax - dB) * InvRange * H);
GC.Pen.Color := CLR_BORDER;
GC.Pen.Color := TColor($00685624);
GC.Pen.Width := 1;
GC.MoveTo(0, Yp); GC.LineTo(W-1, Yp);
GC.TextOut(1, Yp - 9, Format('%4.0f', [dB]));
@@ -1850,7 +1918,7 @@ begin
for i := 0 to 8 do
begin
GX := ScaleX(i, 8, W);
GC.Pen.Color := CLR_BORDER;
GC.Pen.Color := TColor($00685624);
GC.MoveTo(GX, 0); GC.LineTo(GX, H);
end;
end;
@@ -1866,7 +1934,7 @@ begin
end;
X1 := Max(0, Min(W-1, VfoX + Round(Lo_Hz / FSpanHz * W)));
X2 := Max(0, Min(W-1, VfoX + Round(Hi_Hz / FSpanHz * W)));
C.Brush.Color := TColor($00102828);
C.Brush.Color := TColor($006A4E22);
C.Brush.Style := bsSolid;
C.Pen.Style := psClear;
if X2 > X1 then C.FillRect(Rect(X1, 0, X2, H));
@@ -2457,24 +2525,24 @@ begin
FRulerBitmap.SetSize(W, H);
C := FRulerBitmap.Canvas;
C.Brush.Color := TColor($00141414);
C.FillRect(Rect(0, 0, W, H));
C.Pen.Color := CLR_BORDER;
PaintVerticalGradient(C, W, H, TColor($00372A12), TColor($00705A2A));
C.Pen.Color := TColor($00685624);
C.Pen.Width := 1;
C.MoveTo(0, 0); C.LineTo(W, 0);
C.MoveTo(0, H-1); C.LineTo(W, H-1);
C.Font.Name := 'Courier New';
C.Font.Size := 7;
C.Brush.Style := bsClear;
FreqStart := FCenterFreq - FSpanHz / 2;
for i := 0 to 8 do
begin
X := ScaleX(i, 8, W);
C.Pen.Color := CLR_BORDER;
C.Pen.Color := TColor($00685624);
C.MoveTo(X, 0); C.LineTo(X, H div 2);
FreqHz := FreqStart + i * FSpanHz / 8;
Lbl := Format('%.3f', [FreqHz / 1e6]);
TW := C.TextWidth(Lbl);
C.Font.Color := TColor($00888888);
C.Font.Color := TColor($00C8D8E2);
C.TextOut(X - TW div 2, H div 2 - 1, Lbl);
end;
VfoX := Round((FVfoA - FCenterFreq + FSpanHz / 2) / FSpanHz * W);
@@ -3746,11 +3814,10 @@ end;
procedure TMainForm.BtnHidePanelClick(Sender: TObject);
begin
FPanelHidden := not FPanelHidden;
PanelLeft.Visible := not FPanelHidden;
if FPanelHidden then
begin
BtnHidePanel.Caption := '▶ SHOW';
// PbSpectrum — TGraphicControl, не TWinControl, используем PanelRight
PanelLeft.Width := 0;
BtnHidePanel.Caption := '▶';
FVfoOverlay.Parent := PanelRight;
FVfoOverlay.Width := 260;
FVfoOverlay.Height := 130;
@@ -3761,9 +3828,11 @@ begin
end
else
begin
BtnHidePanel.Caption := '◀ HIDE';
PanelLeft.Width := 232;
BtnHidePanel.Caption := '◀';
FVfoOverlay.Visible := False;
end;
ResizeSpectrumPanels;
ResizeSMeter;
end;