Resource

Resource Basics

Resource Name Filter by Macro Command
Resource Version 1.0
Category Filter Script
Downloads 695
Release Date 3/6/2025 10:42:29 AM
 

Resource Details

Description This script allows filtering a collection using macro commands.
Installation Instructions n.a.
Usage Instructions Use in Photo Supreme;
1. Open a collection
2. Open the filter bar
3. Click the FILTER button
4. Select From Repository
5. Select Filter By Macro Command
Changes in this version n.a.
Special Requirements
 

Author Information

Author Name IDimager Support
 

Script

const
  cFormWidth  = 450;
  cFormHeight = 230;

var
  FMacro: WideString;
  FContains, FBetween: WideString;
  FCondition: Integer;

  AForm: TvxSceneForm;
  AFormCaption: String;
  AMacroEdit: TvxTextBox; AContainsEdit: TvxTextBox; ABetweenEdit: TvxTextBox;
  ACondition: TvxPopupBox;
  ASample: TvxLabel;


procedure UpdateSampleText;
var
  AItem: TImageItem;
begin
  ASample.Text := '';
  AItem := nil;
  if ActiveCollection <> nil then
  begin
    if ActiveCollection.Items.Count > 0 then
      AItem := ActiveCollection.Items.Items[0];
  end;

  if AItem = nil then exit;

  ASample.Text := AItem.ParseMacros(AMacroEdit.Text, nil);
end;

procedure UpdateContainsEditState;
begin
  AContainsEdit.Visible := (ACondition.ItemIndex <> 7) and   // is blank
                           (ACondition.ItemIndex <> 8);      // is not blank

  ABetweenEdit.Visible := (ACondition.ItemIndex = 6);        // between
end;

procedure _MacroChangeTracking(Sender: TObject);
begin
  ASample.Text := '';
  //UpdateSampleText;
end;

procedure _SampleButtonClick(Sender: TObject);
begin
  UpdateSampleText;
end;

procedure _MacroButtonClick(Sender: TObject);
begin
  MacroValuesPopup.Component := AMacroEdit;
  MacroValuesPopup.Popup(Mouse.CursorPos.X, Mouse.CursorPos.Y);
end;

procedure _SaveClick (Sender: Tobject);
var
  AElem: TidElement;
begin
  SaveDialog.Filter := 'Macro Save Files|*.msf';
  SaveDialog.DefaultExt := '.msf';
  SaveDialog.InitialDir := DefaultAppDataDir + WideIncludeTrailingBackslash('Filters');
  if not SaveDialog.Execute then
    exit;

  AForm.Caption := AFormCaption + ' - ' + UTF8Encode(WideExtractFileName(SaveDialog.FileName));

  AElem := TidElement.Create(nil);
  AElem.Prop['FilterMacro']          := AMacroEdit.Text;
  AElem.Prop['FilterMacroContains']  := AContainsEdit.Text;
  AElem.Prop['FilterMacroBetween']   := ABetweenEdit.Text;
  AElem.Prop['FilterMacroCondition'] := ACondition.ItemIndex;
  AElem.SaveAsXMLFile(SaveDialog.FileName);
  AElem.Free;
end;

procedure _LoadClick (Sender: TObject);
var
  AElem: TidElement;
begin
  OpenDialog.Filter     := 'Macro Save Files|*.msf';
  OpenDialog.DefaultExt := '.msf';
  OpenDialog.InitialDir := DefaultAppDataDir + WideIncludeTrailingBackslash('Filters');
  if not OpenDialog.Execute then
    exit;
  AElem := TidElement.Create(nil);
  AElem.LoadFromXMLFile(OpenDialog.FileName);

  AForm.Caption := AFormCaption + ' - ' + UTF8Encode(WideExtractFileName(OpenDialog.FileName));

  FMacro    := '';
  FMacro    := Nvl(AElem.Prop['FilterMacro'], FMacro);
  FContains := '';
  FContains := Nvl(AElem.Prop['FilterMacroContains'], FContains);
  FBetween  := '';
  FBetween  := Nvl(AElem.Prop['FilterMacroBetween'], FBetween);
  FCondition:= 0;
  FCondition:= Nvl(AElem.Prop['FilterMacroCondition'], FCondition);
  AElem.Free;

  AMacroEdit.Text := FMacro;
  AContainsEdit.Text := FContains;
  ABetweenEdit.Text := FBetween;
  ACondition.ItemIndex := FCondition;
  UpdateContainsEditState;
end;

procedure _CondtionChange(Sender: TObject);
begin
  UpdateContainsEditState;
end;

function BuildForm: TvxSceneForm;
var
  ALabel: TvxLabel;
  AEdit: TvxTextBox;
  ACombo: TvxPopupBox;
  AOk: TvxButton;
  ASave: TvxButton;
  ALoad: TvxButton;
  AMacroButton: TvxButton;
  ASampleButton: TvxButton;
begin
  result := TvxSceneForm.Create(nil);
  result.Caption  := AFormCaption;
  result.Position := poScreenCenter;
  result.Width := Round(cFormWidth * result.DPIFactor);
  result.Height := Round(cFormHeight * result.DPIFactor);

  ALabel := TvxLabel.Create(result.Root);
  result.Root.AddObject(ALabel);
  ALabel.Text := 'Macro Command';
  ALabel.TextAlign := vgTextAlignNear;
  ALabel.Position.Point := vgPoint(20, 20);

  AEdit := TvxTextBox.Create(result.Root);
  result.Root.AddObject(AEdit);
  AEdit.Text := FMacro;
  AEdit.Width := 200;
  AEdit.Position.Point := vgPoint(ALabel.Position.X, ALabel.Position.Y + ALabel.Height + 0);
  AEdit.OnChangeTracking := '_MacroChangeTracking';
  AMacroEdit := AEdit;

  AMacroButton := TvxButton.Create(result.Root);
  result.Root.AddObject(AMacroButton);
  AMacroButton.Position.Point := vgPoint(AEdit.Position.X + AEdit.Width, AEdit.Position.Y);
  AMacroButton.Width  := AEdit.Height;
  AMacroButton.Text   := '...';
  AMacroButton.OnClick:= '_MacroButtonClick';

  ASampleButton := TvxButton.Create(result.Root);
  result.Root.AddObject(ASampleButton);
  ASampleButton.Position.Point := vgPoint(AMacroButton.Position.X + AMacroButton.Width, AMacroButton.Position.Y);
  ASampleButton.Width  := 100;
  ASampleButton.Text   := 'show sample';
  ASampleButton.OnClick:= '_SampleButtonClick';
  if ActiveCollection = nil then
    ASampleButton.Visible := False
  else
    ASampleButton.Visible := ActiveCollection.Items.Count > 0;

  ASample := TvxLabel.Create(result.Root);
  result.Root.AddObject(ASample);
  ASample.Text := '';
  ASample.Font.Style := vgFontItalic;
  ASample.Width := cFormWidth - AEdit.Position.X - 10;
  ASample.Height := ASample.Height * 2;
  ASample.TextAlign := vgTextAlignNear;
  ASample.WordWrap := True;
  ASample.Position.Point := vgPoint(AEdit.Position.X, AEdit.Position.Y + AEdit.Height + 0);

  ACombo := TvxPopupBox.Create(result.Root);
  result.Root.AddObject(ACombo);
  //ACombo.Style := csDropDownList;
  ACombo.Items.Clear;
  ACombo.Items.Add('Contains value');
  ACombo.Items.Add('Doesn''t contain value');
  ACombo.Items.Add('Equals');
  ACombo.Items.Add('Doesn''t Equal');
  ACombo.Items.Add('Less Than');
  ACombo.Items.Add('Greater Than');
  ACombo.Items.Add('Between');
  ACombo.Items.Add('Is Blank');
  ACombo.Items.Add('Is Not  Blank');
  ACombo.ItemIndex := FCondition;
  ACombo.Position.Point := vgPoint(20, ASample.Position.Y + ASample.Height + 10);
  ACombo.Width := 150;
  ACombo.TextAlign := vgTextAlignNear;
  ACombo.OnChange := '_CondtionChange'
  ACondition := ACombo;

  AEdit := TvxTextBox.Create(result.Root);
  result.Root.AddObject(AEdit);
  AEdit.Text := FContains;
  AEdit.Width := 200;
  AEdit.Position.Point := vgPoint(ACombo.Position.X, ACombo.Position.Y + ACombo.Height + 10);
  AContainsEdit := AEdit;

  AEdit := TvxTextBox.Create(result.Root);
  result.Root.AddObject(AEdit);
  AEdit.Text := FBetween;
  AEdit.Width := 200;
  AEdit.Position.Point := vgPoint(AContainsEdit.Position.X + AContainsEdit.Width + 10, ACombo.Position.Y + ACombo.Height + 10);
  ABetweenEdit := AEdit;

  AOk := TvxButton.Create(result.Root);
  result.Root.AddObject(AOk);
  AOk.ModalResult := mrOk;
  AOk.Position.Point := vgPoint(ACombo.Position.X, (result.Height / result.DPIFactor) - 10 - AOk.Height);
  AOk.Text := 'OK';
  AOk.Default := True;

  ASave := TvxButton.Create(result.Root);
  result.Root.AddObject(ASave);
  ASave.OnClick := '_SaveClick';
  ASave.Position.Point := vgPoint((result.Width / result.DPIFactor) - 10 - ASave.Width, (result.Height / result.DPIFactor) - 10 - ASave.Height);
  ASave.Text := 'Save';

  ALoad := TvxButton.Create(result.Root);
  result.Root.AddObject(ALoad);
  ALoad.OnClick := '_LoadClick';
  ALoad.Position.Point := vgPoint(ASave.Position.X - 5 - ALoad.Width, (result.Height / result.DPIFactor) - 10 - ALoad.Height);
  ALoad.Text := 'Load';

  UpdateContainsEditState;
end;

function Initialize: Boolean;
begin
  result := True;

  FHit := 0;
  FMacro    := '';
  FMacro    := ReadFromRegistry ('Scripts', 'FilterMacro', FMacro);
  FContains := '';
  FContains := ReadFromRegistry ('Scripts', 'FilterMacroContains', FContains);
  FBetween  := '';
  FBetween  := ReadFromRegistry ('Scripts', 'FilterMacroBetween', FBetween);
  FCondition:= 0;
  FCondition:= ReadFromRegistry ('Scripts', 'FilterMacroCondition', FCondition);

  AFormCaption := 'Filter by Macro Command';
  AForm := BuildForm;
  AForm.ShowModal;
  result := (AForm.ModalResult = mrOk);
  if result then
  begin
    FMacro     := Trim(AMacroEdit.Text);
    FContains  := Trim(AContainsEdit.Text);
    FBetween   := Trim(ABetweenEdit.Text);
    FCondition := ACondition.ItemIndex;
  end;
  AForm.Free;
end;

procedure Finalize;
begin
  MacroValuesPopup.Component := nil;

  WriteToRegistry ('Scripts', 'FilterMacro', FMacro);
  WriteToRegistry ('Scripts', 'FilterMacroContains', FContains);
  WriteToRegistry ('Scripts', 'FilterMacroBetween', FBetween);
  WriteToRegistry ('Scripts', 'FilterMacroCondition', FCondition);
end;

function Filter(AItem: TImageItem): Boolean;
var
  AVal: WideString;
  AContains, ABetween: WideString;
begin
  result := False;
  if FMacro = '' then
    exit;

  AVal      := AItem.ParseMacros (FMacro, nil);
  AContains := AItem.ParseMacros (FContains, nil);
  ABetween  := AItem.ParseMacros (FBetween, nil);

  case FCondition of
    0:  // contains
      result := (WideTextPos (AContains, AVal) > 0);
    1:  // not contains
      result := (WideTextPos (AContains, AVal) = 0);
    2:  // equals
      result := WideSameText (AContains, AVal);
    3:  // not equals
      result := not WideSameText (AContains, AVal);
    4:  // less than
    begin
      if AVal = '' then
        result := False
      else if IsValidNumberString(AContains, False, DecimalSeparator) and
              IsValidNumberString(AVal, False, DecimalSeparator)
      then
        result := (AVal < StrToFloat(AContains))
      else
        result := (WideCompareStr(AVal, AContains) < 0);
    end
    5:  // greater than
    begin
      if AVal = '' then
        result := False
      else if IsValidNumberString(AContains, False, DecimalSeparator) and
              IsValidNumberString(AVal, False, DecimalSeparator)
      then
        result := (AVal > StrToFloat(AContains))
      else
        result := (WideCompareStr(AVal, AContains) > 0);
    end
    6:  // between
    begin
      if (AVal = '') then
        result := False
      else if IsValidNumberString(AContains, False, DecimalSeparator) and
              IsValidNumberString(AVal, False, DecimalSeparator) and
              IsValidNumberString(ABetween, False, DecimalSeparator) and
              IsValidNumberString(AVal, False, DecimalSeparator)
      then
        result := ((AVal >= StrToFloat(AContains)) and (AVal <= StrToFloat(ABetween)))
      else
        result := ((WideCompareStr(AVal, AContains) >= 0) and (WideCompareStr(AVal, ABetween) <= 0));
    end
    7:  // is blank
      result := AVal = '';
    8:  // is not blank
      result := AVal <> '';
  end;
end;