unit fmuPrint;

////////////////////////////////////////////////////////////////////////////////////////////////////
//   ,                                                       //
////////////////////////////////////////////////////////////////////////////////////////////////////

interface

uses
  // VCL
  Windows, Messages, SysUtils, Classes, Graphics, Forms, ComObj,
  StdCtrls, Controls, Dialogs, ComCtrls, ExtCtrls, ActiveX, ToolWin,
  // This
  fmuStatus,
  untUtil,
  untType,
  xObj;

type
  TTaskGroupBox = class;

  { TfmPrint }

  TfmPrint = class(TForm)
    pnlMain: TPanel;
    Shape1: TShape;
    lblResultCode: TLabel;
    lblResultDescription: TLabel;
    Panel3: TPanel;
    Panel1: TPanel;
    pnlButtons: TPanel;
    pnlDescription: TPanel;
    edtResultCode: TEdit;
    edtResultDescription: TEdit;
    pnlDeviceEnabled: TPanel;
    btnShowProperties: TButton;
    btnClose: TButton;
    chbDeviceEnabled: TCheckBox;
    pnlPrint: TPanel;
    pnlMainClient: TPanel;
    pnlTaskConfig: TPanel;
    lblRepeatCount: TLabel;
    edtCopies: TEdit;
    pnlTaskConfigCaption: TPanel;
    pnlPrintConfigCaption: TPanel;
    pnlPrintConfig: TPanel;
    chbWaitAck: TCheckBox;
    chbBackground: TCheckBox;
    chbShowProgress: TCheckBox;
    pnlServerState: TPanel;
    chbUpdateServerState: TCheckBox;
    edtServerState: TEdit;
    pnlServerStateCaption: TPanel;
    pnlPrintStatus: TPanel;
    pnlTask: TPanel;
    lblTaskList: TLabel;
    Bevel2: TBevel;
    cboTaskList: TComboBox;
    btnCancelTask: TButton;
    pnlResumePrint: TPanel;
    Bevel1: TBevel;
    btnResume: TButton;
    btnSuspend: TButton;
    btnPrintState: TButton;
    Timer: TTimer;
    pnlConnection: TPanel;
    btnPrint: TButton;
    btnTerminateWaiting: TButton;
    btnCheckServerState: TButton;
    chbUpdatePrinterSettings: TCheckBox;
    chbProgressButtonsVisible: TCheckBox;
    procedure TimerTimer(Sender: TObject);
    procedure btnCloseClick(Sender: TObject);
    procedure chbUpdateServerStateClick(Sender: TObject);
    procedure EditorClick(Sender: TObject);
    procedure EditorChange(Sender: TObject);
    procedure EditorExit(Sender: TObject);
    procedure EditorKeyPress(Sender: TObject; var Key: Char);
    procedure udEditorClick(Sender: TObject; Button: TUDBtnType);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormShow(Sender: TObject);
  private // Drivers
    fDriver: TObjX;
    function DriverException(E: Exception): Boolean;
    property Driver: TObjX read fDriver;
  private // Values
    fShowMessage: Boolean;
    fWaiting: Boolean;
    function ChangePropertyValue(Sender: TObject): Boolean;
    procedure PerformMethodValue(Sender: TObject);
    procedure UpdateControls;
    function  IsEditorControl(Value: TControl): Boolean;
  private // Utils
    fSaveTimerEnabled: Boolean;
    fTaskGroupBox: TTaskGroupBox;
    procedure UpdateControls_TaskList;
    procedure Init(ADriver: TObjX; AShowMessage: Boolean; AFont: TFont);
    procedure PerformEnableControls(Value: Boolean);
    procedure DisableControls;
    procedure EnableControls;
  private // Update object
    procedure UpdateObject_Copies;
    procedure UpdateObject_DeviceEnabled;
    procedure UpdateObject_WaitAck;
    procedure UpdateObject_Background;
    procedure UpdateObject_ShowProgress;
    procedure UpdateObject_ProgressButtonsVisible;
    procedure UpdateObject_UpdatePrinterSettings;
   // procedure Perform_UpdateServerState;
    procedure Perform_ShowSpooler;
    procedure Perfrom_ShowProperties;
    procedure Perform_PrintTask;
    procedure Perform_CancelTask;
    procedure Perform_Suspend;
    procedure Perform_Resume;
    procedure Perform_TerminateWaiting;
    procedure Perform_CheckServerState;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

  { TTaskGroupBox -      }

  TTaskGroupBox = class
  private
    fComboBox: TComboBox;
    property ComboBox: TComboBox read fComboBox;
    function IsValidItemIndex: Boolean;
    function GetCurrentTaskID: Integer;
  public
    constructor Create(AComboBox: TComboBox);
    procedure AddTask(ATaskID: Integer; ATaskNumber: Integer; const ATaskName: String);
    procedure DeleteTaskByIndex(Index: Integer);
    procedure DeleteCurrent;
    property hasCurrentTask: Boolean read IsValidItemIndex;
    property CurrentTaskID: Integer read GetCurrentTaskID;
  end;

procedure ExecutePrintDialog(ADriver: TObjX; AShowMessage: Boolean; Font: TFont);

implementation

const
  PROPERTY_EDIT_TAG = 12345;

{$R *.DFM}

var
  fmPrint: TfmPrint = nil;

procedure ExecutePrintDialog(ADriver: TObjX; AShowMessage: Boolean; Font: TFont);
begin
  if fmPrint = nil then
  begin
    fmPrint := TfmPrint.Create(nil);
    fmPrint.Init(ADriver, AShowMessage, Font);
    fmPrint.ShowModal;
  end
  else
  begin
    fmPrint.Init(ADriver, AShowMessage, Font);
    fmPrint.ShowModal;
    //ShowWindow(fmPrint.Handle, SW_RESTORE);
  end;
end;

(**********************************      ************************************)

{ TTaskGroupBox }

procedure TTaskGroupBox.AddTask(
  ATaskID: Integer;
  ATaskNumber: Integer;
  const ATaskName: String);
begin
  with ComboBox do
    ItemIndex := Items.AddObject(
      Format('(%d) %s', [ATaskNumber, ATaskName]),
      TObject(ATaskID));
end;

constructor TTaskGroupBox.Create(AComboBox: TComboBox);
begin
  inherited Create;
  fComboBox := AComboBox;
end;

procedure TTaskGroupBox.DeleteCurrent;
begin
  DeleteTaskByIndex(ComboBox.ItemIndex);
end;

procedure TTaskGroupBox.DeleteTaskByIndex(Index: Integer);

  procedure AlignItemIndex;
  begin
    with ComboBox do
    begin
      //if ItemIndex >= Items.Count then ItemIndex := Items.Count - 1;  +++ Marat
      ItemIndex := Items.Count - 1;
      if ItemIndex < 0 then ItemIndex := 0;
    end;
  end;

begin
  ComboBox.Items.Delete(Index);
  AlignItemIndex;
end;

function TTaskGroupBox.GetCurrentTaskID: Integer;
begin
  if IsValidItemIndex then
  begin
    with ComboBox do
      Result := Integer(Items.Objects[ItemIndex]);
  end
  else
    Result := -1;
end;

function TTaskGroupBox.IsValidItemIndex: Boolean;
begin
  with ComboBox do
    Result := (0 <= ItemIndex) and (ItemIndex < Items.Count);
end;

(************************************    *********************************************)

{ TfmPrint }

constructor TfmPrint.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  SendMessage(cboTaskList.Handle, CB_SETDROPPEDWIDTH , 150, 0);
  fTaskGroupBox := TTaskGroupBox.Create(cboTaskList);
end;

destructor TfmPrint.Destroy;
begin
  fTaskGroupBox.Free;
  fTaskGroupBox := nil;
  fDriver := nil;
  inherited Destroy;
end;

procedure TfmPrint.Init(ADriver: TobjX; AShowMessage: Boolean; AFont: TFont);
begin
  fShowMessage := AShowMessage;
  fDriver := ADriver;
  Font := AFont;
  UpdateControls;
end;

procedure TfmPrint.DisableControls;
begin
  btnClose.Enabled := False;
  PerformEnableControls(False);
  fSaveTimerEnabled := Timer.Enabled;
  Timer.Enabled := False;
end;

procedure TfmPrint.EnableControls;
begin
  btnClose.Enabled := True;
  Timer.Enabled := fSaveTimerEnabled;
  PerformEnableControls(True);
end;

procedure TfmPrint.PerformEnableControls(Value: Boolean);
begin
  lblResultCode.Enabled := Value;
  edtResultCode.Enabled := Value;
  lblResultDescription.Enabled := Value;
  edtResultDescription.Enabled := Value;
  lblRepeatCount.Enabled := Value;
  edtCopies.Enabled := Value;
  chbWaitAck.Enabled := Value;
  chbBackground.Enabled := Value;
  chbShowProgress.Enabled := Value and chbBackground.Checked;
  chbProgressButtonsVisible.Enabled := Value and chbShowProgress.Enabled and chbShowProgress.Checked;
  edtServerState.Enabled := Value;
  chbUpdateServerState.Enabled := Value;
  btnPrint.Enabled := Value;
  lblTaskList.Enabled := Value;
  cboTaskList.Enabled := Value;
  btnCancelTask.Enabled := Value;
  btnResume.Enabled := Value;
  btnSuspend.Enabled := Value;
  btnPrintState.Enabled := Value;
  chbDeviceEnabled.Enabled := Value;
  btnShowProperties.Enabled := Value;
  btnCheckServerState.Enabled := Value;
  chbUpdatePrinterSettings.Enabled := Value;
end;

procedure TfmPrint.UpdateControls_TaskList;
begin
  with cboTaskList do
  begin
    Enabled := Items.Count > 0;
    btnCancelTask.Enabled := Items.Count > 0;
  end;
end;

(****************************      ********************************)

function TfmPrint.DriverException(E: Exception): Boolean;
begin
  Result := (E is EOleSysError)
    and (ResultFacility(EOleSysError(E).ErrorCode) = FACILITY_ITF);
  if Result then
  begin
    if fShowMessage then
    begin
      with Application do
        MessageBox(PChar(E.Message), PChar(Title), mb_IconStop or mb_Ok);
    end;
  end
  else
  begin
    if E is EConvertError then
    begin
      E.Message := '    .' + #13 +
        ': ' + E.Message;
      Result := not fShowMessage;
    end;
  end;
end;

function TfmPrint.ChangePropertyValue(Sender: TObject): Boolean;
begin
  Result := True;
  try
    try
      if Sender = edtCopies then UpdateObject_Copies
      else if Sender = chbDeviceEnabled then UpdateObject_DeviceEnabled
      else if Sender = chbWaitAck then UpdateObject_WaitAck
      else if Sender = chbBackground then UpdateObject_Background
      else if Sender = chbUpdatePrinterSettings then UpdateObject_UpdatePrinterSettings
      else if Sender = chbProgressButtonsVisible then UpdateObject_ProgressButtonsVisible
      else if Sender = chbShowProgress then UpdateObject_ShowProgress;
    finally
      if Sender is TCustomEdit then TCustomEdit(Sender).Modified := False;
      UpdateControls;
    end;
  except
    on E: Exception do
    begin
      Result := False;
      if (Sender is TWinControl)
         and (TWinControl(Sender).Visible)
         and (TWinControl(Sender).Enabled) then TWinControl(Sender).SetFocus;
      if not DriverException(E) then raise;
    end;
  end;
end;

procedure TfmPrint.PerformMethodValue(Sender: TObject);

   function SavePropertyValues: Boolean;
   var
     I: Integer;
     cmp: TComponent;
   begin
     for I := 0 to ComponentCount - 1 do
     begin
       cmp := Components[I];
       if (cmp is TCustomEdit)
          and IsEditorControl(TCustomEdit(cmp))
          and TCustomEdit(cmp).Modified
           then
           begin
             Result := ChangePropertyValue(cmp);
             Exit;
           end;
     end;
     Result := True;
   end;

begin
  if not SavePropertyValues then Exit;
  try
    try
      if Sender = btnPrintState then Perform_ShowSpooler
      else if Sender = btnPrint then Perform_PrintTask
      else if Sender = btnCancelTask then Perform_CancelTask
      else if Sender = btnSuspend then Perform_Suspend
      else if Sender = btnResume then Perform_Resume
      else if Sender = btnTerminateWaiting then Perform_TerminateWaiting
      else if Sender = btnCheckServerState then Perform_CheckServerState
      else if Sender = btnShowProperties then Perfrom_ShowProperties;
    finally
      UpdateControls;
    end;
   except
    on E: Exception do
    begin
      if (Sender is TWinControl)
         and TWinControl(Sender).Visible
         and (TWinControl(Sender).Enabled) then TWinControl(Sender).SetFocus;
      if not DriverException(E) then raise;
    end;
  end;
end;

procedure TfmPrint.UpdateControls;
var
  V: OleVariant;
begin
  // Update Driver Properties
  V := Driver.ControlInterface;
  SafeSetEdit(edtResultCode, IntToStr(V.ResultCode));
  SafeSetEdit(edtResultDescription, V.ResultDescription);
  SafeSetChecked(chbDeviceEnabled, V.DeviceEnabled);
  SafeSetEdit(edtCopies, IntToStr(V.Copies));
  SafeSetChecked(chbWaitAck, V.WaitPrinterAck);
  SafeSetChecked(chbBackground, V.BackgroundPrint);
  SafeSetChecked(chbUpdatePrinterSettings, V.UpdatePrinterSettings);
  SafeSetChecked(chbShowProgress, V.ShowProgress);
  SafeSetChecked(chbProgressButtonsVisible, not(V.ProgressButtonsVisible));
  edtServerState.Text := Format('%s -> %s - [%s]', [
    PortNumberToStr(V.PortNumber), V.DeviceDescription, V.ServerDescription]);
    
  // Update Coutrols
  UpdateControls_TaskList;
  chbShowProgress.Enabled := not chbBackground.Checked;
  chbProgressButtonsVisible.Enabled := chbShowProgress.Enabled and chbShowProgress.Checked;
end;

function TfmPrint.IsEditorControl(Value: TControl): Boolean;
begin
  Result := (Value <> nil) and (Value.Tag = PROPERTY_EDIT_TAG);
end;

(*************************************    ******************************************)

procedure TfmPrint.UpdateObject_Copies;
begin
  Driver.ControlInterface.Copies := strToInt(edtCopies.Text);
end;

procedure TfmPrint.UpdateObject_DeviceEnabled;
begin
  Driver.ControlInterface.DeviceEnabled := chbDeviceEnabled.Checked;
end;

procedure TfmPrint.UpdateObject_WaitAck;
begin
  Driver.ControlInterface.WaitPrinterAck := chbWaitAck.Checked;
end;

procedure TfmPrint.UpdateObject_Background;
begin
  Driver.ControlInterface.BackgroundPrint := chbBackground.Checked;
end;

procedure TfmPrint.UpdateObject_UpdatePrinterSettings;
begin
  Driver.ControlInterface.UpdatePrinterSettings := chbUpdatePrinterSettings.Checked;
end;

procedure TfmPrint.UpdateObject_ShowProgress;
begin
  Driver.ControlInterface.ShowProgress := chbShowProgress.Checked;
end;

procedure TfmPrint.UpdateObject_ProgressButtonsVisible;
begin
  Driver.ControlInterface.ProgressButtonsVisible := not chbProgressButtonsVisible.Checked;
end;

procedure TfmPrint.Perform_PrintTask;
var
  V: OleVariant;
begin
  //   
  fWaiting := not chbBackground.Checked;
  if fWaiting then
  begin
    DisableControls;
    btnTerminateWaiting.Enabled := True;
    btnTerminateWaiting.SetFocus;
  end;

  //      
  try
    V := Driver.ControlInterface;
    V.PrintTask;
    fTaskGroupBox.AddTask(V.TaskID, V.TaskIDNumber, V.DeviceDescription);
  finally
    if fWaiting then
    begin
      EnableControls;
      btnTerminateWaiting.Enabled := False;
      fWaiting := False;
    end;
    btnPrint.SetFocus;
  end;
end;

procedure TfmPrint.Perform_CancelTask;
begin
  if not fTaskGroupBox.hasCurrentTask then raise Exception.Create('  ');
  try
    Driver.ControlInterface.TaskID := fTaskGroupBox.CurrentTaskID;
    Driver.ControlInterface.CancelTask;
  finally
    fTaskGroupBox.DeleteCurrent;
  end;
end;

procedure TfmPrint.Perform_Suspend;
begin
  Driver.ControlInterface.Suspend;
end;

procedure TfmPrint.Perform_Resume;
begin
  Driver.ControlInterface.Resume;
end;

procedure TfmPrint.Perform_ShowSpooler;
begin
  Driver.ControlInterface.ShowSpooler;
end;

procedure TfmPrint.Perfrom_ShowProperties;
begin
  Driver.ControlInterface.ShowProperties;
end;

procedure TfmPrint.Perform_TerminateWaiting;
begin
  Driver.ControlInterface.TerminateWaiting;
end;

procedure TfmPrint.Perform_CheckServerState;
begin
  Driver.ControlInterface.CheckServerState
end;

(************************************   *****************************************)

procedure TfmPrint.chbUpdateServerStateClick(Sender: TObject);
begin
  Timer.Enabled := chbUpdateServerState.Checked;
end;

procedure TfmPrint.TimerTimer(Sender: TObject);
var
  V: OleVariant;
begin
  //  PerformMethodValue(btnCheckServerState); +++
  try
    V := Driver.ControlInterface;
    try
      V.CheckServerState;
    finally
      SafeSetEdit(edtResultCode, IntToStr(V.ResultCode));
      SafeSetEdit(edtResultDescription, V.ResultDescription);
      SafeSetChecked(chbDeviceEnabled, V.DeviceEnabled);
      edtServerState.Text := Format('%s -> %s - [%s]', [
        PortNumberToStr(V.PortNumber), V.DeviceDescription, V.ServerDescription]);
    end;
  except
    {no exception}
  end;
end;

procedure TfmPrint.EditorClick(Sender: TObject);
begin
  PerformMethodValue(Sender);
end;

procedure TfmPrint.EditorChange(Sender: TObject);
begin
  ChangePropertyValue(Sender);
end;

procedure TfmPrint.EditorExit(Sender: TObject);
begin
  if (Sender is TCustomEdit) and TCustomEdit(Sender).Modified
    then ChangePropertyValue(Sender);
end;

procedure TfmPrint.EditorKeyPress(Sender: TObject; var Key: Char);
begin
  case ord(Key) of
    VK_RETURN: ChangePropertyValue(Sender);
    VK_ESCAPE: UpdateControls;
  end;
end;

procedure TfmPrint.udEditorClick(Sender: TObject; Button: TUDBtnType);
begin
  ChangePropertyValue(Sender);
end;

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

procedure TfmPrint.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Timer.Enabled := False;
end;

procedure TfmPrint.FormShow(Sender: TObject);
begin
  Timer.Enabled := chbUpdateServerState.Checked;
end;

{
procedure TfmPrint.Button1Click(Sender: TObject);
var
  I: Integer;
begin
  Driver.ControlInterface.CheckTaskState;
  I := Driver.ControlInterface.TaskState;
  showMessage(Driver.ControlInterface.TaskDescription)
end;
}
{
procedure TfmPrint.Button1Click(Sender: TObject);
var
  V: OleVariant;
  I: Integer;
begin
  V := Driver.ControlInterface;
  I := V.ActiveStations;
  V.ActiveStations := 0;
  V.ActiveStations := 1;
  I := 0;
end;
}

end.
