// =====================================================
//
//   miniLA_win - Channel setup
//
//   (c) miniLA Team
//
// =====================================================
//
// This is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This software is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this package; see the file COPYING.  If not, write to
// the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.


unit dlgChannel;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Buttons, uDisplay, Menus, uLATypes;

type
  TfrmChannel = class(TForm)
    ScrollBox1: TScrollBox;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    ComboBox1: TComboBox;
    Button1: TButton;
    CheckBox1: TCheckBox;
    Edit1: TEdit;
    Label6: TLabel;
    Label7: TLabel;
    Edit2: TEdit;
    CheckBox2: TCheckBox;
    Button2: TButton;
    ComboBox2: TComboBox;
    ComboBox3: TComboBox;
    ComboBox4: TComboBox;
    ComboBox5: TComboBox;
    ComboBox6: TComboBox;
    ComboBox7: TComboBox;
    ComboBox8: TComboBox;
    ComboBox9: TComboBox;
    ComboBox10: TComboBox;
    ComboBox11: TComboBox;
    ComboBox12: TComboBox;
    ComboBox13: TComboBox;
    ComboBox14: TComboBox;
    ComboBox15: TComboBox;
    ComboBox16: TComboBox;
    ComboBox17: TComboBox;
    Button17: TButton;
    Button16: TButton;
    Button15: TButton;
    Button14: TButton;
    Button13: TButton;
    Button12: TButton;
    Button11: TButton;
    Button10: TButton;
    Button8: TButton;
    Button9: TButton;
    Button7: TButton;
    Button6: TButton;
    Button5: TButton;
    Button4: TButton;
    Button3: TButton;
    CheckBox3: TCheckBox;
    CheckBox4: TCheckBox;
    CheckBox5: TCheckBox;
    CheckBox6: TCheckBox;
    CheckBox7: TCheckBox;
    CheckBox8: TCheckBox;
    CheckBox9: TCheckBox;
    CheckBox10: TCheckBox;
    CheckBox11: TCheckBox;
    CheckBox12: TCheckBox;
    CheckBox13: TCheckBox;
    CheckBox14: TCheckBox;
    CheckBox15: TCheckBox;
    CheckBox16: TCheckBox;
    CheckBox17: TCheckBox;
    Edit17: TEdit;
    Edit16: TEdit;
    Edit15: TEdit;
    Edit14: TEdit;
    Edit13: TEdit;
    Edit12: TEdit;
    Edit11: TEdit;
    Edit10: TEdit;
    Edit9: TEdit;
    Edit8: TEdit;
    Edit7: TEdit;
    Edit6: TEdit;
    Edit5: TEdit;
    Edit4: TEdit;
    Edit3: TEdit;
    Label8: TLabel;
    Label9: TLabel;
    Label10: TLabel;
    Label11: TLabel;
    Label12: TLabel;
    Label13: TLabel;
    Label14: TLabel;
    Label15: TLabel;
    Label16: TLabel;
    Label17: TLabel;
    Label18: TLabel;
    Label19: TLabel;
    Label20: TLabel;
    Label21: TLabel;
    Label22: TLabel;
    ComboBox18: TComboBox;
    Button18: TButton;
    CheckBox18: TCheckBox;
    Edit18: TEdit;
    Label28: TLabel;
    Label29: TLabel;
    Edit19: TEdit;
    CheckBox19: TCheckBox;
    Button19: TButton;
    ComboBox19: TComboBox;
    ComboBox20: TComboBox;
    ComboBox21: TComboBox;
    ComboBox22: TComboBox;
    ComboBox23: TComboBox;
    ComboBox24: TComboBox;
    ComboBox25: TComboBox;
    ComboBox26: TComboBox;
    ComboBox27: TComboBox;
    ComboBox28: TComboBox;
    ComboBox29: TComboBox;
    ComboBox30: TComboBox;
    ComboBox31: TComboBox;
    ComboBox32: TComboBox;
    Button22: TButton;
    Button23: TButton;
    Button24: TButton;
    Button25: TButton;
    Button26: TButton;
    Button27: TButton;
    Button28: TButton;
    Button29: TButton;
    Button30: TButton;
    Button31: TButton;
    Button32: TButton;
    Button21: TButton;
    Button20: TButton;
    CheckBox20: TCheckBox;
    CheckBox21: TCheckBox;
    CheckBox22: TCheckBox;
    CheckBox23: TCheckBox;
    CheckBox24: TCheckBox;
    CheckBox25: TCheckBox;
    CheckBox26: TCheckBox;
    CheckBox27: TCheckBox;
    CheckBox28: TCheckBox;
    CheckBox29: TCheckBox;
    CheckBox30: TCheckBox;
    CheckBox31: TCheckBox;
    CheckBox32: TCheckBox;
    Edit32: TEdit;
    Edit31: TEdit;
    Edit30: TEdit;
    Edit29: TEdit;
    Edit28: TEdit;
    Edit27: TEdit;
    Edit26: TEdit;
    Edit25: TEdit;
    Edit24: TEdit;
    Edit23: TEdit;
    Edit22: TEdit;
    Edit21: TEdit;
    Edit20: TEdit;
    Label30: TLabel;
    Label31: TLabel;
    Label32: TLabel;
    Label33: TLabel;
    Label34: TLabel;
    Label35: TLabel;
    Label36: TLabel;
    Label37: TLabel;
    Label38: TLabel;
    Label39: TLabel;
    Label40: TLabel;
    Label41: TLabel;
    Label42: TLabel;
    GroupBox1: TGroupBox;
    lbSigWeights: TListBox;
    Label26: TLabel;
    btnMoveSignalTop: TButton;
    btnMoveSignalUp: TButton;
    btnMoveSignalDown: TButton;
    btnMoveSignalBottom: TButton;
    cbGroupRadix: TComboBox;
    btnOK: TBitBtn;
    GroupBox2: TGroupBox;
    btnRemoveGroup: TButton;
    btnNewGroup: TButton;
    btnRenameGroup: TButton;
    lbGroups: TListBox;
    Label23: TLabel;
    btnMoveGroupTop: TButton;
    btnMoveGroupUp: TButton;
    btnMoveGroupDown: TButton;
    btnMoveGroupBottom: TButton;
    ColorDialog1: TColorDialog;
    procedure btnNewGroupClick(Sender: TObject);
    procedure btnRemoveGroupClick(Sender: TObject);
    procedure btnRenameGroupClick(Sender: TObject);
    procedure lbGroupsClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ComboBox1Change(Sender: TObject);
    procedure btnMoveSignalTopClick(Sender: TObject);
    procedure btnMoveSignalBottomClick(Sender: TObject);
    procedure btnMoveSignalUpClick(Sender: TObject);
    procedure btnMoveSignalDownClick(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure btnMoveGroupTopClick(Sender: TObject);
    procedure btnMoveGroupUpClick(Sender: TObject);
    procedure btnMoveGroupDownClick(Sender: TObject);
    procedure btnMoveGroupBottomClick(Sender: TObject);
    procedure btnOKClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormActivate(Sender: TObject);
  private
    { Private declarations }
    FEnabledChannels:integer;
  public
    { Public declarations }
    ChannelInfo:TChannelRecs;
    FreeList:TStrings;
    DefaultSigColor:TColor;
    function SaveLayout(FileName:string):integer;
    function LoadLayout(FileName:string):integer;
    procedure SetEnabledChannels(num: byte; force: boolean);
  end;

type TGroupList=class(TStringList)
     public
       Base:integer;
       constructor Create;
     end;

var
  frmChannel: TfrmChannel;

implementation

uses dlgGroup, dlgMain, ComCtrls, uINIFile;

{$R *.DFM}

procedure TfrmChannel.FormCreate(Sender: TObject);
var i:byte;
begin

  DefaultSigColor := INIFile.ReadInteger('GUI','SIGNAL_COLOR', (51*256+185)*256+85); // olive, teal

  // load array
  ChannelInfo[0].Edit:=Edit1;
  ChannelInfo[0].Enabled:=CheckBox1;
  ChannelInfo[0].Color:=Button1;
  ChannelInfo[0].Group:=ComboBox1;

  ChannelInfo[1].Edit:=Edit2;
  ChannelInfo[1].Enabled:=CheckBox2;
  ChannelInfo[1].Color:=Button2;
  ChannelInfo[1].Group:=ComboBox2;

  ChannelInfo[2].Edit:=Edit3;
  ChannelInfo[2].Enabled:=CheckBox3;
  ChannelInfo[2].Color:=Button3;
  ChannelInfo[2].Group:=ComboBox3;

  ChannelInfo[3].Edit:=Edit4;
  ChannelInfo[3].Enabled:=CheckBox4;
  ChannelInfo[3].Color:=Button4;
  ChannelInfo[3].Group:=ComboBox4;

  ChannelInfo[4].Edit:=Edit5;
  ChannelInfo[4].Enabled:=CheckBox5;
  ChannelInfo[4].Color:=Button5;
  ChannelInfo[4].Group:=ComboBox5;

  ChannelInfo[5].Edit:=Edit6;
  ChannelInfo[5].Enabled:=CheckBox6;
  ChannelInfo[5].Color:=Button6;
  ChannelInfo[5].Group:=ComboBox6;

  ChannelInfo[6].Edit:=Edit7;
  ChannelInfo[6].Enabled:=CheckBox7;
  ChannelInfo[6].Color:=Button7;
  ChannelInfo[6].Group:=ComboBox7;

  ChannelInfo[7].Edit:=Edit8;
  ChannelInfo[7].Enabled:=CheckBox8;
  ChannelInfo[7].Color:=Button8;
  ChannelInfo[7].Group:=ComboBox8;

  ChannelInfo[8].Edit:=Edit9;
  ChannelInfo[8].Enabled:=CheckBox9;
  ChannelInfo[8].Color:=Button9;
  ChannelInfo[8].Group:=ComboBox9;

  ChannelInfo[9].Edit:=Edit10;
  ChannelInfo[9].Enabled:=CheckBox10;
  ChannelInfo[9].Color:=Button10;
  ChannelInfo[9].Group:=ComboBox10;

  ChannelInfo[10].Edit:=Edit11;
  ChannelInfo[10].Enabled:=CheckBox11;
  ChannelInfo[10].Color:=Button11;
  ChannelInfo[10].Group:=ComboBox11;

  ChannelInfo[11].Edit:=Edit12;
  ChannelInfo[11].Enabled:=CheckBox12;
  ChannelInfo[11].Color:=Button12;
  ChannelInfo[11].Group:=ComboBox12;

  ChannelInfo[12].Edit:=Edit13;
  ChannelInfo[12].Enabled:=CheckBox13;
  ChannelInfo[12].Color:=Button13;
  ChannelInfo[12].Group:=ComboBox13;

  ChannelInfo[13].Edit:=Edit14;
  ChannelInfo[13].Enabled:=CheckBox14;
  ChannelInfo[13].Color:=Button14;
  ChannelInfo[13].Group:=ComboBox14;

  ChannelInfo[14].Edit:=Edit15;
  ChannelInfo[14].Enabled:=CheckBox15;
  ChannelInfo[14].Color:=Button15;
  ChannelInfo[14].Group:=ComboBox15;

  ChannelInfo[15].Edit:=Edit16;
  ChannelInfo[15].Enabled:=CheckBox16;
  ChannelInfo[15].Color:=Button16;
  ChannelInfo[15].Group:=ComboBox16;

  ChannelInfo[16].Edit:=Edit17;
  ChannelInfo[16].Enabled:=CheckBox17;
  ChannelInfo[16].Color:=Button17;
  ChannelInfo[16].Group:=ComboBox17;

  ChannelInfo[17].Edit:=Edit18;
  ChannelInfo[17].Enabled:=CheckBox18;
  ChannelInfo[17].Color:=Button18;
  ChannelInfo[17].Group:=ComboBox18;

  ChannelInfo[18].Edit:=Edit19;
  ChannelInfo[18].Enabled:=CheckBox19;
  ChannelInfo[18].Color:=Button19;
  ChannelInfo[18].Group:=ComboBox19;

  ChannelInfo[19].Edit:=Edit20;
  ChannelInfo[19].Enabled:=CheckBox20;
  ChannelInfo[19].Color:=Button20;
  ChannelInfo[19].Group:=ComboBox20;

  ChannelInfo[20].Edit:=Edit21;
  ChannelInfo[20].Enabled:=CheckBox21;
  ChannelInfo[20].Color:=Button21;
  ChannelInfo[20].Group:=ComboBox21;

  ChannelInfo[21].Edit:=Edit22;
  ChannelInfo[21].Enabled:=CheckBox22;
  ChannelInfo[21].Color:=Button22;
  ChannelInfo[21].Group:=ComboBox22;

  ChannelInfo[22].Edit:=Edit23;
  ChannelInfo[22].Enabled:=CheckBox23;
  ChannelInfo[22].Color:=Button23;
  ChannelInfo[22].Group:=ComboBox23;

  ChannelInfo[23].Edit:=Edit24;
  ChannelInfo[23].Enabled:=CheckBox24;
  ChannelInfo[23].Color:=Button24;
  ChannelInfo[23].Group:=ComboBox24;

  ChannelInfo[24].Edit:=Edit25;
  ChannelInfo[24].Enabled:=CheckBox25;
  ChannelInfo[24].Color:=Button25;
  ChannelInfo[24].Group:=ComboBox25;

  ChannelInfo[25].Edit:=Edit26;
  ChannelInfo[25].Enabled:=CheckBox26;
  ChannelInfo[25].Color:=Button26;
  ChannelInfo[25].Group:=ComboBox26;

  ChannelInfo[26].Edit:=Edit27;
  ChannelInfo[26].Enabled:=CheckBox27;
  ChannelInfo[26].Color:=Button27;
  ChannelInfo[26].Group:=ComboBox27;

  ChannelInfo[27].Edit:=Edit28;
  ChannelInfo[27].Enabled:=CheckBox28;
  ChannelInfo[27].Color:=Button28;
  ChannelInfo[27].Group:=ComboBox28;

  ChannelInfo[28].Edit:=Edit29;
  ChannelInfo[28].Enabled:=CheckBox29;
  ChannelInfo[28].Color:=Button29;
  ChannelInfo[28].Group:=ComboBox29;

  ChannelInfo[29].Edit:=Edit30;
  ChannelInfo[29].Enabled:=CheckBox30;
  ChannelInfo[29].Color:=Button30;
  ChannelInfo[29].Group:=ComboBox30;

  ChannelInfo[30].Edit:=Edit31;
  ChannelInfo[30].Enabled:=CheckBox31;
  ChannelInfo[30].Color:=Button31;
  ChannelInfo[30].Group:=ComboBox31;

  ChannelInfo[31].Edit:=Edit32;
  ChannelInfo[31].Enabled:=CheckBox32;
  ChannelInfo[31].Color:=Button32;
  ChannelInfo[31].Group:=ComboBox32;

  for i:=0 to MaxChannels-1 do
    with ChannelInfo[i] do begin
      Edit.Text:='channel';
      Edit.Enabled:=true;
      Enabled.Enabled:=true;
      Enabled.Checked:=i<EnChannels;
      Edit.Font.Color:= DefaultSigColor;
      Color.Enabled:=true;
      Group.ItemIndex:=0;
      Group.Enabled:=true;
    end;

  FreeList:=lbSigWeights.Items;

  cbGroupRadix.ItemIndex:=3;
  FEnabledChannels := MaxChannels;
end;

procedure TfrmChannel.FormActivate(Sender: TObject);
begin
   // update base selector for currently selected group
   // (base can changed externally and it would not show up)
   if lbGroups.ItemIndex > -1 then
      cbGroupRadix.ItemIndex:=(lbGroups.Items.Objects[lbGroups.ItemIndex] as TGroupList).Base;
end;

procedure TfrmChannel.FormDestroy(Sender: TObject);
begin
  INIFile.WriteInteger('GUI','SIGNAL_COLOR', DefaultSigColor);
end;


//==============================================================================
//  Operations with signals
//==============================================================================

// change number of channels for use
procedure TfrmChannel.SetEnabledChannels(num: byte; force: boolean);
var i: integer;
begin
  if (num <> FEnabledChannels) or force then
   begin
     for i:=0 to MaxChannels-1 do
       with ChannelInfo[i] do
        begin
          Edit.Enabled:=i<num;
          Enabled.Enabled:=i<num;
          Color.Enabled:=i<num;
          Group.Enabled:=i<num;
          if i>=num then
           begin
             Group.ItemIndex:=0;
             if force then
                ComboBox1Change(ChannelInfo[i].Group);	// force change (OnChange event is not fired when loading layout)
           end;
        end;
     FEnabledChannels := num;
   end;
end;


// signal color selection
procedure TfrmChannel.Button1Click(Sender: TObject);
var i:integer;
begin
  i:=0;
  repeat
    if ChannelInfo[i].Color=Sender then
       break;
    inc(i);
  until i=32;

  if i=32 then
     exit;

  ColorDialog1.Color:=ChannelInfo[i].Edit.Font.Color;
  if ColorDialog1.Execute then
    ChannelInfo[i].Edit.Font.Color:=ColorDialog1.Color;
end;


// signal group change
procedure TfrmChannel.ComboBox1Change(Sender: TObject);
var i,j,k:integer;
    t:string;
begin
  i:=0;
  repeat
    if ChannelInfo[i].Group=Sender then
       break;
    inc(i);
  until i=32;

  if i=32 then
    exit; // group not found

  // delete current group
  for j:=0 to lbGroups.Items.Count-1 do
   begin
     k:=(lbGroups.Items.Objects[j] as TGroupList).IndexOfObject(Sender);
     if k>=0 then
       (lbGroups.Items.Objects[j] as TGroupList).Delete(k);
   end;

  // add to new group
  if (Sender as TComboBox).ItemIndex>0 then
   begin
     k:=lbGroups.Items.IndexOf(
       (Sender as TComboBox).Items.Strings[(Sender as TComboBox).ItemIndex]);
     if k<0 then halt; // group not found
     (lbGroups.Items.Objects[k] as TGroupList).AddObject(IntToStr(i+1)+'. channel',Sender);
   end;

  t:=Copy(GroupBox1.Caption,9,Length(GroupBox1.Caption)-9);
  k:=lbGroups.Items.IndexOf(t);
  if k<0 then
    if lbGroups.Items.Count>0 then
      k:=0
    else exit;

  GroupBox1.Caption:=' Group: '+lbGroups.Items.Strings[k]+' ';
  // doplnit ostatni parametry (barvu apod.)
  lbSigWeights.Items:=(lbGroups.Items.Objects[k] as TGroupList);
end;


//==============================================================================
//  Operations with groups
//==============================================================================

constructor TGroupList.Create;
begin
  inherited Create;
  Base:=3; // hexadecimal
end;


procedure TfrmChannel.btnNewGroupClick(Sender: TObject);
var s:string;
    i:integer;
    GroupList:TGroupList;
begin
  frmGroup.Caption:='New group';
  frmGroup.Edit1.Text:='';
  if frmGroup.ShowModal=mrOk then begin
    s:=frmGroup.Edit1.Text;
    if (s='') then begin
      Application.MessageBox('Cannot create group without name. Please type some name.',
        'Error',mb_IconError);
      exit;
    end;
    if lbGroups.Items.IndexOf(s)>=0 then begin
      Application.MessageBox('Cannot create two groups with the same name. Please type new name of a group.',
        'Error',mb_IconError);
      exit;
    end;
    GroupList:=TGroupList.Create; // vytvor prazdny seznam spoju
    lbGroups.Items.AddObject(frmGroup.Edit1.Text,GroupList); // a pridej nove jmeno a seznam do databaze
    // pridej skupinu do seznamu skupin
    for i:=0 to MaxChannels-1 do
      ChannelInfo[i].Group.Items.Add(frmGroup.Edit1.Text);
  end;
end;

procedure TfrmChannel.btnRemoveGroupClick(Sender: TObject);
var S:string;
    i:integer;
    O:TObject;
begin
  if lbGroups.ItemIndex<0 then
    if lbGroups.Items.Count>0 then
      lbGroups.ItemIndex:=0
    else begin
      Beep;
      exit;
    end;

  s:='Do you wish to remove the group "'+lbGroups.Items.Strings[lbGroups.ItemIndex]+'"?';
  if Application.MessageBox(PChar(s),'Remove group',mb_IconQuestion or mb_YesNo)=mrYes then begin
    // remove group from channel list
    for i:=0 to MaxChannels-1 do begin
      with ChannelInfo[i].Group.Items do begin
        O:=Objects[IndexOf(lbGroups.Items.Strings[lbGroups.ItemIndex])];
        O.Free;
        Delete(IndexOf(lbGroups.Items.Strings[lbGroups.ItemIndex]));
      end;
      if ChannelInfo[i].Group.ItemIndex<0 then
        ChannelInfo[i].Group.ItemIndex:=0;
    end;

    // remove group from group list
    if GroupBox1.Caption=' Group: '+lbGroups.Items.Strings[lbGroups.ItemIndex]+' ' then begin
      lbGroups.Items.Delete(lbGroups.ItemIndex);
      // nutno zrusit skupinu
      if lbGroups.Items.Count>0 then
       begin
         GroupBox1.Caption:=' Group: '+lbGroups.Items.Strings[0]+' ';
         lbSigWeights.Items:=lbGroups.Items.Objects[0] as TGroupList;
       end
      else
       begin
         GroupBox1.Caption:=' Group: ';
         lbSigWeights.Items:=FreeList;
       end;
      exit;
    end;
  end;
end;

procedure TfrmChannel.btnRenameGroupClick(Sender: TObject);
var s,s2:string;
    i,j:integer;
begin
  if lbGroups.ItemIndex<0 then
    if lbGroups.Items.Count>0 then
      lbGroups.ItemIndex:=0
    else begin
      Beep;
      exit;
    end;

  frmGroup.Caption:='Rename group';
  frmGroup.Edit1.Text:=lbGroups.Items.Strings[lbGroups.ItemIndex];
  if frmGroup.ShowModal=mrOk then begin
    s:=frmGroup.Edit1.Text;
    if s='' then begin
      Application.MessageBox('Cannot rename group name to empty. Please type some name.',
        'Error',mb_IconError);
      exit;
    end;

    i:=lbGroups.Items.IndexOf(s);
    if (i=lbGroups.ItemIndex) or (i<0) then begin
      s2:=lbGroups.Items.Strings[lbGroups.ItemIndex];
      for i:=0 to MaxChannels-1 do
        with ChannelInfo[i] do begin
          j:=Group.ItemIndex;
          Group.Items.Strings[Group.Items.IndexOf(s2)]:=s;
          Group.ItemIndex:=j;
        end;
      lbGroups.Items.Strings[lbGroups.ItemIndex]:=s;
    end else
      Application.MessageBox('Cannot rename group, the name you typed is already in use.Please type another name of the group.',
        'Error',mb_IconError);
  end;
end;

procedure TfrmChannel.lbGroupsClick(Sender: TObject);
var s:string;
    k:integer;
begin
  s:=Copy(GroupBox1.Caption,9,Length(GroupBox1.Caption)-9);
  k:=lbGroups.Items.IndexOf(s);
  if k>-1 then begin // je z ceho updatovat
    (lbGroups.Items.Objects[k] as TGroupList).Clear;
    (lbGroups.Items.Objects[k] as TGroupList).AddStrings(lbSigWeights.Items as TStrings);
    (lbGroups.Items.Objects[k] as TGroupList).Base:=cbGroupRadix.ItemIndex;
  end;
  GroupBox1.Caption:=' Group: '+lbGroups.Items.Strings[lbGroups.ItemIndex]+' ';
  lbSigWeights.Items:=(lbGroups.Items.Objects[lbGroups.ItemIndex] as TGroupList);
  cbGroupRadix.ItemIndex:=(lbGroups.Items.Objects[lbGroups.ItemIndex] as TGroupList).Base;
end;

procedure TfrmChannel.btnMoveGroupTopClick(Sender: TObject);
begin
  if (lbGroups.Items.Count=0) or (lbGroups.ItemIndex<0) then begin
    Beep;
    exit;
  end;
  lbGroups.Items.Move(lbGroups.ItemIndex,0);
  lbGroups.ItemIndex:=0;
end;

procedure TfrmChannel.btnMoveGroupUpClick(Sender: TObject);
var i:integer;
begin
  if (lbGroups.Items.Count=0) or (lbGroups.ItemIndex<1) then begin
    Beep;
    exit;
  end;
  i:=lbGroups.ItemIndex;
  lbGroups.Items.Move(i,i-1);
  lbGroups.ItemIndex:=i-1;
end;

procedure TfrmChannel.btnMoveGroupDownClick(Sender: TObject);
var i:integer;
begin
  if (lbGroups.Items.Count=0) or (lbGroups.ItemIndex<0) or (lbGroups.ItemIndex=lbGroups.Items.Count-1) then begin
    Beep;
    exit;
  end;
  i:=lbGroups.ItemIndex;
  lbGroups.Items.Move(i,i+1);
  lbGroups.ItemIndex:=i+1;
end;

procedure TfrmChannel.btnMoveGroupBottomClick(Sender: TObject);
begin
  if (lbGroups.Items.Count=0) or (lbGroups.ItemIndex<0) then begin
    Beep;
    exit;
  end;
  lbGroups.Items.Move(lbGroups.ItemIndex,lbGroups.Items.Count-1);
  lbGroups.ItemIndex:=lbGroups.Items.Count-1;
end;


//==============================================================================
//  Operations with signals in group
//==============================================================================


procedure TfrmChannel.btnMoveSignalTopClick(Sender: TObject);
begin
  if (lbSigWeights.Items.Count=0) or (lbSigWeights.ItemIndex<0) then begin
    Beep;
    exit;
  end;
  lbSigWeights.Items.Move(lbSigWeights.ItemIndex,0);
  lbSigWeights.ItemIndex:=0;
end;

procedure TfrmChannel.btnMoveSignalBottomClick(Sender: TObject);
begin
  if (lbSigWeights.Items.Count=0) or (lbSigWeights.ItemIndex<0) then begin
    Beep;
    exit;
  end;
  lbSigWeights.Items.Move(lbSigWeights.ItemIndex,lbSigWeights.Items.Count-1);
  lbSigWeights.ItemIndex:=lbSigWeights.Items.Count-1;
end;

procedure TfrmChannel.btnMoveSignalUpClick(Sender: TObject);
var i:integer;
begin
  if (lbSigWeights.Items.Count=0) or (lbSigWeights.ItemIndex<1) then begin
    Beep;
    exit;
  end;
  i:=lbSigWeights.ItemIndex;
  lbSigWeights.Items.Move(i,i-1);
  lbSigWeights.ItemIndex:=i-1;
end;

procedure TfrmChannel.btnMoveSignalDownClick(Sender: TObject);
var i:integer;
begin
  if (lbSigWeights.Items.Count=0) or (lbSigWeights.ItemIndex<0) or (lbSigWeights.ItemIndex=lbSigWeights.Items.Count-1) then begin
    Beep;
    exit;
  end;
  i:=lbSigWeights.ItemIndex;
  lbSigWeights.Items.Move(i,i+1);
  lbSigWeights.ItemIndex:=i+1;
end;

//==============================================================================
//  Load/Save layout
//==============================================================================

type TLaySig=array[0..6] of char;

const LayoutSig:TLaySig='LASTML'#0;

function TfrmChannel.SaveLayout;
var F:TFileStream;
    i,j:integer;
    s:ShortString;
    b:boolean;
    c:TColor;
begin
  Result:=0;
  F:=TFileStream.Create(FileName,fmCreate);
  F.Write(LayoutSig,SizeOf(LayoutSig)); 		// zapis signaturu
  i:=lbGroups.Items.Count;
  F.Write(i,SizeOf(i)); 				// zapis pocet skupin
  for i:=0 to lbGroups.Items.Count-1 do begin
    s:=lbGroups.Items.Strings[i];
    F.Write(s,SizeOf(s)); 				// ulozime nazev skupiny
    with (lbGroups.Items.Objects[i] as TGroupList) do begin
      F.Write(Base,SizeOf(Base)); 			// ulozime zaklad zobrazeni skupiny
      j:=Count;
      F.Write(j,SizeOf(j)); 				// ulozime pocet signalu ve skupine
      for j:=0 to Count-1 do begin
        s:=Strings[j];
        F.Write(s,SizeOf(s)); 				// ulozime jejich nazvy (odpovidaji cislum signalu)
      end;
    end;
  end;
  
  for i:=0 to MaxChannels-1 do begin
    s:=ChannelInfo[i].Edit.Text;
    F.Write(s,SizeOf(s));
    b:=ChannelInfo[i].Enabled.Checked;
    F.Write(b,SizeOf(b));
    c:=ChannelInfo[i].Edit.Font.Color;
    F.Write(c,SizeOf(c));
  end;
  F.Free;
end;

function TfrmChannel.LoadLayout;
var F:TFileStream;
    Sig:TLaySig;
    i,j,k,l,m:integer;
    s:ShortString;
    GroupList:TGroupList;
    b:boolean;
    c:TColor;
begin
  Result:=0;
  try
    F:=TFileStream.Create(FileName,fmOpenRead);
  except
    Result:=-1;
    try
      F.Free;
    except
    end;
    exit;
  end;
  F.Read(Sig,SizeOf(Sig));
  if Sig<>LayoutSig then begin
    Result:=-2;
    F.Free;
    exit;
  end;
  lbSigWeights.Items:=FreeList; 			// odstranime vazby
  lbGroups.Clear;
  for i:=0 to MaxChannels-1 do begin
    ChannelInfo[i].Group.Clear;
    ChannelInfo[i].Group.Items.Add('<none>');
    ChannelInfo[i].Group.ItemIndex:=0;
  end;
  GroupBox1.Caption:=' Group: ';
  F.Read(k,SizeOf(k)); 					// precti pocet skupin
  for i:=0 to k-1 do begin
    F.Read(s,SizeOf(s)); 				// precteme nazev skupiny a zalozime ji
    GroupList:=TGroupList.Create; 			// vytvor prazdny seznam spoju
    lbGroups.Items.AddObject(s,GroupList); 		// a pridej nove jmeno a seznam do databaze
    // pridej skupinu do seznamu skupin
    for j:=0 to MaxChannels-1 do
      ChannelInfo[j].Group.Items.Add(s);
    F.Read(GroupList.Base,SizeOf(GroupList.Base)); 	// nahrajeme bazi skupiny
    F.Read(l,SizeOf(l)); 				// nacti jednotlive prvky
    for j:=0 to l-1 do begin
      F.Read(s,SizeOf(s)); 				// precti jmeno kanalu
      m:=StrToInt(Copy(s,1,Pos('.',s)-1))-1;
      GroupList.AddObject(s,ChannelInfo[m].Group); 	// zarad ho
      ChannelInfo[m].Group.ItemIndex:=i+1; 		// a pridel mu polozku
    end;
  end;
  if lbGroups.Items.Count>0 then begin
    lbGroups.ItemIndex:=0;
    lbGroupsClick(nil);
  end;
  for i:=0 to MaxChannels-1 do begin
    F.Read(s,SizeOf(s));
    ChannelInfo[i].Edit.Text:=s;
    F.Read(b,SizeOf(b));
    ChannelInfo[i].Enabled.Checked:=b;
    F.Read(c,SizeOf(c));
    ChannelInfo[i].Edit.Font.Color:=c;
  end;
  F.Free;

  SetEnabledChannels(FEnabledChannels, true);
  btnOKClick(self);
end;


//==============================================================================
//  Misc operations
//==============================================================================


procedure TfrmChannel.btnOKClick(Sender: TObject);
var s:string;
    i,j,k:integer;
    ND,Root,RootNA,RootGE:TTreeNode;
    Cnt:integer;
begin
  s:=Copy(GroupBox1.Caption,9,Length(GroupBox1.Caption)-9);
  k:=lbGroups.Items.IndexOf(s);
  if k>-1 then
   begin // je z ceho updatovat
     (lbGroups.Items.Objects[k] as TGroupList).Clear;
     (lbGroups.Items.Objects[k] as TGroupList).AddStrings(lbSigWeights.Items as TStrings);
     (lbGroups.Items.Objects[k] as TGroupList).Base:=cbGroupRadix.ItemIndex;
   end;

  // update treeview and stringgrid
  with frmMain do begin
    TreeView1.Visible:=false;
    TreeView1.Items.Clear;
    Root:=TreeView1.Items.Add(nil,'Active signals & groups');
    RootNA:=TreeView1.Items.Add(nil,'Disabled signals');
    RootGE:=TreeView1.Items.Add(nil,'Empty Defined Groups');
    Cnt:=0;

    for i:=0 to frmChannel.lbGroups.Items.Count-1 do // zarad signaly do skupin
      with (frmChannel.lbGroups.Items.Objects[i] as TGroupList) do
        if Count>0 then begin
          ND:=TreeView1.Items.AddChild(Root,frmChannel.lbGroups.Items.Strings[i]);
          for j:=0 to Count-1 do begin
            s:=ChannelInfo[StrToInt(Copy(Strings[j],1,Pos('.',Strings[j])-1))-1].Edit.Text;
            if (Count>1) and (j=0) then
              TreeView1.Items.AddChild(ND,Copy(Strings[j],1,Pos('.',Strings[j])-1)+'. '+s+' (LSB)')
            else if (Count>1) and (j=Count-1) then
              TreeView1.Items.AddChild(ND,Copy(Strings[j],1,Pos('.',Strings[j])-1)+'. '+s+' (MSB)')
            else
              TreeView1.Items.AddChild(ND,Copy(Strings[j],1,Pos('.',Strings[j])-1)+'. '+s);
	  end;
          sgSigNames.Cells[0,Cnt]:=frmChannel.lbGroups.Items.Strings[i];
          inc(Cnt);
        end else
          TreeView1.Items.AddChild(RootGE,frmChannel.lbGroups.Items.Strings[i]);

    for i:=0 to MaxChannels-1 do // najdi neprirazene signaly
      with frmChannel.ChannelInfo[i] do
        if (Group.ItemIndex=0) then
          if Enabled.Checked and Enabled.Enabled then begin
            TreeView1.Items.AddChild(Root,IntToStr(i+1)+'. '+Edit.Text);
            sgSigNames.Cells[0,Cnt]:=IntToStr(i+1)+'. '+Edit.Text;
            inc(Cnt);
          end else
            TreeView1.Items.AddChild(RootNA,IntToStr(i+1)+'. '+Edit.Text);

    sgSigNames.RowCount:=Cnt;
    sgSigValues.RowCount:=Cnt;
    TreeView1.Visible:=true;
  end;

end;





end.
