unit fmuWindows;

interface

uses
  // VCL
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls, ExtCtrls,
  // This
  cuUtils,
  LineX,
  cuWindows,
  untTypes;

type
  { TfmWindows }

  TfmWindows = class(TForm)
    lvData: TListView;
    Label1: TLabel;
    btnAddWindow: TButton;
    btnDeleteWindow: TButton;
    btnClose: TButton;
    HelpMemo: TMemo;
    Label5: TLabel;
    Label6: TLabel;
    Shape1: TShape;
    edtResultCode: TEdit;
    edtResultDescription: TEdit;
    Bevel1: TBevel;
    btnAddViewPort: TButton;
    btnClearViewPorts: TButton;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label7: TLabel;
    Label8: TLabel;
    Label9: TLabel;
    edtViewPortRow: TEdit;
    edtViewPortColumn: TEdit;
    edtViewPortHeight: TEdit;
    edtViewPortWidth: TEdit;
    edtWindowHeight: TEdit;
    edtWindowWidth: TEdit;
    procedure ControlChanged(Sender: TObject);
    procedure btnCloseClick(Sender: TObject);
  private
    FLine: TLineX;
    fWindowList: TWindowList;
    procedure Init(ALineX: TLineX; AWindowList: TWindowList; AFont: TFont);
    procedure UpdatePage;
    property LineX: TLineX read FLine write FLine;
    property WindowList: TWindowList read fWindowList write fWindowList;
  end;

procedure ShowWindowManager(ALineX: TLineX;
  AWindowList: TWindowList; AFont: TFont);

implementation

{$R *.DFM}

procedure ShowWindowManager(ALineX: TLineX; AWindowList: TWindowList;
  AFont: TFont);
var
  fm: TfmWindows;
begin
  fm := TfmWindows.Create(nil);
  try
    with fm do
    begin
      Init(ALineX, AWindowList, AFont);
      ShowModal;
    end;
  finally
    fm.Free;
  end;
end;

procedure TfmWindows.Init(ALineX: TLineX; AWindowList: TWindowList;
  AFont: TFont);

  function IsEqualColumns: Boolean;
  var
    I: Integer;
    SaveDeviceColumns: Integer;
  begin
    Result := False;
    SaveDeviceColumns := ALineX.GetDeviceColumns(0);
    for I := 1 to ALineX.DeviceRows - 1 do
      if SaveDeviceColumns <> ALineX.GetDeviceColumns(I) then Exit;
    Result := True;
  end;

begin
  FLine := ALineX;
  FWindowList := AWindowList;
  Font := AFont;
  if IsEqualColumns then
    edtViewPortHeight.Text := IntToStr(FLine.DeviceRows)
  else
    edtViewPortHeight.Text := '1';
  edtViewPortWidth.Text := IntToStr(FLine.GetDeviceColumns(0));
  edtWindowHeight.Text := edtViewPortHeight.Text;
  edtWindowWidth.Text := edtViewPortWidth.Text;
  UpdatePage;
end;

procedure TfmWindows.UpdatePage;

  procedure UpdateWindowList;

    procedure AddWindow(const ALineWindow: TLineWindow);
    var
      ListItem: TListItem;
      B: TBounds;
    begin
      ListItem := lvData.Items.Add;
      with ALineWindow do
      begin
        ListItem.Data := ALineWindow;
        ListItem.Caption := Caption;
        B := ALineWindow.ViewPortsBounds;
        ListItem.SubItems.Add(IntToStr(B.Top));
        ListItem.SubItems.Add(IntToStr(B.Left));
        ListItem.SubItems.Add(IntToStr(B.Height));
        ListItem.SubItems.Add(IntToStr(B.Width));
        ListItem.SubItems.Add(IntToStr(Height));
        ListItem.SubItems.Add(IntToStr(Width));
      end;
    end;

  var
    I: Integer;
  begin
    lvData.Items.BeginUpdate;
    try
      lvData.Items.Clear;
      for I := 0 to WindowList.Count - 1 do AddWindow(WindowList[I]);
      lvData.Selected := lvData.Items[LineX.CurrentWindow];
    finally
      lvData.Items.EndUpdate;
    end;
  end;

begin
  edtResultCode.Text := IntToStr(LineX.ResultCode);
  edtResultDescription.Text := LineX.ResultDescription;
  UpdateWindowList;
end;

procedure TfmWindows.ControlChanged(Sender: TObject);

  procedure HandleException(E: Exception);
  begin
    if E is EDisplayError then
      edtResultCode.Text := IntToStr(EDisplayError(E).ErrorCode)
    else
      edtResultCode.Text := '-6';
    edtResultDescription.Text := E.Message;
  end;

  procedure CreateWindow;
  var
    Y, X, VH, VW, WH, WW: Integer;
  begin
    Y := StrToIntRus(edtViewPortRow.Text);
    X := StrToIntRus(edtViewPortColumn.Text);
    VH := StrToIntRus(edtViewPortHeight.Text);
    VW := StrToIntRus(edtViewPortWidth.Text);
    WH := StrToIntRus(edtWindowHeight.Text);
    WW := StrToIntRus(edtWindowWidth.Text);
    FLine.CreateWindow(Y, X, VH, VW, WH, WW);
    TLineWindow.CreateDirect(FWindowList, Y, X, VH, VW, WH, WW);
  end;

  procedure DeleteWindow;
  var
    LineWindow: TLineWindow;
    SelectedItem: TListItem;
  begin
    SelectedItem := lvData.Selected;
    if SelectedItem <> nil then
    begin
      LineWindow := TObject(SelectedItem.Data) as TLineWindow;
      LineX.CurrentWindow := LineWindow.Index;
      LineX.DestroyWindow;
      LineWindow.Free;
      SelectedItem.Delete;
    end;
  end;

  procedure AddViewPort;
  var
    LineWindow: TLineWindow;
    SelectedItem: TListItem;
    B: TBounds;
  begin
    SelectedItem := lvData.Selected;
    if SelectedItem <> nil then
    begin
      LineWindow := TObject(SelectedItem.Data) as TLineWindow;
      LineX.CurrentWindow := LineWindow.Index;
      B := MakeBounds(StrToIntRus(edtViewPortColumn.Text),
        StrToIntRus(edtViewPortRow.Text),
        StrToIntRus(edtViewPortWidth.Text),
        StrToIntRus(edtViewPortHeight.Text));
      LineX.AddViewPort(B.Top, B.Left, B.Height, B.Width);
      LineWindow.AddViewPort(B.Top, B.Left, B.Height, B.Width);  
    end;
  end;

  procedure ClearViewPorts;
  var
    LineWindow: TLineWindow;
    SelectedItem: TListItem;
  begin
    SelectedItem := lvData.Selected;
    if SelectedItem <> nil then
    begin
      LineWindow := TObject(SelectedItem.Data) as TLineWindow;
      LineX.CurrentWindow := LineWindow.Index;
      LineX.ClearViewPorts;
      LineWindow.ClearViewPorts;
    end;
  end;
  
begin
  try
    try
      if Sender = btnAddWindow then CreateWindow
      else if Sender = btnDeleteWindow then DeleteWindow
      else if Sender = btnAddViewPort then AddViewPort
      else if Sender = btnClearViewPorts then ClearViewPorts;
    finally
      UpdatePage;
    end;
  except
    on E: Exception do HandleException(E);
  end;
end;

procedure TfmWindows.btnCloseClick(Sender: TObject);
begin
  Close;
end;

end.
