unit ChannelsForm;

{ TChannelsForm — редактор списка каналов (channel memory).
  Открывается по правой кнопке мыши на кнопке CH в блоке RX левой панели.
  Список каналов слева (FlatListBox), поля редактирования справа.
  Все изменения сохраняются немедленно в TChannelStore и на диск. }

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Math,
  Forms, Controls, Graphics, StdCtrls, ExtCtrls,
  FlatButton, FlatCheckBox, FlatComboBox, FlatEdit,
  FlatSpinEdit, FlatFloatSpinEdit, FlatListBox,
  AppTheme, ChannelStore;

const
  // Копии из MainForm: нужны для выпадающих списков
  CH_MODE_COUNT = 12;
  CH_MODE_NAMES: array[0..CH_MODE_COUNT-1] of string =
    ('LSB','USB','DSB','CWL','CWU','FM','AM','SAM','DIGU','DIGL','WFM','DMR');

  CH_CTCSS_COUNT = 38;
  CH_CTCSS_NAMES: array[0..CH_CTCSS_COUNT-1] of string = (
    '67.0', '71.9', '74.4', '77.0', '79.7', '82.5', '85.4', '88.5',
    '91.5', '94.8', '97.4', '100.0', '103.5', '107.2', '110.9', '114.8',
    '118.8', '123.0', '127.3', '131.8', '136.5', '141.3', '146.2', '151.4',
    '156.7', '162.2', '167.9', '173.8', '179.9', '186.2', '192.8', '203.5',
    '210.7', '218.1', '225.7', '233.6', '241.8', '250.3');

type
  TChannelsForm = class(TForm)
  private
    // --- Левая панель ---
    FPanelLeft:   TPanel;
    FBtnAdd:      TFlatButton;
    FBtnDelete:   TFlatButton;
    FBtnUp:       TFlatButton;
    FBtnDown:     TFlatButton;
    FList:        TFlatListBox;

    // --- Правая панель (поля редактирования) ---
    FPanelRight:  TPanel;

    // Labels (для перекраски темой)
    FLbls: array of TLabel;

    // Поля
    FEdGroup:      TFlatEdit;
    FEdName:       TFlatEdit;
    FSpinRXFreq:   TFlatFloatSpinEdit;
    FSpinTXFreq:   TFlatFloatSpinEdit;
    FCmbMode:      TFlatComboBox;
    FBtnRptNone:   TFlatButton;
    FBtnRptMinus:  TFlatButton;
    FBtnRptPlus:   TFlatButton;
    FSpinRptOffset: TFlatFloatSpinEdit;
    FChkCTCSS:     TFlatCheckBox;
    FCmbCTCSS:     TFlatComboBox;
    FSpinPower:    TFlatSpinEdit;

    // Данные
    FStore:            TChannelStore;
    FUpdating:         Boolean;
    FOnChanged:        TNotifyEvent;
    FCurrentDefaults:  TChannel;   // значения по умолчанию для новых каналов

    procedure BuildUI;
    procedure StyleBtn(B: TFlatButton; AActive: Boolean = False);
    function  MakeLabel(AParent: TWinControl; const Cap: string;
                        X, Y, W, H: Integer): TLabel;
    procedure LoadChannelToFields(Idx: Integer);
    procedure SaveFieldsToChannel;
    procedure RefreshList(KeepIdx: Integer = -1);
    function  SelectedIdx: Integer;

    // Handlers — список
    procedure OnListClick(Sender: TObject);
    procedure OnListDblClick(Sender: TObject);
    // Handlers — тулбар
    procedure OnAddClick(Sender: TObject);
    procedure OnDeleteClick(Sender: TObject);
    procedure OnUpClick(Sender: TObject);
    procedure OnDownClick(Sender: TObject);
    // Handlers — поля
    procedure OnFieldChange(Sender: TObject);
    procedure OnRptBtnClick(Sender: TObject);
    procedure OnCTCSSChkChange(Sender: TObject);
    procedure OnCTCSSCmbChange(Sender: TObject);
    // Handlers — форма
    procedure OnFormClose(Sender: TObject; var CloseAction: TCloseAction);
  public
    constructor Create(AOwner: TComponent; AStore: TChannelStore;
                       AOnChanged: TNotifyEvent); reintroduce;
    procedure ApplyTheme(const T: TAppTheme);
    procedure SetCurrentDefaults(const Ch: TChannel);
    property OnChannelsChanged: TNotifyEvent read FOnChanged write FOnChanged;
  end;

implementation

const
  // Геометрия
  LPANEL_W  = 185;   // ширина левой панели
  TOOLBAR_H = 32;    // высота тулбара с кнопками Add/Del/Up/Down
  BTN_H     = 24;

  // Правая панель
  LBL_X     = 8;
  LBL_W     = 95;
  CTRL_X    = 106;
  ROW_H     = 30;    // высота строки
  CTRL_H    = 24;    // высота контрола

constructor TChannelsForm.Create(AOwner: TComponent; AStore: TChannelStore;
                                  AOnChanged: TNotifyEvent);
begin
  inherited CreateNew(AOwner);
  FStore     := AStore;
  FOnChanged := AOnChanged;
  FUpdating  := False;
  TChannelStore.DefaultChannel(FCurrentDefaults);

  Caption      := 'Channels';
  BorderStyle  := bsSizeable;
  Width        := 720;
  Height       := 480;
  Position     := poScreenCenter;
  KeyPreview   := True;
  OnClose      := @OnFormClose;

  BuildUI;
  ApplyTheme(DarkTheme);
  RefreshList(0);
end;

procedure TChannelsForm.BuildUI;
var
  i: Integer;
  BtnW: Integer;
  RW: Integer;  // ширина правой панели
  Y: Integer;
begin
  // ----- Левая панель -----
  FPanelLeft := TPanel.Create(Self);
  FPanelLeft.Parent     := Self;
  FPanelLeft.Align      := alLeft;
  FPanelLeft.Width      := LPANEL_W;
  FPanelLeft.BevelOuter := bvNone;

  BtnW := (LPANEL_W - 4 - 3 * 2) div 4;  // 4 кнопки с зазорами
  FBtnAdd := TFlatButton.Create(Self);
  FBtnAdd.Parent  := FPanelLeft;
  FBtnAdd.SetBounds(2, 4, BtnW, BTN_H);
  FBtnAdd.Caption := 'ADD';
  FBtnAdd.OnClick := @OnAddClick;

  FBtnDelete := TFlatButton.Create(Self);
  FBtnDelete.Parent  := FPanelLeft;
  FBtnDelete.SetBounds(2 + (BtnW + 2), 4, BtnW, BTN_H);
  FBtnDelete.Caption := 'DEL';
  FBtnDelete.OnClick := @OnDeleteClick;

  FBtnUp := TFlatButton.Create(Self);
  FBtnUp.Parent  := FPanelLeft;
  FBtnUp.SetBounds(2 + 2 * (BtnW + 2), 4, BtnW, BTN_H);
  FBtnUp.Caption := '↑';
  FBtnUp.OnClick := @OnUpClick;

  FBtnDown := TFlatButton.Create(Self);
  FBtnDown.Parent  := FPanelLeft;
  FBtnDown.SetBounds(2 + 3 * (BtnW + 2), 4, BtnW, BTN_H);
  FBtnDown.Caption := '↓';
  FBtnDown.OnClick := @OnDownClick;

  FList := TFlatListBox.Create(Self);
  FList.Parent   := FPanelLeft;
  FList.SetBounds(0, TOOLBAR_H, LPANEL_W, FPanelLeft.Height - TOOLBAR_H);
  FList.Anchors  := [akLeft, akTop, akRight, akBottom];
  FList.OnClick  := @OnListClick;
  FList.OnDblClick := @OnListDblClick;

  // ----- Правая панель -----
  FPanelRight := TPanel.Create(Self);
  FPanelRight.Parent     := Self;
  FPanelRight.Align      := alClient;
  FPanelRight.BevelOuter := bvNone;

  SetLength(FLbls, 0);
  RW := Width - LPANEL_W;

  Y := 8;

  // Group
  MakeLabel(FPanelRight, 'Group', LBL_X, Y + 1, LBL_W, CTRL_H);
  FEdGroup := TFlatEdit.Create(Self);
  FEdGroup.Parent := FPanelRight;
  FEdGroup.SetBounds(CTRL_X, Y, RW - CTRL_X - 8, CTRL_H);
  FEdGroup.Anchors := [akLeft, akTop, akRight];
  FEdGroup.OnChange := @OnFieldChange;
  Inc(Y, ROW_H);

  // Name
  MakeLabel(FPanelRight, 'Name', LBL_X, Y + 1, LBL_W, CTRL_H);
  FEdName := TFlatEdit.Create(Self);
  FEdName.Parent := FPanelRight;
  FEdName.SetBounds(CTRL_X, Y, RW - CTRL_X - 8, CTRL_H);
  FEdName.Anchors := [akLeft, akTop, akRight];
  FEdName.OnChange := @OnFieldChange;
  Inc(Y, ROW_H);

  // RX Freq
  MakeLabel(FPanelRight, 'RX Freq', LBL_X, Y + 1, LBL_W, CTRL_H);
  FSpinRXFreq := TFlatFloatSpinEdit.Create(Self);
  FSpinRXFreq.Parent := FPanelRight;
  FSpinRXFreq.SetBounds(CTRL_X, Y, RW - CTRL_X - 50, CTRL_H);
  FSpinRXFreq.Anchors := [akLeft, akTop, akRight];
  FSpinRXFreq.MinValue := 0.001;
  FSpinRXFreq.MaxValue := 2000.0;
  FSpinRXFreq.Increment := 0.001;
  FSpinRXFreq.DecimalPlaces := 6;
  FSpinRXFreq.Value := 145.5;
  FSpinRXFreq.OnChange := @OnFieldChange;
  MakeLabel(FPanelRight, 'MHz', RW - 46, Y + 1, 40, CTRL_H);
  Inc(Y, ROW_H);

  // TX Freq
  MakeLabel(FPanelRight, 'TX Freq', LBL_X, Y + 1, LBL_W, CTRL_H);
  FSpinTXFreq := TFlatFloatSpinEdit.Create(Self);
  FSpinTXFreq.Parent := FPanelRight;
  FSpinTXFreq.SetBounds(CTRL_X, Y, RW - CTRL_X - 50, CTRL_H);
  FSpinTXFreq.Anchors := [akLeft, akTop, akRight];
  FSpinTXFreq.MinValue := 0.001;
  FSpinTXFreq.MaxValue := 2000.0;
  FSpinTXFreq.Increment := 0.001;
  FSpinTXFreq.DecimalPlaces := 6;
  FSpinTXFreq.Value := 145.5;
  FSpinTXFreq.OnChange := @OnFieldChange;
  MakeLabel(FPanelRight, 'MHz', RW - 46, Y + 1, 40, CTRL_H);
  Inc(Y, ROW_H);

  // Mode
  MakeLabel(FPanelRight, 'Mode', LBL_X, Y + 1, LBL_W, CTRL_H);
  FCmbMode := TFlatComboBox.Create(Self);
  FCmbMode.Parent := FPanelRight;
  FCmbMode.SetBounds(CTRL_X, Y, 160, CTRL_H);
  for i := 0 to CH_MODE_COUNT - 1 do FCmbMode.Items.Add(CH_MODE_NAMES[i]);
  FCmbMode.ItemIndex := 5; // FM default
  FCmbMode.OnChange := @OnFieldChange;
  Inc(Y, ROW_H);

  // RPTR direction
  MakeLabel(FPanelRight, 'RPTR', LBL_X, Y + 1, LBL_W, CTRL_H);
  FBtnRptNone := TFlatButton.Create(Self);
  FBtnRptNone.Parent  := FPanelRight;
  FBtnRptNone.SetBounds(CTRL_X, Y, 55, CTRL_H);
  FBtnRptNone.Caption := 'NONE';
  FBtnRptNone.Tag     := 0;
  FBtnRptNone.OnClick := @OnRptBtnClick;

  FBtnRptMinus := TFlatButton.Create(Self);
  FBtnRptMinus.Parent  := FPanelRight;
  FBtnRptMinus.SetBounds(CTRL_X + 58, Y, 38, CTRL_H);
  FBtnRptMinus.Caption := '−';
  FBtnRptMinus.Tag     := 1;
  FBtnRptMinus.OnClick := @OnRptBtnClick;

  FBtnRptPlus := TFlatButton.Create(Self);
  FBtnRptPlus.Parent  := FPanelRight;
  FBtnRptPlus.SetBounds(CTRL_X + 99, Y, 38, CTRL_H);
  FBtnRptPlus.Caption := '+';
  FBtnRptPlus.Tag     := 2;
  FBtnRptPlus.OnClick := @OnRptBtnClick;
  Inc(Y, ROW_H);

  // RPTR Offset
  MakeLabel(FPanelRight, 'RPT Offset', LBL_X, Y + 1, LBL_W, CTRL_H);
  FSpinRptOffset := TFlatFloatSpinEdit.Create(Self);
  FSpinRptOffset.Parent := FPanelRight;
  FSpinRptOffset.SetBounds(CTRL_X, Y, RW - CTRL_X - 50, CTRL_H);
  FSpinRptOffset.Anchors := [akLeft, akTop, akRight];
  FSpinRptOffset.MinValue := 0.0;
  FSpinRptOffset.MaxValue := 100.0;
  FSpinRptOffset.Increment := 0.025;
  FSpinRptOffset.DecimalPlaces := 3;
  FSpinRptOffset.Value := 0.6;
  FSpinRptOffset.OnChange := @OnFieldChange;
  MakeLabel(FPanelRight, 'MHz', RW - 46, Y + 1, 40, CTRL_H);
  Inc(Y, ROW_H);

  // CTCSS
  MakeLabel(FPanelRight, 'CTCSS', LBL_X, Y + 1, LBL_W, CTRL_H);
  FChkCTCSS := TFlatCheckBox.Create(Self);
  FChkCTCSS.Parent  := FPanelRight;
  FChkCTCSS.SetBounds(CTRL_X, Y, 26, CTRL_H);
  FChkCTCSS.Caption := '';
  FChkCTCSS.Checked := False;
  FChkCTCSS.OnChange := @OnCTCSSChkChange;

  FCmbCTCSS := TFlatComboBox.Create(Self);
  FCmbCTCSS.Parent := FPanelRight;
  FCmbCTCSS.SetBounds(CTRL_X + 30, Y, RW - CTRL_X - 38, CTRL_H);
  FCmbCTCSS.Anchors := [akLeft, akTop, akRight];
  for i := 0 to CH_CTCSS_COUNT - 1 do FCmbCTCSS.Items.Add(CH_CTCSS_NAMES[i]);
  FCmbCTCSS.ItemIndex := 0;
  FCmbCTCSS.OnChange := @OnCTCSSCmbChange;
  Inc(Y, ROW_H);

  // Power
  MakeLabel(FPanelRight, 'Power', LBL_X, Y + 1, LBL_W, CTRL_H);
  FSpinPower := TFlatSpinEdit.Create(Self);
  FSpinPower.Parent := FPanelRight;
  FSpinPower.SetBounds(CTRL_X, Y, 80, CTRL_H);
  FSpinPower.MinValue := 0;
  FSpinPower.MaxValue := 100;
  FSpinPower.Value := 100;
  FSpinPower.OnChange := @OnFieldChange;
  MakeLabel(FPanelRight, '%', CTRL_X + 84, Y + 1, 20, CTRL_H);
end;

function TChannelsForm.MakeLabel(AParent: TWinControl; const Cap: string;
  X, Y, W, H: Integer): TLabel;
var L: TLabel;
begin
  L := TLabel.Create(Self);
  L.Parent   := AParent;
  L.Caption  := Cap;
  L.SetBounds(X, Y, W, H);
  L.Font.Name := 'Courier New';
  L.Font.Size := 8;
  L.Font.Color := DarkTheme.TextDim;
  // Сохраняем для последующей перекраски темой
  SetLength(FLbls, Length(FLbls) + 1);
  FLbls[High(FLbls)] := L;
  Result := L;
end;

procedure TChannelsForm.StyleBtn(B: TFlatButton; AActive: Boolean);
var T: TAppTheme;
begin
  T := DarkTheme;
  B.Active      := AActive;
  B.ClrNorm     := T.BtnNorm;
  B.ClrActive   := T.BtnActive;
  B.ClrHot      := T.BtnHot;
  B.ClrBorder   := IfThen(AActive, T.BtnBorderActive, T.BtnBorderNorm);
  B.ClrText     := T.BtnText;
  B.ClrTextAct  := T.BtnTextActive;
end;

procedure TChannelsForm.ApplyTheme(const T: TAppTheme);
var
  i:  Integer;
  Ch: TChannel;
begin
  Color := T.Panel;
  FPanelLeft.Color  := T.Panel;
  FPanelRight.Color := T.Panel;

  FList.SetAppTheme(T);

  StyleBtn(FBtnAdd);
  StyleBtn(FBtnDelete);
  StyleBtn(FBtnUp);
  StyleBtn(FBtnDown);

  // RPT buttons — пересчитываем Active из текущего состояния
  if SelectedIdx >= 0 then
  begin
    Ch := FStore.GetChannel(SelectedIdx);
    StyleBtn(FBtnRptNone,  Ch.RptDir = 0);
    StyleBtn(FBtnRptMinus, Ch.RptDir = 1);
    StyleBtn(FBtnRptPlus,  Ch.RptDir = 2);
  end
  else
  begin
    StyleBtn(FBtnRptNone,  True);
    StyleBtn(FBtnRptMinus, False);
    StyleBtn(FBtnRptPlus,  False);
  end;

  FEdGroup.SetAppTheme(T);
  FEdName.SetAppTheme(T);
  FSpinRXFreq.SetAppTheme(T);
  FSpinTXFreq.SetAppTheme(T);
  FCmbMode.SetAppTheme(T);
  FSpinRptOffset.SetAppTheme(T);
  FChkCTCSS.SetAppTheme(T);
  FCmbCTCSS.SetAppTheme(T);
  FSpinPower.SetAppTheme(T);

  for i := 0 to High(FLbls) do
  begin
    FLbls[i].Font.Color := T.TextDim;
    FLbls[i].Color      := T.Panel;
    FLbls[i].ParentColor := False;
  end;
end;

// ---------------------------------------------------------------------------
// Список каналов
// ---------------------------------------------------------------------------

function TChannelsForm.SelectedIdx: Integer;
begin
  Result := FList.ItemIndex;
end;

procedure TChannelsForm.RefreshList(KeepIdx: Integer);
var
  i, NewIdx: Integer;
  Ch: TChannel;
begin
  FList.Items.Clear;
  for i := 0 to FStore.Count - 1 do
  begin
    Ch := FStore.GetChannel(i);
    if Ch.Group <> '' then
      FList.Items.Add(Ch.Group + ': ' + Ch.Name)
    else
      FList.Items.Add(Ch.Name);
  end;
  if FStore.Count = 0 then
  begin
    LoadChannelToFields(-1);
    Exit;
  end;
  NewIdx := EnsureRange(KeepIdx, 0, FStore.Count - 1);
  FList.ItemIndex := NewIdx;
  LoadChannelToFields(NewIdx);
end;

procedure TChannelsForm.LoadChannelToFields(Idx: Integer);
var Ch: TChannel;
    HasSel: Boolean;
begin
  FUpdating := True;
  try
    HasSel := (Idx >= 0) and (Idx < FStore.Count);
    FEdGroup.Enabled       := HasSel;
    FEdName.Enabled        := HasSel;
    FSpinRXFreq.Enabled    := HasSel;
    FSpinTXFreq.Enabled    := HasSel;
    FCmbMode.Enabled       := HasSel;
    FBtnRptNone.Enabled    := HasSel;
    FBtnRptMinus.Enabled   := HasSel;
    FBtnRptPlus.Enabled    := HasSel;
    FSpinRptOffset.Enabled := HasSel;
    FChkCTCSS.Enabled      := HasSel;
    FCmbCTCSS.Enabled      := HasSel;
    FSpinPower.Enabled      := HasSel;

    if not HasSel then Exit;

    Ch := FStore.GetChannel(Idx);
    FEdGroup.Text              := Ch.Group;
    FEdName.Text               := Ch.Name;
    FSpinRXFreq.Value          := Ch.RXFreq / 1000000.0;
    FSpinTXFreq.Value          := Ch.TXFreq / 1000000.0;
    FCmbMode.ItemIndex         := EnsureRange(Ch.Mode, 0, CH_MODE_COUNT - 1);
    StyleBtn(FBtnRptNone,  Ch.RptDir = 0);
    StyleBtn(FBtnRptMinus, Ch.RptDir = 1);
    StyleBtn(FBtnRptPlus,  Ch.RptDir = 2);
    FSpinRptOffset.Value       := Ch.RptOffsetHz / 1000000.0;
    FChkCTCSS.Checked          := Ch.CTCSSOn;
    FCmbCTCSS.ItemIndex        := EnsureRange(Ch.CTCSSToneIdx, 0, CH_CTCSS_COUNT - 1);
    FSpinPower.Value           := Ch.Power;
  finally
    FUpdating := False;
  end;
end;

procedure TChannelsForm.SaveFieldsToChannel;
var
  Idx: Integer;
  Ch:  TChannel;
  i:   Integer;
begin
  if FUpdating then Exit;
  Idx := SelectedIdx;
  if (Idx < 0) or (Idx >= FStore.Count) then Exit;

  Ch := FStore.GetChannel(Idx);
  Ch.Group        := FEdGroup.Text;
  Ch.Name         := FEdName.Text;
  Ch.RXFreq       := FSpinRXFreq.Value * 1000000.0;
  Ch.TXFreq       := FSpinTXFreq.Value * 1000000.0;
  Ch.Mode         := EnsureRange(FCmbMode.ItemIndex, 0, CH_MODE_COUNT - 1);
  // RptDir берётся из кнопок (Active)
  if FBtnRptMinus.Active then Ch.RptDir := 1
  else if FBtnRptPlus.Active then Ch.RptDir := 2
  else Ch.RptDir := 0;
  Ch.RptOffsetHz  := FSpinRptOffset.Value * 1000000.0;
  Ch.CTCSSOn      := FChkCTCSS.Checked;
  Ch.CTCSSToneIdx := EnsureRange(FCmbCTCSS.ItemIndex, 0, CH_CTCSS_COUNT - 1);
  Ch.Power        := FSpinPower.Value;

  FStore.UpdateChannel(Idx, Ch);
  FStore.Save;

  // Обновляем имя в списке
  FUpdating := True;
  try
    if Ch.Group <> '' then
      FList.Items[Idx] := Ch.Group + ': ' + Ch.Name
    else
      FList.Items[Idx] := Ch.Name;
  finally
    FUpdating := False;
  end;

  if Assigned(FOnChanged) then FOnChanged(Self);
end;

// ---------------------------------------------------------------------------
// Обработчики кнопок тулбара
// ---------------------------------------------------------------------------

procedure TChannelsForm.OnListClick(Sender: TObject);
begin
  if FUpdating then Exit;
  LoadChannelToFields(FList.ItemIndex);
end;

procedure TChannelsForm.OnListDblClick(Sender: TObject);
begin
  LoadChannelToFields(FList.ItemIndex);
end;

procedure TChannelsForm.OnAddClick(Sender: TObject);
var
  Ch:     TChannel;
  NewIdx: Integer;
begin
  Ch := FCurrentDefaults;   // берём значения текущего состояния радио
  FStore.AddChannel(Ch);
  FStore.Save;
  NewIdx := FStore.Count - 1;
  RefreshList(NewIdx);
  if Assigned(FOnChanged) then FOnChanged(Self);
  // Фокус на имя для быстрого переименования
  if FEdName.Enabled then FEdName.SetFocus;
  FEdName.SelectAll;
end;

procedure TChannelsForm.OnDeleteClick(Sender: TObject);
var Idx: Integer;
begin
  Idx := SelectedIdx;
  if (Idx < 0) or (Idx >= FStore.Count) then Exit;
  FStore.DeleteChannel(Idx);
  FStore.Save;
  RefreshList(EnsureRange(Idx, 0, FStore.Count - 1));
  if Assigned(FOnChanged) then FOnChanged(Self);
end;

procedure TChannelsForm.OnUpClick(Sender: TObject);
var Idx: Integer;
begin
  Idx := SelectedIdx;
  if Idx < 1 then Exit;
  FStore.MoveUp(Idx);
  FStore.Save;
  RefreshList(Idx - 1);
  if Assigned(FOnChanged) then FOnChanged(Self);
end;

procedure TChannelsForm.OnDownClick(Sender: TObject);
var Idx: Integer;
begin
  Idx := SelectedIdx;
  if (Idx < 0) or (Idx >= FStore.Count - 1) then Exit;
  FStore.MoveDown(Idx);
  FStore.Save;
  RefreshList(Idx + 1);
  if Assigned(FOnChanged) then FOnChanged(Self);
end;

// ---------------------------------------------------------------------------
// Обработчики полей редактирования
// ---------------------------------------------------------------------------

procedure TChannelsForm.OnFieldChange(Sender: TObject);
begin
  SaveFieldsToChannel;
end;

procedure TChannelsForm.OnRptBtnClick(Sender: TObject);
var Dir: Integer;
begin
  Dir := (Sender as TFlatButton).Tag;
  StyleBtn(FBtnRptNone,  Dir = 0);
  StyleBtn(FBtnRptMinus, Dir = 1);
  StyleBtn(FBtnRptPlus,  Dir = 2);
  SaveFieldsToChannel;
end;

procedure TChannelsForm.OnCTCSSChkChange(Sender: TObject);
begin
  SaveFieldsToChannel;
end;

procedure TChannelsForm.OnCTCSSCmbChange(Sender: TObject);
begin
  SaveFieldsToChannel;
end;

procedure TChannelsForm.OnFormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
  CloseAction := caHide;  // скрываем, не уничтожаем — указатель в MainForm остаётся валидным
end;

procedure TChannelsForm.SetCurrentDefaults(const Ch: TChannel);
begin
  FCurrentDefaults := Ch;
end;

end.
