unit uDiscoverDifferencesDialog;
{$INCLUDE 'DirSync3.inc'}

interface

uses
  SysUtils, Windows, Classes,
  {$IFDEF FAR3} Plugin3, {$ELSE} PluginW, {$ENDIF} FarKeysW, FarColor,
  uSystem, uFAR, uLog,
  uDirSyncConsts, uMessages, uOptions;

type
  TDiscoverDifferencesDialog = class(TFarDialog)
  private
    fLeftPanel: TFarPanelInfo;
    fRightPanel: TFarPanelInfo;
    fOptions: TDirSyncOptions;
  private
    fCheckProcessSubfolders: integer;
    fCheckUseMaxScanDepth: integer;
    fEditMaxScanDepth: integer;
    fCheckProcessSelected: integer;
    fCheckCompareTime: integer;
    fCheckCompareLowPrecision: integer;
    fCheckIgnoreTimeZone: integer;
    fCheckCompareSize: integer;
    fCheckCompareContents: integer;
    fCheckCompareContentsIgnore: integer;
    fRadioIgnoreNewLines: integer;
    fRadioIgnoreWhiteSpace: integer;
    fCheckSelectOnBothPanels: integer;
    fButtonOK: integer;
    fButtonCancel: integer;
  private
    fMaxScanDepthBuf: TFarCharArray;
  protected
    function DialogProc(Msg, Param1, Param2: TIntPtr; var DlgProcResult: TIntPtr): boolean; override;
  public
    constructor Create;
    destructor Destroy; override;
    procedure ClearDialog; override;
    function Execute: boolean;
    property LeftPanel: TFarPanelInfo read fLeftPanel write fLeftPanel;
    property RightPanel: TFarPanelInfo read fRightPanel write fRightPanel;
    property Options: TDirSyncOptions read fOptions write fOptions;
  end;

implementation

{ TDirSyncMainDialog }

procedure TDiscoverDifferencesDialog.ClearDialog;
begin
  inherited;
  fCheckProcessSubfolders := -1;
  fCheckUseMaxScanDepth := -1;
  fEditMaxScanDepth := -1;
  fCheckProcessSelected := -1;
  fCheckCompareTime := -1;
  fCheckCompareLowPrecision := -1;
  fCheckIgnoreTimeZone := -1;
  fCheckCompareSize := -1;
  fCheckCompareContents := -1;
  fCheckCompareContentsIgnore := -1;
  fRadioIgnoreNewLines := -1;
  fRadioIgnoreWhiteSpace := -1;
  fCheckSelectOnBothPanels := -1;
  fButtonOK := -1;
  fButtonCancel := -1;
  SetLength(fMaxScanDepthBuf, 0);
end;

constructor TDiscoverDifferencesDialog.Create;
begin
  inherited Create( {$IFDEF FAR3_UP} PLUGIN_GUID, DIALOG_MAIN_GUID {$ELSE} FarApi.ModuleNumber {$ENDIF} );
end;

destructor TDiscoverDifferencesDialog.Destroy;
begin
  inherited;
end;

function TDiscoverDifferencesDialog.DialogProc(Msg, Param1, Param2: TIntPtr; var DlgProcResult: TIntPtr): boolean;
var
  SubItemEnabled, SubSubItemEnabled: boolean;
begin
  Result := False;
  case Msg of
    DN_BTNCLICK:
      begin
        if Param1 = fCheckProcessSubfolders then begin
          SubItemEnabled := Param2 <> 0;
          SubSubItemEnabled := SubItemEnabled and ItemChecked[fCheckUseMaxScanDepth];
          ItemEnabled[fCheckUseMaxScanDepth] := SubItemEnabled;
          ItemEnabled[fEditMaxScanDepth] := SubSubItemEnabled;
        end
        else if Param1 = fCheckUseMaxScanDepth then begin
          SubItemEnabled := Param2 <> 0;
          ItemEnabled[fEditMaxScanDepth] := SubItemEnabled;
        end
        else if Param1 = fCheckCompareContents then begin
          SubItemEnabled := Param2 <> 0;
          SubSubItemEnabled := SubItemEnabled and ItemChecked[fCheckCompareContentsIgnore];
          ItemEnabled[fCheckCompareContentsIgnore] := SubItemEnabled;
          ItemEnabled[fRadioIgnoreNewLines] := SubSubItemEnabled;
          ItemEnabled[fRadioIgnoreWhiteSpace] := SubSubItemEnabled;
        end
        else if Param1 = fCheckCompareContentsIgnore then begin
          SubItemEnabled := Param2 <> 0;
          ItemEnabled[fRadioIgnoreNewLines] := SubItemEnabled;
          ItemEnabled[fRadioIgnoreWhiteSpace] := SubItemEnabled;
        end
        else if Param1 = fCheckCompareTime then begin
          SubItemEnabled := Param2 <> 0;
          ItemEnabled[fCheckCompareLowPrecision] := SubItemEnabled;
          ItemEnabled[fCheckIgnoreTimeZone] := SubItemEnabled;
        end;
      end;
  end;
  if not Result then
    Result := inherited DialogProc(Msg, Param1, Param2, DlgProcResult);
end;

function TDiscoverDifferencesDialog.Execute: boolean;
const
  EnabledFlag: array[boolean] of DWORD = (DIF_DISABLE, 0);
  MaxScanDepthMask = '99999';
var
  CanCompareContents, IsCompareContents, IsIgnoringContents: boolean;
  CanProcessSubfolders, IsProcessSubfolders: boolean;
  CanProcessSelected: boolean;
  i: Integer;
  Button: integer;
begin
  Result := False;
  // Initialize runtime variables
  SetLength(fMaxScanDepthBuf, Succ(Length(MaxScanDepthMask)));
  StrPCopy(PChar(fMaxScanDepthBuf), Copy(IntToStr(Options.MaxScanDepth), 1, Length(MaxScanDepthMask)));
  //
  CanProcessSubfolders := (not LeftPanel.IsPluginPanel) and (not RightPanel.IsPluginPanel);
  IsProcessSubfolders := CanProcessSubfolders and Options.ProcessSubfolders;
  CanCompareContents := (not LeftPanel.IsPluginPanel) and (not RightPanel.IsPluginPanel);
  IsCompareContents := CanCompareContents and Options.CompareContents;
  IsIgnoringContents := Options.CompareContentsIgnore;
  CanProcessSelected := LeftPanel.HasSelectedItems or RightPanel.HasSelectedItems;
  // Build the dialog
                                            AddDoubleBox(  3,  1, 62, 20, GetMsg(MTitle), 0);
                                            AddLabel    (  5,  2,         GetMsg(MProcessBox), 0);
  fCheckProcessSubfolders :=                AddCheckbox (  5,  3,         GetMsg(MProcessSubfolders), IsProcessSubfolders, EnabledFlag[CanProcessSubfolders]);
  fCheckUseMaxScanDepth :=                  AddCheckbox (  9,  4,         GetMsg(MUseMaxScanDepth), Options.UseMaxScanDepth, EnabledFlag[IsProcessSubfolders]);
  fEditMaxScanDepth :=                      AddEdit     ( -1,  4,  5,     PFarChar(fMaxScanDepthBuf), MaxScanDepthMask, nil, Length(MaxScanDepthMask), DIF_MASKEDIT or EnabledFlag[IsProcessSubfolders]);
  fCheckProcessSelected :=                  AddCheckbox (  5,  5,         GetMsg(MProcessSelected), CanProcessSelected {and Options.ProcessSelected}, EnabledFlag[CanProcessSelected]);
                                            AddLabel    (  0,  6,         nil, DIF_SEPARATOR);
                                            AddLabel    (  5,  7,         GetMsg(MCompareBox), 0);
  fCheckCompareTime :=                      AddCheckbox (  5,  8,         GetMsg(MCompareTime), Options.CompareTime, 0);
  fCheckCompareLowPrecision :=              AddCheckbox (  9,  9,         GetMsg(MCompareLowPrecision), Options.LowPrecisionTime, EnabledFlag[Options.CompareTime]);
  fCheckIgnoreTimeZone :=                   AddCheckbox (  9, 10,         GetMsg(MCompareIgnoreTimeZone), Options.IgnorePossibleTimeZoneDifferences, EnabledFlag[Options.CompareTime]);
  fCheckCompareSize :=                      AddCheckbox (  5, 11,         GetMsg(MCompareSize), Options.CompareSize, 0);
  fCheckCompareContents :=                  AddCheckbox (  5, 12,         GetMsg(MCompareContents), IsCompareContents, EnabledFlag[CanCompareContents]);
  fCheckCompareContentsIgnore :=            AddCheckbox (  9, 13,         GetMsg(MCompareContentsIgnore), IsIgnoringContents, EnabledFlag[IsCompareContents]);
  fRadioIgnoreNewLines :=                   AddRadio    ( 13, 14,         GetMsg(MCompareIgnoreNewLines), Options.IgnoreNewLines or (not Options.IgnoreWhitespace), DIF_GROUP or EnabledFlag[IsCompareContents and IsIgnoringContents]);
  fRadioIgnoreWhiteSpace :=                 AddRadio    ( 13, 15,         GetMsg(MCompareIgnoreWhitespace), Options.IgnoreWhitespace and (not Options.IgnoreNewLines), EnabledFlag[IsCompareContents and IsIgnoringContents]);
                                            AddLabel    (  0, 16,         nil, DIF_SEPARATOR);
  fCheckSelectOnBothPanels :=               AddCheckbox (  5, 17,         GetMsg(MSelectOnBothPanels), Options.SelectDifferencesOnBothPanels, 0);
                                            AddLabel    (  0, 18,         nil, DIF_SEPARATOR);

  fButtonOK :=                              AddButton   (  0, 19,         GetMsg(MOk), DIF_CENTERGROUP);
  fButtonCancel :=                          AddButton   (  0, 19,         GetMsg(MCancel), DIF_CENTERGROUP);
  // Set focus to the first enabled checkbox
  for i := 0 to Pred(Count) do
    if Items[i].ItemType = DI_CHECKBOX then
      if (Items[i].Flags and DIF_DISABLE) = 0 then begin
        {$IFDEF FAR3_UP}
        Items[i].Flags := Items[i].Flags or DIF_FOCUS;
        {$ELSE}
        Items[i].Focus := 1;
        {$ENDIF}
        Break;
      end;
  // Set the default button
  {$IFDEF FAR3_UP}
  Items[fButtonOK].Flags := Items[fButtonOK].Flags or DIF_DEFAULTBUTTON;
  {$ELSE}
  Items[fButtonOK].DefaultButton := 1;
  {$ENDIF}
  // Show the dialog
  if Build(-1, -1, 66, 22, 0, 'Contents') then begin
    if inherited Execute(Button) then begin
      if Button = fButtonOK then begin
        //Log('OK pressed, reading the settings');
        Options.ProcessSubfolders := ItemChecked[fCheckProcessSubfolders];
        Options.UseMaxScanDepth := ItemChecked[fCheckUseMaxScanDepth];
        Options.MaxScanDepth := StrToIntDef(Trim(ItemText[fEditMaxScanDepth]), Options.MaxScanDepth);
        Options.ProcessSelected := ItemChecked[fCheckProcessSelected];
        Options.CompareTime := ItemChecked[fCheckCompareTime];
        Options.LowPrecisionTime := ItemChecked[fCheckCompareLowPrecision];
        Options.IgnorePossibleTimeZoneDifferences := ItemChecked[fCheckIgnoreTimeZone];
        Options.CompareSize := ItemChecked[fCheckCompareSize];
        Options.CompareContents := ItemChecked[fCheckCompareContents];
        Options.CompareContentsIgnore := ItemChecked[fCheckCompareContentsIgnore];
        Options.IgnoreNewLines := ItemChecked[fRadioIgnoreNewLines];
        Options.IgnoreWhitespace := ItemChecked[fRadioIgnoreWhiteSpace];
        Options.SelectDifferencesOnBothPanels := ItemChecked[fCheckSelectOnBothPanels];
        Result := True;
      end;
    end;
  end;
end;

end.
