Files
ewsdr/FlatButton.pas
ew8bakandClaude Sonnet 4.6 68d05657e6 Add FM mode improvements: NFM/FM filters, CTCSS, squelch; ADC and web settings
FM modulation:
- Replace 10 generic FM filter buttons with NFM (2.5kHz dev/11kHz BW) and FM
  (5.0kHz dev/16kHz BW); deviation applied to both RX and TX via WDSP
- Add FM squelch panel (SQL toggle + slider 0..100, per-band save/restore)
  with WDSP SetRXAFMSQRun/SetRXAFMSQThreshold (threshold = level/200.0)
- Add CTCSS panel with on/off toggle and custom flat-button tone picker popup
  (38 standard tones 67.0..250.3 Hz, default 67.0); tone selection and enable
  state saved per band via SetTXACTCSS*
- FM panels (SQL, CTCSS) shown only in FM mode, layout via RelayoutBelowBands
- PanelFilter height shrinks in FM mode so panels sit tight below filters
- FlatButton: handle CMTextChanged to invalidate on Caption change

ADC settings (Dither/Random):
- Add DitherEnabled/RandomEnabled to TGlobalSettings (default true)
- Pass as bitmask to ConfigureDDCs DDC Specific packet bytes 5/6
- Exposed in Settings → Advanced tab with live apply via ApplyADCSettings

Web server settings:
- Add TWebSettings (enabled, port, bind_addr, user, pass) stored globally
- WebServer: configurable port/bind IP via ParseIPv4; Reconfigure method
- Exposed in Settings → Advanced tab with live apply via ApplyWebSettings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 19:01:17 +03:00

179 lines
4.9 KiB
ObjectPascal

unit FlatButton;
{ Кнопка с полным контролем цвета на Windows и Linux.
Используй вместо TButton везде где нужна тёмная тема. }
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Controls, Graphics, LCLType, LMessages, Types;
type
TFlatButton = class(TGraphicControl)
private
FActive: Boolean;
FHot: Boolean;
FClrNorm: TColor;
FClrActive: TColor;
FClrHot: TColor;
FClrBorder: TColor;
FClrText: TColor;
FClrTextAct:TColor;
FOnClick: TNotifyEvent;
procedure SetActive(V: Boolean);
protected
procedure Paint; override;
procedure MouseEnter; override;
procedure MouseLeave; override;
procedure CMTextChanged(var Msg: TLMessage); message CM_TEXTCHANGED;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
public
constructor Create(AOwner: TComponent); override;
property Active: Boolean read FActive write SetActive;
property ClrNorm: TColor read FClrNorm write FClrNorm;
property ClrActive: TColor read FClrActive write FClrActive;
property ClrHot: TColor read FClrHot write FClrHot;
property ClrBorder: TColor read FClrBorder write FClrBorder;
property ClrText: TColor read FClrText write FClrText;
property ClrTextAct:TColor read FClrTextAct write FClrTextAct;
property OnClick: TNotifyEvent read FOnClick write FOnClick;
property Caption;
property Font;
property Enabled;
property Visible;
end;
// Фабрика — аналог MakeBtn, возвращает TFlatButton
function MakeFlatBtn(AParent: TWinControl; const ACap: string;
ALeft, ATop, AW, AH: Integer;
AHandler: TNotifyEvent;
ClrNorm: TColor = TColor($00202020);
ClrActive: TColor = TColor($00003300);
ClrHot: TColor = TColor($00303030);
ClrBorder: TColor = TColor($00404040);
ClrText: TColor = TColor($00E0E0E0);
ClrTextAct: TColor = TColor($0000FF88)): TFlatButton;
implementation
constructor TFlatButton.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FActive := False;
FHot := False;
FClrNorm := TColor($00202020);
FClrActive := TColor($00003300);
FClrHot := TColor($00303030);
FClrBorder := TColor($00404040);
FClrText := TColor($00E0E0E0);
FClrTextAct := TColor($0000FF88);
Cursor := crHandPoint;
end;
procedure TFlatButton.SetActive(V: Boolean);
begin
if FActive = V then Exit;
FActive := V;
Invalidate;
end;
procedure TFlatButton.Paint;
const
CORNER = 3;
var
R: TRect;
TW, TH: Integer;
BG: TColor;
begin
R := ClientRect;
if FActive then BG := FClrActive
else if FHot then BG := FClrHot
else BG := FClrNorm;
// Фон со скруглёнными углами
Canvas.Brush.Color := BG;
Canvas.Brush.Style := bsSolid;
Canvas.Pen.Color := BG;
Canvas.Pen.Style := psSolid;
Canvas.RoundRect(R.Left, R.Top, R.Right, R.Bottom, CORNER * 2, CORNER * 2);
// Рамка
Canvas.Pen.Color := FClrBorder;
Canvas.Brush.Style := bsClear;
Canvas.RoundRect(R.Left, R.Top, R.Right - 1, R.Bottom - 1, CORNER * 2, CORNER * 2);
// Текст
if FActive then Canvas.Font.Color := FClrTextAct
else Canvas.Font.Color := FClrText;
Canvas.Brush.Style := bsClear;
TW := Canvas.TextWidth(Caption);
TH := Canvas.TextHeight('A');
Canvas.TextOut((Width - TW) div 2, (Height - TH) div 2, Caption);
end;
procedure TFlatButton.MouseEnter;
begin
inherited;
FHot := True;
Invalidate;
end;
procedure TFlatButton.MouseLeave;
begin
inherited;
FHot := False;
Invalidate;
end;
procedure TFlatButton.CMTextChanged(var Msg: TLMessage);
begin
Invalidate;
end;
procedure TFlatButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
inherited;
end;
procedure TFlatButton.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
inherited;
if (Button = mbLeft) and PtInRect(ClientRect, Point(X, Y)) then
if Assigned(FOnClick) then FOnClick(Self);
end;
function MakeFlatBtn(AParent: TWinControl; const ACap: string;
ALeft, ATop, AW, AH: Integer;
AHandler: TNotifyEvent;
ClrNorm, ClrActive, ClrHot, ClrBorder, ClrText, ClrTextAct: TColor): TFlatButton;
begin
Result := TFlatButton.Create(AParent);
Result.Parent := AParent;
Result.Caption := ACap;
Result.Left := ALeft;
Result.Top := ATop;
Result.Width := AW;
Result.Height := AH;
Result.OnClick := AHandler;
Result.ClrNorm := ClrNorm;
Result.ClrActive := ClrActive;
Result.ClrHot := ClrHot;
Result.ClrBorder := ClrBorder;
Result.ClrText := ClrText;
Result.ClrTextAct := ClrTextAct;
Result.Font.Name := 'Courier New';
Result.Font.Size := 8;
Result.Font.Color := ClrText;
end;
end.