mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
ui(channels): redesign editor and fix DPI scaling
This commit is contained in:
+247
-92
@@ -14,7 +14,7 @@ uses
|
|||||||
Forms, Controls, Graphics, StdCtrls, ExtCtrls,
|
Forms, Controls, Graphics, StdCtrls, ExtCtrls,
|
||||||
FlatButton, FlatCheckBox, FlatComboBox, FlatEdit,
|
FlatButton, FlatCheckBox, FlatComboBox, FlatEdit,
|
||||||
FlatSpinEdit, FlatFloatSpinEdit, FlatListBox,
|
FlatSpinEdit, FlatFloatSpinEdit, FlatListBox,
|
||||||
AppTheme, ChannelStore, RadioModes;
|
AppTheme, ChannelStore, RadioModes, DpiUtils;
|
||||||
|
|
||||||
const
|
const
|
||||||
// Копии из MainForm: нужны для выпадающих списков
|
// Копии из MainForm: нужны для выпадающих списков
|
||||||
@@ -39,10 +39,19 @@ type
|
|||||||
FBtnDelete: TFlatButton;
|
FBtnDelete: TFlatButton;
|
||||||
FBtnUp: TFlatButton;
|
FBtnUp: TFlatButton;
|
||||||
FBtnDown: TFlatButton;
|
FBtnDown: TFlatButton;
|
||||||
|
FBtnClose: TFlatButton;
|
||||||
FList: TFlatListBox;
|
FList: TFlatListBox;
|
||||||
|
|
||||||
// --- Правая панель (поля редактирования) ---
|
// --- Правая панель (поля редактирования) ---
|
||||||
FPanelRight: TPanel;
|
FPanelRight: TPanel;
|
||||||
|
FFooterPanel: TPanel;
|
||||||
|
FCardIdentity: TPanel;
|
||||||
|
FCardRadio: TPanel;
|
||||||
|
FCardRepeater: TPanel;
|
||||||
|
FLeftTitle: TLabel;
|
||||||
|
FLeftHint: TLabel;
|
||||||
|
FRightTitle: TLabel;
|
||||||
|
FRightHint: TLabel;
|
||||||
|
|
||||||
// Labels (для перекраски темой)
|
// Labels (для перекраски темой)
|
||||||
FLbls: array of TLabel;
|
FLbls: array of TLabel;
|
||||||
@@ -66,11 +75,13 @@ type
|
|||||||
FUpdating: Boolean;
|
FUpdating: Boolean;
|
||||||
FOnChanged: TNotifyEvent;
|
FOnChanged: TNotifyEvent;
|
||||||
FCurrentDefaults: TChannel; // значения по умолчанию для новых каналов
|
FCurrentDefaults: TChannel; // значения по умолчанию для новых каналов
|
||||||
|
FTheme: TAppTheme;
|
||||||
|
|
||||||
procedure BuildUI;
|
procedure BuildUI;
|
||||||
procedure StyleBtn(B: TFlatButton; AActive: Boolean = False);
|
procedure StyleBtn(B: TFlatButton; AActive: Boolean = False);
|
||||||
function MakeLabel(AParent: TWinControl; const Cap: string;
|
function MakeLabel(AParent: TWinControl; const Cap: string;
|
||||||
X, Y, W, H: Integer): TLabel;
|
X, Y, W, H: Integer): TLabel;
|
||||||
|
function MakeGroupPanel(const Cap: string; Y, H: Integer): TPanel;
|
||||||
procedure LoadChannelToFields(Idx: Integer);
|
procedure LoadChannelToFields(Idx: Integer);
|
||||||
procedure SaveFieldsToChannel;
|
procedure SaveFieldsToChannel;
|
||||||
procedure RefreshList(KeepIdx: Integer = -1);
|
procedure RefreshList(KeepIdx: Integer = -1);
|
||||||
@@ -90,6 +101,7 @@ type
|
|||||||
procedure OnCTCSSChkChange(Sender: TObject);
|
procedure OnCTCSSChkChange(Sender: TObject);
|
||||||
procedure OnCTCSSCmbChange(Sender: TObject);
|
procedure OnCTCSSCmbChange(Sender: TObject);
|
||||||
// Handlers — форма
|
// Handlers — форма
|
||||||
|
procedure OnCloseClick(Sender: TObject);
|
||||||
procedure OnFormClose(Sender: TObject; var CloseAction: TCloseAction);
|
procedure OnFormClose(Sender: TObject; var CloseAction: TCloseAction);
|
||||||
public
|
public
|
||||||
constructor Create(AOwner: TComponent; AStore: TChannelStore;
|
constructor Create(AOwner: TComponent; AStore: TChannelStore;
|
||||||
@@ -103,31 +115,54 @@ implementation
|
|||||||
|
|
||||||
const
|
const
|
||||||
// Геометрия
|
// Геометрия
|
||||||
LPANEL_W = 185; // ширина левой панели
|
LPANEL_W = 240;
|
||||||
TOOLBAR_H = 32; // высота тулбара с кнопками Add/Del/Up/Down
|
TOOLBAR_Y = 66;
|
||||||
BTN_H = 24;
|
TOOLBAR_H = 30;
|
||||||
|
BTN_H = 26;
|
||||||
|
FORM_W = 820;
|
||||||
|
FORM_H = 540;
|
||||||
|
PAGE_MARGIN = 18;
|
||||||
|
|
||||||
// Правая панель
|
// Правая панель
|
||||||
LBL_X = 8;
|
LBL_X = 14;
|
||||||
LBL_W = 95;
|
LBL_W = 106;
|
||||||
CTRL_X = 106;
|
CTRL_X = 126;
|
||||||
ROW_H = 30; // высота строки
|
ROW_H = 28;
|
||||||
CTRL_H = 24; // высота контрола
|
CTRL_H = 24;
|
||||||
|
|
||||||
constructor TChannelsForm.Create(AOwner: TComponent; AStore: TChannelStore;
|
constructor TChannelsForm.Create(AOwner: TComponent; AStore: TChannelStore;
|
||||||
AOnChanged: TNotifyEvent);
|
AOnChanged: TNotifyEvent);
|
||||||
|
var
|
||||||
|
WorkArea: TRect;
|
||||||
|
MaxW, MaxH: Integer;
|
||||||
begin
|
begin
|
||||||
inherited CreateNew(AOwner);
|
inherited CreateNew(AOwner);
|
||||||
FStore := AStore;
|
FStore := AStore;
|
||||||
FOnChanged := AOnChanged;
|
FOnChanged := AOnChanged;
|
||||||
FUpdating := False;
|
FUpdating := False;
|
||||||
|
FTheme := DarkTheme;
|
||||||
TChannelStore.DefaultChannel(FCurrentDefaults);
|
TChannelStore.DefaultChannel(FCurrentDefaults);
|
||||||
|
|
||||||
|
Scaled := False;
|
||||||
Caption := 'Channels';
|
Caption := 'Channels';
|
||||||
BorderStyle := bsSizeable;
|
BorderStyle := bsSizeable;
|
||||||
Width := 720;
|
if AOwner is TCustomForm then
|
||||||
Height := 480;
|
begin
|
||||||
Position := poScreenCenter;
|
WorkArea := TCustomForm(AOwner).BoundsRect;
|
||||||
|
WorkArea := Screen.MonitorFromRect(WorkArea).WorkareaRect;
|
||||||
|
Position := poOwnerFormCenter;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
WorkArea := Screen.PrimaryMonitor.WorkareaRect;
|
||||||
|
Position := poScreenCenter;
|
||||||
|
end;
|
||||||
|
MaxW := WorkArea.Right - WorkArea.Left - DpiScale(48);
|
||||||
|
MaxH := WorkArea.Bottom - WorkArea.Top - DpiScale(48);
|
||||||
|
Width := Min(DpiScale(FORM_W), MaxW);
|
||||||
|
Height := Min(DpiScale(FORM_H), MaxH);
|
||||||
|
Constraints.MinWidth := Min(DpiScale(680), Width);
|
||||||
|
Constraints.MinHeight := Min(DpiScale(530), Height);
|
||||||
KeyPreview := True;
|
KeyPreview := True;
|
||||||
OnClose := @OnFormClose;
|
OnClose := @OnFormClose;
|
||||||
|
|
||||||
@@ -138,46 +173,72 @@ end;
|
|||||||
|
|
||||||
procedure TChannelsForm.BuildUI;
|
procedure TChannelsForm.BuildUI;
|
||||||
var
|
var
|
||||||
i: Integer;
|
i, BtnW, CardW, Y: Integer;
|
||||||
BtnW: Integer;
|
L: TLabel;
|
||||||
RW: Integer; // ширина правой панели
|
|
||||||
Y: Integer;
|
procedure PlaceRightUnit(AParent: TWinControl; const Cap: string;
|
||||||
|
ATop: Integer);
|
||||||
|
begin
|
||||||
|
L := MakeLabel(AParent, Cap, 0, ATop + 1, 42, CTRL_H);
|
||||||
|
L.SetBounds(AParent.ClientWidth - DpiScale(50), DpiScale(ATop + 1),
|
||||||
|
DpiScale(42), DpiScale(CTRL_H));
|
||||||
|
L.Anchors := [akTop, akRight];
|
||||||
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
SetLength(FLbls, 0);
|
||||||
|
|
||||||
// ----- Левая панель -----
|
// ----- Левая панель -----
|
||||||
FPanelLeft := TPanel.Create(Self);
|
FPanelLeft := TPanel.Create(Self);
|
||||||
FPanelLeft.Parent := Self;
|
FPanelLeft.Parent := Self;
|
||||||
FPanelLeft.Align := alLeft;
|
FPanelLeft.Align := alLeft;
|
||||||
FPanelLeft.Width := LPANEL_W;
|
FPanelLeft.Width := DpiScale(LPANEL_W);
|
||||||
FPanelLeft.BevelOuter := bvNone;
|
FPanelLeft.BevelOuter := bvNone;
|
||||||
|
|
||||||
BtnW := (LPANEL_W - 4 - 3 * 2) div 4; // 4 кнопки с зазорами
|
FLeftTitle := MakeLabel(FPanelLeft, 'CHANNEL MEMORY',
|
||||||
|
14, 12, LPANEL_W - 28, 24);
|
||||||
|
FLeftTitle.Font.Size := 9;
|
||||||
|
FLeftTitle.Font.Style := [fsBold];
|
||||||
|
FLeftTitle.Font.Color := FTheme.Text;
|
||||||
|
|
||||||
|
FLeftHint := MakeLabel(FPanelLeft, 'Saved frequencies and modes',
|
||||||
|
14, 37, LPANEL_W - 28, 18);
|
||||||
|
FLeftHint.Font.Size := 8;
|
||||||
|
|
||||||
|
BtnW := (DpiScale(LPANEL_W - 24) - 3 * DpiScale(6)) div 4;
|
||||||
FBtnAdd := TFlatButton.Create(Self);
|
FBtnAdd := TFlatButton.Create(Self);
|
||||||
FBtnAdd.Parent := FPanelLeft;
|
FBtnAdd.Parent := FPanelLeft;
|
||||||
FBtnAdd.SetBounds(2, 4, BtnW, BTN_H);
|
FBtnAdd.SetBounds(DpiScale(12), DpiScale(TOOLBAR_Y),
|
||||||
|
BtnW, DpiScale(BTN_H));
|
||||||
FBtnAdd.Caption := 'ADD';
|
FBtnAdd.Caption := 'ADD';
|
||||||
FBtnAdd.OnClick := @OnAddClick;
|
FBtnAdd.OnClick := @OnAddClick;
|
||||||
|
|
||||||
FBtnDelete := TFlatButton.Create(Self);
|
FBtnDelete := TFlatButton.Create(Self);
|
||||||
FBtnDelete.Parent := FPanelLeft;
|
FBtnDelete.Parent := FPanelLeft;
|
||||||
FBtnDelete.SetBounds(2 + (BtnW + 2), 4, BtnW, BTN_H);
|
FBtnDelete.SetBounds(FBtnAdd.Left + BtnW + DpiScale(6),
|
||||||
|
FBtnAdd.Top, BtnW, FBtnAdd.Height);
|
||||||
FBtnDelete.Caption := 'DEL';
|
FBtnDelete.Caption := 'DEL';
|
||||||
FBtnDelete.OnClick := @OnDeleteClick;
|
FBtnDelete.OnClick := @OnDeleteClick;
|
||||||
|
|
||||||
FBtnUp := TFlatButton.Create(Self);
|
FBtnUp := TFlatButton.Create(Self);
|
||||||
FBtnUp.Parent := FPanelLeft;
|
FBtnUp.Parent := FPanelLeft;
|
||||||
FBtnUp.SetBounds(2 + 2 * (BtnW + 2), 4, BtnW, BTN_H);
|
FBtnUp.SetBounds(FBtnDelete.Left + BtnW + DpiScale(6),
|
||||||
|
FBtnAdd.Top, BtnW, FBtnAdd.Height);
|
||||||
FBtnUp.Caption := '↑';
|
FBtnUp.Caption := '↑';
|
||||||
FBtnUp.OnClick := @OnUpClick;
|
FBtnUp.OnClick := @OnUpClick;
|
||||||
|
|
||||||
FBtnDown := TFlatButton.Create(Self);
|
FBtnDown := TFlatButton.Create(Self);
|
||||||
FBtnDown.Parent := FPanelLeft;
|
FBtnDown.Parent := FPanelLeft;
|
||||||
FBtnDown.SetBounds(2 + 3 * (BtnW + 2), 4, BtnW, BTN_H);
|
FBtnDown.SetBounds(FBtnUp.Left + BtnW + DpiScale(6),
|
||||||
|
FBtnAdd.Top, BtnW, FBtnAdd.Height);
|
||||||
FBtnDown.Caption := '↓';
|
FBtnDown.Caption := '↓';
|
||||||
FBtnDown.OnClick := @OnDownClick;
|
FBtnDown.OnClick := @OnDownClick;
|
||||||
|
|
||||||
FList := TFlatListBox.Create(Self);
|
FList := TFlatListBox.Create(Self);
|
||||||
FList.Parent := FPanelLeft;
|
FList.Parent := FPanelLeft;
|
||||||
FList.SetBounds(0, TOOLBAR_H, LPANEL_W, FPanelLeft.Height - TOOLBAR_H);
|
FList.SetBounds(DpiScale(12), DpiScale(TOOLBAR_Y + TOOLBAR_H + 10),
|
||||||
|
FPanelLeft.ClientWidth - DpiScale(24),
|
||||||
|
FPanelLeft.ClientHeight - DpiScale(TOOLBAR_Y + TOOLBAR_H + 22));
|
||||||
FList.Anchors := [akLeft, akTop, akRight, akBottom];
|
FList.Anchors := [akLeft, akTop, akRight, akBottom];
|
||||||
FList.OnClick := @OnListClick;
|
FList.OnClick := @OnListClick;
|
||||||
FList.OnDblClick := @OnListDblClick;
|
FList.OnDblClick := @OnListDblClick;
|
||||||
@@ -188,34 +249,62 @@ begin
|
|||||||
FPanelRight.Align := alClient;
|
FPanelRight.Align := alClient;
|
||||||
FPanelRight.BevelOuter := bvNone;
|
FPanelRight.BevelOuter := bvNone;
|
||||||
|
|
||||||
SetLength(FLbls, 0);
|
FFooterPanel := TPanel.Create(Self);
|
||||||
RW := Width - LPANEL_W;
|
FFooterPanel.Parent := FPanelRight;
|
||||||
|
FFooterPanel.Align := alBottom;
|
||||||
|
FFooterPanel.Height := DpiScale(50);
|
||||||
|
FFooterPanel.BevelOuter := bvNone;
|
||||||
|
|
||||||
Y := 8;
|
FBtnClose := TFlatButton.Create(Self);
|
||||||
|
FBtnClose.Parent := FFooterPanel;
|
||||||
|
FBtnClose.Caption := 'Close';
|
||||||
|
FBtnClose.SetBounds(FFooterPanel.ClientWidth - DpiScale(110),
|
||||||
|
DpiScale(10), DpiScale(92), DpiScale(30));
|
||||||
|
FBtnClose.Anchors := [akTop, akRight];
|
||||||
|
FBtnClose.OnClick := @OnCloseClick;
|
||||||
|
|
||||||
// Group
|
FRightTitle := MakeLabel(FPanelRight, 'CHANNEL DETAILS',
|
||||||
MakeLabel(FPanelRight, 'Group', LBL_X, Y + 1, LBL_W, CTRL_H);
|
PAGE_MARGIN, 10, 420, 22);
|
||||||
|
FRightTitle.Font.Size := 9;
|
||||||
|
FRightTitle.Font.Style := [fsBold];
|
||||||
|
FRightTitle.Font.Color := FTheme.Text;
|
||||||
|
FRightTitle.Anchors := [akLeft, akTop, akRight];
|
||||||
|
|
||||||
|
FRightHint := MakeLabel(FPanelRight,
|
||||||
|
'Changes are saved automatically', PAGE_MARGIN, 31, 420, 18);
|
||||||
|
FRightHint.Font.Size := 8;
|
||||||
|
FRightHint.Anchors := [akLeft, akTop, akRight];
|
||||||
|
|
||||||
|
FCardIdentity := MakeGroupPanel('IDENTITY', 56, 90);
|
||||||
|
CardW := FCardIdentity.ClientWidth;
|
||||||
|
Y := 34;
|
||||||
|
|
||||||
|
MakeLabel(FCardIdentity, 'Group', LBL_X, Y + 1, LBL_W, CTRL_H);
|
||||||
FEdGroup := TFlatEdit.Create(Self);
|
FEdGroup := TFlatEdit.Create(Self);
|
||||||
FEdGroup.Parent := FPanelRight;
|
FEdGroup.Parent := FCardIdentity;
|
||||||
FEdGroup.SetBounds(CTRL_X, Y, RW - CTRL_X - 8, CTRL_H);
|
FEdGroup.SetBounds(DpiScale(CTRL_X), DpiScale(Y),
|
||||||
|
CardW - DpiScale(CTRL_X + 14), DpiScale(CTRL_H));
|
||||||
FEdGroup.Anchors := [akLeft, akTop, akRight];
|
FEdGroup.Anchors := [akLeft, akTop, akRight];
|
||||||
FEdGroup.OnChange := @OnFieldChange;
|
FEdGroup.OnChange := @OnFieldChange;
|
||||||
Inc(Y, ROW_H);
|
Inc(Y, ROW_H);
|
||||||
|
|
||||||
// Name
|
MakeLabel(FCardIdentity, 'Name', LBL_X, Y + 1, LBL_W, CTRL_H);
|
||||||
MakeLabel(FPanelRight, 'Name', LBL_X, Y + 1, LBL_W, CTRL_H);
|
|
||||||
FEdName := TFlatEdit.Create(Self);
|
FEdName := TFlatEdit.Create(Self);
|
||||||
FEdName.Parent := FPanelRight;
|
FEdName.Parent := FCardIdentity;
|
||||||
FEdName.SetBounds(CTRL_X, Y, RW - CTRL_X - 8, CTRL_H);
|
FEdName.SetBounds(DpiScale(CTRL_X), DpiScale(Y),
|
||||||
|
CardW - DpiScale(CTRL_X + 14), DpiScale(CTRL_H));
|
||||||
FEdName.Anchors := [akLeft, akTop, akRight];
|
FEdName.Anchors := [akLeft, akTop, akRight];
|
||||||
FEdName.OnChange := @OnFieldChange;
|
FEdName.OnChange := @OnFieldChange;
|
||||||
Inc(Y, ROW_H);
|
|
||||||
|
|
||||||
// RX Freq
|
FCardRadio := MakeGroupPanel('RADIO', 156, 120);
|
||||||
MakeLabel(FPanelRight, 'RX Freq', LBL_X, Y + 1, LBL_W, CTRL_H);
|
CardW := FCardRadio.ClientWidth;
|
||||||
|
Y := 34;
|
||||||
|
|
||||||
|
MakeLabel(FCardRadio, 'RX frequency', LBL_X, Y + 1, LBL_W, CTRL_H);
|
||||||
FSpinRXFreq := TFlatFloatSpinEdit.Create(Self);
|
FSpinRXFreq := TFlatFloatSpinEdit.Create(Self);
|
||||||
FSpinRXFreq.Parent := FPanelRight;
|
FSpinRXFreq.Parent := FCardRadio;
|
||||||
FSpinRXFreq.SetBounds(CTRL_X, Y, RW - CTRL_X - 50, CTRL_H);
|
FSpinRXFreq.SetBounds(DpiScale(CTRL_X), DpiScale(Y),
|
||||||
|
CardW - DpiScale(CTRL_X + 56), DpiScale(CTRL_H));
|
||||||
FSpinRXFreq.Anchors := [akLeft, akTop, akRight];
|
FSpinRXFreq.Anchors := [akLeft, akTop, akRight];
|
||||||
FSpinRXFreq.MinValue := 0.001;
|
FSpinRXFreq.MinValue := 0.001;
|
||||||
FSpinRXFreq.MaxValue := 2000.0;
|
FSpinRXFreq.MaxValue := 2000.0;
|
||||||
@@ -223,14 +312,14 @@ begin
|
|||||||
FSpinRXFreq.DecimalPlaces := 6;
|
FSpinRXFreq.DecimalPlaces := 6;
|
||||||
FSpinRXFreq.Value := 145.5;
|
FSpinRXFreq.Value := 145.5;
|
||||||
FSpinRXFreq.OnChange := @OnFieldChange;
|
FSpinRXFreq.OnChange := @OnFieldChange;
|
||||||
MakeLabel(FPanelRight, 'MHz', RW - 46, Y + 1, 40, CTRL_H);
|
PlaceRightUnit(FCardRadio, 'MHz', Y);
|
||||||
Inc(Y, ROW_H);
|
Inc(Y, ROW_H);
|
||||||
|
|
||||||
// TX Freq
|
MakeLabel(FCardRadio, 'TX frequency', LBL_X, Y + 1, LBL_W, CTRL_H);
|
||||||
MakeLabel(FPanelRight, 'TX Freq', LBL_X, Y + 1, LBL_W, CTRL_H);
|
|
||||||
FSpinTXFreq := TFlatFloatSpinEdit.Create(Self);
|
FSpinTXFreq := TFlatFloatSpinEdit.Create(Self);
|
||||||
FSpinTXFreq.Parent := FPanelRight;
|
FSpinTXFreq.Parent := FCardRadio;
|
||||||
FSpinTXFreq.SetBounds(CTRL_X, Y, RW - CTRL_X - 50, CTRL_H);
|
FSpinTXFreq.SetBounds(DpiScale(CTRL_X), DpiScale(Y),
|
||||||
|
CardW - DpiScale(CTRL_X + 56), DpiScale(CTRL_H));
|
||||||
FSpinTXFreq.Anchors := [akLeft, akTop, akRight];
|
FSpinTXFreq.Anchors := [akLeft, akTop, akRight];
|
||||||
FSpinTXFreq.MinValue := 0.001;
|
FSpinTXFreq.MinValue := 0.001;
|
||||||
FSpinTXFreq.MaxValue := 2000.0;
|
FSpinTXFreq.MaxValue := 2000.0;
|
||||||
@@ -238,48 +327,53 @@ begin
|
|||||||
FSpinTXFreq.DecimalPlaces := 6;
|
FSpinTXFreq.DecimalPlaces := 6;
|
||||||
FSpinTXFreq.Value := 145.5;
|
FSpinTXFreq.Value := 145.5;
|
||||||
FSpinTXFreq.OnChange := @OnFieldChange;
|
FSpinTXFreq.OnChange := @OnFieldChange;
|
||||||
MakeLabel(FPanelRight, 'MHz', RW - 46, Y + 1, 40, CTRL_H);
|
PlaceRightUnit(FCardRadio, 'MHz', Y);
|
||||||
Inc(Y, ROW_H);
|
Inc(Y, ROW_H);
|
||||||
|
|
||||||
// Mode
|
MakeLabel(FCardRadio, 'Mode', LBL_X, Y + 1, LBL_W, CTRL_H);
|
||||||
MakeLabel(FPanelRight, 'Mode', LBL_X, Y + 1, LBL_W, CTRL_H);
|
|
||||||
FCmbMode := TFlatComboBox.Create(Self);
|
FCmbMode := TFlatComboBox.Create(Self);
|
||||||
FCmbMode.Parent := FPanelRight;
|
FCmbMode.Parent := FCardRadio;
|
||||||
FCmbMode.SetBounds(CTRL_X, Y, 160, CTRL_H);
|
FCmbMode.SetBounds(DpiScale(CTRL_X), DpiScale(Y),
|
||||||
|
DpiScale(180), DpiScale(CTRL_H));
|
||||||
for i := 0 to CH_MODE_COUNT - 1 do FCmbMode.Items.Add(CH_MODE_NAMES[i]);
|
for i := 0 to CH_MODE_COUNT - 1 do FCmbMode.Items.Add(CH_MODE_NAMES[i]);
|
||||||
FCmbMode.ItemIndex := 5; // FM default
|
FCmbMode.ItemIndex := 5; // FM default
|
||||||
FCmbMode.OnChange := @OnFieldChange;
|
FCmbMode.OnChange := @OnFieldChange;
|
||||||
Inc(Y, ROW_H);
|
|
||||||
|
|
||||||
// RPTR direction
|
FCardRepeater := MakeGroupPanel('REPEATER / TRANSMIT', 286, 148);
|
||||||
MakeLabel(FPanelRight, 'RPTR', LBL_X, Y + 1, LBL_W, CTRL_H);
|
CardW := FCardRepeater.ClientWidth;
|
||||||
|
Y := 34;
|
||||||
|
|
||||||
|
MakeLabel(FCardRepeater, 'Direction', LBL_X, Y + 1, LBL_W, CTRL_H);
|
||||||
FBtnRptNone := TFlatButton.Create(Self);
|
FBtnRptNone := TFlatButton.Create(Self);
|
||||||
FBtnRptNone.Parent := FPanelRight;
|
FBtnRptNone.Parent := FCardRepeater;
|
||||||
FBtnRptNone.SetBounds(CTRL_X, Y, 55, CTRL_H);
|
FBtnRptNone.SetBounds(DpiScale(CTRL_X), DpiScale(Y),
|
||||||
|
DpiScale(72), DpiScale(CTRL_H));
|
||||||
FBtnRptNone.Caption := 'NONE';
|
FBtnRptNone.Caption := 'NONE';
|
||||||
FBtnRptNone.Tag := 0;
|
FBtnRptNone.Tag := 0;
|
||||||
FBtnRptNone.OnClick := @OnRptBtnClick;
|
FBtnRptNone.OnClick := @OnRptBtnClick;
|
||||||
|
|
||||||
FBtnRptMinus := TFlatButton.Create(Self);
|
FBtnRptMinus := TFlatButton.Create(Self);
|
||||||
FBtnRptMinus.Parent := FPanelRight;
|
FBtnRptMinus.Parent := FCardRepeater;
|
||||||
FBtnRptMinus.SetBounds(CTRL_X + 58, Y, 38, CTRL_H);
|
FBtnRptMinus.SetBounds(DpiScale(CTRL_X + 78), DpiScale(Y),
|
||||||
|
DpiScale(46), DpiScale(CTRL_H));
|
||||||
FBtnRptMinus.Caption := '−';
|
FBtnRptMinus.Caption := '−';
|
||||||
FBtnRptMinus.Tag := 1;
|
FBtnRptMinus.Tag := 1;
|
||||||
FBtnRptMinus.OnClick := @OnRptBtnClick;
|
FBtnRptMinus.OnClick := @OnRptBtnClick;
|
||||||
|
|
||||||
FBtnRptPlus := TFlatButton.Create(Self);
|
FBtnRptPlus := TFlatButton.Create(Self);
|
||||||
FBtnRptPlus.Parent := FPanelRight;
|
FBtnRptPlus.Parent := FCardRepeater;
|
||||||
FBtnRptPlus.SetBounds(CTRL_X + 99, Y, 38, CTRL_H);
|
FBtnRptPlus.SetBounds(DpiScale(CTRL_X + 130), DpiScale(Y),
|
||||||
|
DpiScale(46), DpiScale(CTRL_H));
|
||||||
FBtnRptPlus.Caption := '+';
|
FBtnRptPlus.Caption := '+';
|
||||||
FBtnRptPlus.Tag := 2;
|
FBtnRptPlus.Tag := 2;
|
||||||
FBtnRptPlus.OnClick := @OnRptBtnClick;
|
FBtnRptPlus.OnClick := @OnRptBtnClick;
|
||||||
Inc(Y, ROW_H);
|
Inc(Y, ROW_H);
|
||||||
|
|
||||||
// RPTR Offset
|
MakeLabel(FCardRepeater, 'Offset', LBL_X, Y + 1, LBL_W, CTRL_H);
|
||||||
MakeLabel(FPanelRight, 'RPT Offset', LBL_X, Y + 1, LBL_W, CTRL_H);
|
|
||||||
FSpinRptOffset := TFlatFloatSpinEdit.Create(Self);
|
FSpinRptOffset := TFlatFloatSpinEdit.Create(Self);
|
||||||
FSpinRptOffset.Parent := FPanelRight;
|
FSpinRptOffset.Parent := FCardRepeater;
|
||||||
FSpinRptOffset.SetBounds(CTRL_X, Y, RW - CTRL_X - 50, CTRL_H);
|
FSpinRptOffset.SetBounds(DpiScale(CTRL_X), DpiScale(Y),
|
||||||
|
CardW - DpiScale(CTRL_X + 56), DpiScale(CTRL_H));
|
||||||
FSpinRptOffset.Anchors := [akLeft, akTop, akRight];
|
FSpinRptOffset.Anchors := [akLeft, akTop, akRight];
|
||||||
FSpinRptOffset.MinValue := 0.0;
|
FSpinRptOffset.MinValue := 0.0;
|
||||||
FSpinRptOffset.MaxValue := 100.0;
|
FSpinRptOffset.MaxValue := 100.0;
|
||||||
@@ -287,37 +381,38 @@ begin
|
|||||||
FSpinRptOffset.DecimalPlaces := 3;
|
FSpinRptOffset.DecimalPlaces := 3;
|
||||||
FSpinRptOffset.Value := 0.6;
|
FSpinRptOffset.Value := 0.6;
|
||||||
FSpinRptOffset.OnChange := @OnFieldChange;
|
FSpinRptOffset.OnChange := @OnFieldChange;
|
||||||
MakeLabel(FPanelRight, 'MHz', RW - 46, Y + 1, 40, CTRL_H);
|
PlaceRightUnit(FCardRepeater, 'MHz', Y);
|
||||||
Inc(Y, ROW_H);
|
Inc(Y, ROW_H);
|
||||||
|
|
||||||
// CTCSS
|
MakeLabel(FCardRepeater, 'CTCSS tone', LBL_X, Y + 1, LBL_W, CTRL_H);
|
||||||
MakeLabel(FPanelRight, 'CTCSS', LBL_X, Y + 1, LBL_W, CTRL_H);
|
|
||||||
FChkCTCSS := TFlatCheckBox.Create(Self);
|
FChkCTCSS := TFlatCheckBox.Create(Self);
|
||||||
FChkCTCSS.Parent := FPanelRight;
|
FChkCTCSS.Parent := FCardRepeater;
|
||||||
FChkCTCSS.SetBounds(CTRL_X, Y, 26, CTRL_H);
|
FChkCTCSS.SetBounds(DpiScale(CTRL_X), DpiScale(Y),
|
||||||
|
DpiScale(28), DpiScale(CTRL_H));
|
||||||
FChkCTCSS.Caption := '';
|
FChkCTCSS.Caption := '';
|
||||||
FChkCTCSS.Checked := False;
|
FChkCTCSS.Checked := False;
|
||||||
FChkCTCSS.OnChange := @OnCTCSSChkChange;
|
FChkCTCSS.OnChange := @OnCTCSSChkChange;
|
||||||
|
|
||||||
FCmbCTCSS := TFlatComboBox.Create(Self);
|
FCmbCTCSS := TFlatComboBox.Create(Self);
|
||||||
FCmbCTCSS.Parent := FPanelRight;
|
FCmbCTCSS.Parent := FCardRepeater;
|
||||||
FCmbCTCSS.SetBounds(CTRL_X + 30, Y, RW - CTRL_X - 38, CTRL_H);
|
FCmbCTCSS.SetBounds(DpiScale(CTRL_X + 34), DpiScale(Y),
|
||||||
|
CardW - DpiScale(CTRL_X + 48), DpiScale(CTRL_H));
|
||||||
FCmbCTCSS.Anchors := [akLeft, akTop, akRight];
|
FCmbCTCSS.Anchors := [akLeft, akTop, akRight];
|
||||||
for i := 0 to CH_CTCSS_COUNT - 1 do FCmbCTCSS.Items.Add(CH_CTCSS_NAMES[i]);
|
for i := 0 to CH_CTCSS_COUNT - 1 do FCmbCTCSS.Items.Add(CH_CTCSS_NAMES[i]);
|
||||||
FCmbCTCSS.ItemIndex := 0;
|
FCmbCTCSS.ItemIndex := 0;
|
||||||
FCmbCTCSS.OnChange := @OnCTCSSCmbChange;
|
FCmbCTCSS.OnChange := @OnCTCSSCmbChange;
|
||||||
Inc(Y, ROW_H);
|
Inc(Y, ROW_H);
|
||||||
|
|
||||||
// Power
|
MakeLabel(FCardRepeater, 'Power', LBL_X, Y + 1, LBL_W, CTRL_H);
|
||||||
MakeLabel(FPanelRight, 'Power', LBL_X, Y + 1, LBL_W, CTRL_H);
|
|
||||||
FSpinPower := TFlatSpinEdit.Create(Self);
|
FSpinPower := TFlatSpinEdit.Create(Self);
|
||||||
FSpinPower.Parent := FPanelRight;
|
FSpinPower.Parent := FCardRepeater;
|
||||||
FSpinPower.SetBounds(CTRL_X, Y, 80, CTRL_H);
|
FSpinPower.SetBounds(DpiScale(CTRL_X), DpiScale(Y),
|
||||||
|
DpiScale(92), DpiScale(CTRL_H));
|
||||||
FSpinPower.MinValue := 0;
|
FSpinPower.MinValue := 0;
|
||||||
FSpinPower.MaxValue := 100;
|
FSpinPower.MaxValue := 100;
|
||||||
FSpinPower.Value := 100;
|
FSpinPower.Value := 100;
|
||||||
FSpinPower.OnChange := @OnFieldChange;
|
FSpinPower.OnChange := @OnFieldChange;
|
||||||
MakeLabel(FPanelRight, '%', CTRL_X + 84, Y + 1, 20, CTRL_H);
|
MakeLabel(FCardRepeater, '%', CTRL_X + 98, Y + 1, 24, CTRL_H);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TChannelsForm.MakeLabel(AParent: TWinControl; const Cap: string;
|
function TChannelsForm.MakeLabel(AParent: TWinControl; const Cap: string;
|
||||||
@@ -327,37 +422,86 @@ begin
|
|||||||
L := TLabel.Create(Self);
|
L := TLabel.Create(Self);
|
||||||
L.Parent := AParent;
|
L.Parent := AParent;
|
||||||
L.Caption := Cap;
|
L.Caption := Cap;
|
||||||
L.SetBounds(X, Y, W, H);
|
L.AutoSize := False;
|
||||||
L.Font.Name := 'Courier New';
|
L.SetBounds(DpiScale(X), DpiScale(Y), DpiScale(W), DpiScale(H));
|
||||||
|
L.Layout := tlCenter;
|
||||||
L.Font.Size := 8;
|
L.Font.Size := 8;
|
||||||
L.Font.Color := DarkTheme.TextDim;
|
L.Font.Color := FTheme.TextDim;
|
||||||
// Сохраняем для последующей перекраски темой
|
// Сохраняем для последующей перекраски темой
|
||||||
SetLength(FLbls, Length(FLbls) + 1);
|
SetLength(FLbls, Length(FLbls) + 1);
|
||||||
FLbls[High(FLbls)] := L;
|
FLbls[High(FLbls)] := L;
|
||||||
Result := L;
|
Result := L;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TChannelsForm.StyleBtn(B: TFlatButton; AActive: Boolean);
|
function TChannelsForm.MakeGroupPanel(const Cap: string; Y, H: Integer): TPanel;
|
||||||
var T: TAppTheme;
|
var
|
||||||
|
Title: TLabel;
|
||||||
|
Divider: TPanel;
|
||||||
begin
|
begin
|
||||||
T := DarkTheme;
|
Result := TPanel.Create(Self);
|
||||||
|
Result.Parent := FPanelRight;
|
||||||
|
Result.SetBounds(DpiScale(PAGE_MARGIN), DpiScale(Y),
|
||||||
|
FPanelRight.ClientWidth - DpiScale(2 * PAGE_MARGIN), DpiScale(H));
|
||||||
|
Result.Anchors := [akLeft, akTop, akRight];
|
||||||
|
Result.BevelOuter := bvNone;
|
||||||
|
Result.Color := FTheme.Panel;
|
||||||
|
|
||||||
|
Title := MakeLabel(Result, Cap, 12, 2, 300, 24);
|
||||||
|
Title.Font.Size := 8;
|
||||||
|
Title.Font.Style := [fsBold];
|
||||||
|
Title.Font.Color := FTheme.FreqActive;
|
||||||
|
|
||||||
|
Divider := TPanel.Create(Self);
|
||||||
|
Divider.Parent := Result;
|
||||||
|
Divider.SetBounds(0, DpiScale(28), Result.ClientWidth, 1);
|
||||||
|
Divider.Anchors := [akLeft, akTop, akRight];
|
||||||
|
Divider.BevelOuter := bvNone;
|
||||||
|
Divider.Color := FTheme.Border;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TChannelsForm.StyleBtn(B: TFlatButton; AActive: Boolean);
|
||||||
|
begin
|
||||||
|
// Прямо созданные TFlatButton не проходят через MakeFlatBtn, поэтому
|
||||||
|
// явно даём им тот же системный шрифт, что и остальному интерфейсу.
|
||||||
|
B.Font.Assign(Font);
|
||||||
|
B.Font.Size := 8;
|
||||||
|
B.Font.Style := [];
|
||||||
B.Active := AActive;
|
B.Active := AActive;
|
||||||
B.ClrNorm := T.BtnNorm;
|
B.ClrNorm := FTheme.BtnNorm;
|
||||||
B.ClrActive := T.BtnActive;
|
B.ClrActive := FTheme.BtnActive;
|
||||||
B.ClrHot := T.BtnHot;
|
B.ClrHot := FTheme.BtnHot;
|
||||||
B.ClrBorder := IfThen(AActive, T.BtnBorderActive, T.BtnBorderNorm);
|
B.ClrBorder := IfThen(AActive,
|
||||||
B.ClrText := T.BtnText;
|
FTheme.BtnBorderActive, FTheme.BtnBorderNorm);
|
||||||
B.ClrTextAct := T.BtnTextActive;
|
B.ClrText := FTheme.BtnText;
|
||||||
|
B.ClrTextAct := FTheme.BtnTextActive;
|
||||||
|
B.Invalidate;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TChannelsForm.ApplyTheme(const T: TAppTheme);
|
procedure TChannelsForm.ApplyTheme(const T: TAppTheme);
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
Ch: TChannel;
|
Ch: TChannel;
|
||||||
|
|
||||||
|
procedure ThemeCard(P: TPanel);
|
||||||
|
var
|
||||||
|
n: Integer;
|
||||||
|
begin
|
||||||
|
if P = nil then Exit;
|
||||||
|
P.Color := T.Panel;
|
||||||
|
for n := 0 to P.ControlCount - 1 do
|
||||||
|
if (P.Controls[n] is TPanel) and (P.Controls[n].Height = 1) then
|
||||||
|
TPanel(P.Controls[n]).Color := T.Border;
|
||||||
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Color := T.Panel;
|
FTheme := T;
|
||||||
|
Color := T.BG;
|
||||||
FPanelLeft.Color := T.Panel;
|
FPanelLeft.Color := T.Panel;
|
||||||
FPanelRight.Color := T.Panel;
|
FPanelRight.Color := T.BG;
|
||||||
|
FFooterPanel.Color := T.BG;
|
||||||
|
ThemeCard(FCardIdentity);
|
||||||
|
ThemeCard(FCardRadio);
|
||||||
|
ThemeCard(FCardRepeater);
|
||||||
|
|
||||||
FList.SetAppTheme(T);
|
FList.SetAppTheme(T);
|
||||||
|
|
||||||
@@ -365,6 +509,7 @@ begin
|
|||||||
StyleBtn(FBtnDelete);
|
StyleBtn(FBtnDelete);
|
||||||
StyleBtn(FBtnUp);
|
StyleBtn(FBtnUp);
|
||||||
StyleBtn(FBtnDown);
|
StyleBtn(FBtnDown);
|
||||||
|
StyleBtn(FBtnClose);
|
||||||
|
|
||||||
// RPT buttons — пересчитываем Active из текущего состояния
|
// RPT buttons — пересчитываем Active из текущего состояния
|
||||||
if SelectedIdx >= 0 then
|
if SelectedIdx >= 0 then
|
||||||
@@ -393,9 +538,15 @@ begin
|
|||||||
|
|
||||||
for i := 0 to High(FLbls) do
|
for i := 0 to High(FLbls) do
|
||||||
begin
|
begin
|
||||||
FLbls[i].Font.Color := T.TextDim;
|
if FLbls[i] = FLeftTitle then
|
||||||
FLbls[i].Color := T.Panel;
|
FLbls[i].Font.Color := T.Text
|
||||||
FLbls[i].ParentColor := False;
|
else if FLbls[i] = FRightTitle then
|
||||||
|
FLbls[i].Font.Color := T.Text
|
||||||
|
else if fsBold in FLbls[i].Font.Style then
|
||||||
|
FLbls[i].Font.Color := T.FreqActive
|
||||||
|
else
|
||||||
|
FLbls[i].Font.Color := T.TextDim;
|
||||||
|
FLbls[i].Transparent := True;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -476,7 +627,6 @@ procedure TChannelsForm.SaveFieldsToChannel;
|
|||||||
var
|
var
|
||||||
Idx: Integer;
|
Idx: Integer;
|
||||||
Ch: TChannel;
|
Ch: TChannel;
|
||||||
i: Integer;
|
|
||||||
begin
|
begin
|
||||||
if FUpdating then Exit;
|
if FUpdating then Exit;
|
||||||
Idx := SelectedIdx;
|
Idx := SelectedIdx;
|
||||||
@@ -607,6 +757,11 @@ begin
|
|||||||
SaveFieldsToChannel;
|
SaveFieldsToChannel;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TChannelsForm.OnCloseClick(Sender: TObject);
|
||||||
|
begin
|
||||||
|
Close;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TChannelsForm.OnFormClose(Sender: TObject; var CloseAction: TCloseAction);
|
procedure TChannelsForm.OnFormClose(Sender: TObject; var CloseAction: TCloseAction);
|
||||||
begin
|
begin
|
||||||
CloseAction := caHide; // скрываем, не уничтожаем — указатель в MainForm остаётся валидным
|
CloseAction := caHide; // скрываем, не уничтожаем — указатель в MainForm остаётся валидным
|
||||||
|
|||||||
Reference in New Issue
Block a user