{ *************************************************************************** }
{                                                                             }
{ EControl Syntax Editor SDK                                                  }
{                                                                             }
{ Copyright (c) 2004 - 2008 EControl Ltd., Zaharov Michael                    }
{     www.econtrol.ru                                                         }
{     support@econtrol.ru                                                     }
{                                                                             }
{ *************************************************************************** }
{$I ecSyntEdit.INC}

unit ecPropListDlg;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, ecSyntMemo, ComCtrls, ToolWin, StdActns, ActnList, ImgList,
  ecSyntAnal, ecPopupCtrl, ecActns, ExtCtrls, StdCtrls;

type
  TPropsListDlg = class(TForm)
    ToolBar1: TToolBar;
    SyntaxMemo1: TSyntaxMemo;
    ActionList1: TActionList;
    ImageList1: TImageList;
    ToolButton1: TToolButton;
    ToolButton2: TToolButton;
    AutoCompletePopup1: TAutoCompletePopup;
    SyntStyles1: TSyntStyles;
    ecCut1: TecCut;
    ecCopy1: TecCopy;
    ecPaste1: TecPaste;
    ecClear1: TecClear;
    ecUndo1: TecUndo;
    ecRedo1: TecRedo;
    ecToggleWordWrap1: TecToggleWordWrap;
    ToolButton3: TToolButton;
    ToolButton4: TToolButton;
    ToolButton5: TToolButton;
    ToolButton6: TToolButton;
    ToolButton7: TToolButton;
    ToolButton8: TToolButton;
    ToolButton9: TToolButton;
    ToolButton10: TToolButton;
    ToolButton11: TToolButton;
    ToolButton12: TToolButton;
    Panel1: TPanel;
    Button1: TButton;
    Button2: TButton;
    SyntAnalyzer1: TSyntAnalyzer;
    actOpen: TAction;
    actSave: TAction;
    SaveDialog1: TSaveDialog;
    OpenDialog1: TOpenDialog;
    procedure AutoCompletePopup1GetAutoCompleteList(Sender: TObject;
      Pos: TPoint; List, Display: TStrings);
    procedure SyntAnalyzer1BlockRules0BlockCheck(Sender: TObject;
      Client: TClientSyntAnalyzer; const Text: String; var RefIdx: Integer;
      var Accept: Boolean);
    procedure actOpenExecute(Sender: TObject);
    procedure actSaveExecute(Sender: TObject);
  private
    FRoot: TComponent;
    FTempl: TObject;
  public
  end;

function EditPropertyList(List: TStrings; Root: TComponent; Template: TObject): Boolean;

implementation

uses TypInfo, ecPropManager, ecRttiUtils;

{$R *.dfm}

function EditPropertyList(List: TStrings; Root: TComponent; Template: TObject): Boolean;
begin
  with TPropsListDlg.Create(nil) do
   try
     FRoot := Root;
     FTempl := Template;
     SyntaxMemo1.Lines.Text := List.Text;
     Result := ShowModal = mrOk;
     if Result then
      List.Assign(SyntaxMemo1.Lines);
   finally
     Free;
   end;
end;

procedure TPropsListDlg.AutoCompletePopup1GetAutoCompleteList(
  Sender: TObject; Pos: TPoint; List, Display: TStrings);
var s, Path: string;
    i, Count: integer;
    Obj: TObject;
    PList: PPropList;
  procedure AddComponents(Own: TComponent);
  var i: integer;
  begin
    for i := 0 to Own.ComponentCount - 1 do
      with Own.Components[i] do
        if Name <> '' then
          begin
            List.Add(Name);
            Display.Add('\s2\' + Name + '\s3\: ' + ClassName);
          end;
  end;
begin
  List.Clear;
  Display.Clear;
  if SyntaxMemo1.Lines.Count = 0 then S := ''
    else S := SyntaxMemo1.Lines[Pos.Y];
  Path  := Trim(Copy(S, 1, Pos.X));
  if (Length(Path) > 0) and (Path[Length(Path)] = '.') then Delete(Path, Length(Path), 1);
  // fills component of the Root
  if Path = '' then
    AddComponents(FRoot);
  // fills properties
  Obj := ExtractObject(FTempl, FRoot, Path, False);
  if (Obj <> nil) and (Path = '') then
   begin
     if Obj is TComponent then
       AddComponents(Obj as TComponent);
    {$IFNDEF EC_DOTNET}
    {$IFDEF EC_VCL5}
     PList := nil;
     Count := GetPropList(PTypeInfo(Obj.ClassInfo), tkProperties, PList);
     GetMem(PList, Count * sizeof(Pointer));
     Count := GetPropList(PTypeInfo(Obj.ClassInfo), tkProperties, PList);
    {$ELSE}
     Count := GetPropList(Obj, PList);
    {$ENDIF}
     try
     for i := 0 to Count - 1 do
      with PList^[i]^ do
       if PropType^^.Kind <> tkMethod then
        begin
         List.Add(Name);
         Display.Add('\s1\' + Name + '\s3\: ' + PropType^^.Name);
        end;
     finally
      FreeMem(PList);
     end;
    {$ELSE}
     PList := GetPropList(Obj);
     for i := 0 to Length(PList) - 1 do
      with PList[i] do
       if PropType.Kind <> tkMethod then
        begin
         List.Add(Name);
         Display.Add('\s1\' + Name + '\s3\: ' + PropType.Name);
        end;
    {$ENDIF}
   end;
end;

procedure TPropsListDlg.SyntAnalyzer1BlockRules0BlockCheck(Sender: TObject;
  Client: TClientSyntAnalyzer; const Text: String; var RefIdx: Integer;
  var Accept: Boolean);
begin
  Accept := Accept and (Client.TagPos[RefIdx].X = 0) and
            (FRoot <> nil) and (FRoot.FindComponent(Client.TagStr[RefIdx]) <> nil);
end;

procedure TPropsListDlg.actOpenExecute(Sender: TObject);
begin
  if OpenDialog1.Execute then
    SyntaxMemo1.LoadFromFile(OpenDialog1.FileName);
end;

procedure TPropsListDlg.actSaveExecute(Sender: TObject);
begin
  if SaveDialog1.Execute then
  SyntaxMemo1.SaveToFile(SaveDialog1.FileName);
end;

end.
