{******************************************************************

                       JEDI-VCL Demo

 Copyright (C) 2002 Project JEDI

 Original author:

 Contributor(s):

 You may retrieve the latest version of this file at the JEDI-JVCL
 home page, located at http://jvcl.sourceforge.net

 The contents of this file are used with permission, subject to
 the Mozilla Public License Version 1.1 (the "License"); you may
 not use this file except in compliance with the License. You may
 obtain a copy of the License at
 http://www.mozilla.org/MPL/MPL-1_1Final.html

 Software distributed under the License is distributed on an
 "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 implied. See the License for the specific language governing
 rights and limitations under the License.

******************************************************************}

unit InspectorExampleMain;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  JvInspector, IniFiles, TypInfo, JvComponent, ImgList, JvExControls;

type
  TfrmInspector = class(TForm)
    JvInspector1: TJvInspector;
    JvInspectorBorlandPainter1: TJvInspectorBorlandPainter;
    JvInspectorDotNETPainter1: TJvInspectorDotNETPainter;
    TestImageList: TImageList;
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure JvInspector1AfterItemCreate(Sender: TObject; const Item: TJvCustomInspectorItem);
    procedure GetBoolsAsChecks(Sender: TJvInspectorEventData; var Value: Int64);
    procedure SetBoolsAsChecks(Sender: TJvInspectorEventData; var Value: Int64);
    procedure OnINISection(var SectionName: string; var Parse: Boolean);
    procedure OnINIKey(const SectionName: string; var ItemName: string; var ATypeInfo: PTypeInfo;
      var Allow: Boolean);
  private
    BoolsAsChecks: Boolean;
    INI: TIniFile;
    procedure AddInspectorSettings;
    procedure AddGlobalSettings;
    procedure AddFormAndControls;
    procedure AddCompoundTest;
    procedure AddCtrl(const Parent: TJvCustomInspectorItem; const Ctrl: TControl);
    procedure AddINIFile;
    procedure AddVarious;
    procedure ChangeChkState(const Item: TJvCustomInspectorItem);
    procedure Edit1Change2(Sender: TObject);
  public
  end;

var
  frmInspector: TfrmInspector;

implementation

{$R *.dfm}

uses
  InspectorExampleTestForm,
  JclRTTI,
  JVCLVer, JvInspExtraEditors;

type
  TTestOption = (toOption1, toOption2, toOption3, toOption4, toOption5, toOption6, toOption7, toOption8);
  TTestOptions = set of TTestOption;
  TTestRange = 0..9;
  TTestEnum = (teNone, teAtLeastOne, teAtMostTwo, teUnlimited);

var
  GeneratedTestEnum: PTypeInfo;
  FirstName: string = 'Marcel';
  Initial: string;
  LastName: string = 'Bestebroer';
  VerInfoStr: string = JVCL_VERSIONSTRING;
  ADate: TDateTime;
  ImgIdx: TImageIndex;

procedure TfrmInspector.AddInspectorSettings;
var
  InspCat: TJvInspectorCustomCategoryItem;
  I: Integer;
const
  PropArray: array [0..2, 0..1] of string =
   (
    ('UseBands', 'Use bands'),
    ('WantTabs', 'TAB navigates'),
    ('Painter', 'Paint style')
   );
begin
  InspCat := TJvInspectorCustomCategoryItem.Create(JvInspector1.Root, nil);
  InspCat.DisplayName := 'JvInspector Settings';
  for I := Low(PropArray) to High(PropArray) do
    TJvInspectorPropData.New(InspCat, JvInspector1, GetPropInfo(JvInspector1, PropArray[I, 0])).DisplayName := PropArray[I, 1];
  TJvInspectorVarData.New(InspCat, 'AboutJVCL', TypeInfo(string), @VerInfoStr).DisplayName := 'About JVCL';
  InspCat.Expanded := True;
end;

procedure TfrmInspector.AddGlobalSettings;
var
  InspCat: TJvInspectorCustomCategoryItem;
begin
  InspCat := TJvInspectorCustomCategoryItem.Create(JvInspector1.Root, nil);
  InspCat.DisplayName := 'Global Settings (event based data)';
  with TJvInspectorEventData(TJvInspectorEventData.New(InspCat, 'Use check marks', System.TypeInfo(Boolean)).Data) do
  begin
    OnGetAsOrdinal := GetBoolsAsChecks;
    OnSetAsOrdinal := SetBoolsAsChecks;
  end;
  InspCat.Expanded := True;
end;

procedure TfrmInspector.AddFormAndControls;
var
  InspCat: TJvInspectorCustomCategoryItem;
begin
  frmTest := TfrmTest.Create(Self);
  InspCat := TJvInspectorCustomCategoryItem.Create(JvInspector1.Root, nil);
  InspCat.DisplayName := 'Form and controls (published property data).';
  InspCat.SortKind := iskNone;
  AddCtrl(InspCat, frmTest); 
  AddCtrl(InspCat, frmTest.PanelForLabel);
  AddCtrl(InspCat, frmTest.lblTest);
  AddCtrl(InspCat, frmTest.Edit1);
  InspCat.Expanded := True;
end;

procedure TfrmInspector.AddCompoundTest;
var
  InspCat: TJvInspectorCustomCategoryItem;
  CompItem: TJvInspectorCompoundItem;
begin
  InspCat := TJvInspectorCustomCategoryItem.Create(JvInspector1.Root, nil);
  InspCat.DisplayName := 'Compound items test (variable or heap data).';
  CompItem := TJvInspectorCompoundItem.Create(InspCat, nil);
  CompItem.AddColumn(TJvInspectorVarData.New(CompItem, 'First', TypeInfo(string), @FirstName));
  CompItem.AddColumn(TJvInspectorVarData.New(CompItem, 'Initial', TypeInfo(string), @Initial));
  CompItem.AddColumn(TJvInspectorVarData.New(CompItem, 'Last', TypeInfo(string), @LastName));
  CompItem.Columns[0].Width := 25;
  CompItem.Columns[1].Width := 15;
end;

procedure TfrmInspector.AddCtrl(const Parent: TJvCustomInspectorItem; const Ctrl: TControl);
var
  InspCat: TJvInspectorCustomCategoryItem;
  M: TNotifyEvent;
begin
  InspCat := TJvInspectorCustomCategoryItem.Create(Parent, nil);
  InspCat.DisplayName := Ctrl.Name + ': ' + Ctrl.ClassName;
  if Ctrl = frmTest.Edit1 then
  begin
    with TJvInspectorPropData.New(InspCat, Ctrl, 'OnChange') as TJvInspectorTMethodItem do
    begin
      AddInstance(frmTest, 'frmTest');
      AddInstance(Self, 'frmInspector');
      M := frmTest.Edit1Change1;
      AddMethod(TMethod(M), 'Edit1Change1');
      M := Edit1Change2;
      AddMethod(TMethod(M), 'Edit1Change2');
    end;
  end
  else
    TJvInspectorPropData.New(InspCat, Ctrl);
end;

procedure TfrmInspector.AddINIFile;
var
  InspCat: TJvInspectorCustomCategoryItem;
begin
  if FileExists(ExtractFilePath(Application.ExeName) + 'JvInspectorDemo.ini') then
    INI := TIniFile.Create(ExtractFilePath(Application.ExeName) + 'JvInspectorDemo.ini')
  else if FileExists(ExtractFilePath(Application.ExeName) + '\Data\JvInspectorDemo.ini') then
    INI := TIniFile.Create(ExtractFilePath(Application.ExeName) + '\Data\JvInspectorDemo.ini')
  else
    MessageDlg('Unable to locate the JvInspectorDemo.ini file', mtError, [mbOK], 0);

  InspCat := TJvInspectorCustomCategoryItem.Create(JvInspector1.Root, nil);
  InspCat.DisplayName := 'INI files (INI-file data layer).';
  TJvInspectorINIFileData.New(InspCat, INI, OnINISection, OnINIKey);
end;

procedure TfrmInspector.AddVarious;
var
  InspCat: TJvInspectorCustomCategoryItem;
  NewItem: TJvCustomInspectorItem;
begin
  InspCat := TJvInspectorCustomCategoryItem.Create(JvInspector1.Root, nil);
  InspCat.DisplayName := 'Various tests.';
  TJvInspectorVarData.New(InspCat, 'Date/time', TypeInfo(TDateTime), @ADate);
  { Duplicate the columns of the compound items test. This will return the same data instance as
    used by the columns; a new item will be added to it. We change the name of this item, but the
    name of the data instance and the columns remain what they were. If we would change the Name
    of the data instance, this will result in all items that have the same name as the data instance
    to be renamed as well. }
  TJvInspectorVarData.New(InspCat, 'First', TypeInfo(string), @FirstName).DisplayName := 'Copy of first name';
  TJvInspectorVarData.New(InspCat, 'Initial', TypeInfo(string), @Initial).DisplayName := 'Copy of initial';
  TJvInspectorVarData.New(InspCat, 'Last', TypeInfo(string), @LastName).DisplayName := 'Copy of last name';

  { Add an ImageIndex test item }
  NewItem := TJvInspectorVarData.New(InspCat, 'ImageIndex', TypeInfo(TImageIndex), @ImgIdx);
  if NewItem is TJvInspectorTImageIndexItem then
    (NewItem as TJvInspectorTImageIndexItem).Images := TestImageList;
//  NewItem.RowSizing.MinHeight := 24;

  InspCat.Expanded := True;
end;

procedure TfrmInspector.ChangeChkState(const Item: TJvCustomInspectorItem);
var
  I: Integer;
begin
  if Item is TJvInspectorBooleanItem then
    TJvInspectorBooleanItem(Item).ShowAsCheckbox := BoolsAsChecks;
  for I := 0 to Item.Count - 1 do
    ChangeChkState(Item[I]);
end;

procedure TfrmInspector.Edit1Change2(Sender: TObject);
begin
  frmTest.mmChanges.Lines.Add('Edit1Change2 event');
end;

procedure TfrmInspector.FormCreate(Sender: TObject);
begin
  BoolsAsChecks := True;
  JvInspector1.BeginUpdate;
  JvInspector1.Root.SortKind := iskNone;
  AddGlobalSettings;
  AddInspectorSettings;
  AddCompoundTest;
  AddINIFile;
  AddVarious;
  JvInspector1.SelectedIndex := 0;
end;

procedure TfrmInspector.JvInspector1AfterItemCreate(Sender: TObject; const Item: TJvCustomInspectorItem);
begin
  if Item is TJvInspectorBooleanItem then
    TJvInspectorBooleanItem(Item).ShowAsCheckbox := True;
  if (Item.Data <> nil) and (CompareText(Item.Data.Name, 'AboutJVCL') = 0) then
    Item.ReadOnly := True;
  if (Item.Data <> nil) and (CompareText(Item.Data.Name, 'Painter') = 0) then
    with Item as TJvInspectorComponentItem do
    begin
      AddOwner(Self);
    end
  else if Item is TJvInspectorComponentItem then
    with Item as TJvInspectorComponentItem do
    begin
      AddOwner(frmTest);
    end;
end;

procedure TfrmInspector.GetBoolsAsChecks(Sender: TJvInspectorEventData; var Value: Int64);
begin
  Value := Ord(BoolsAsChecks);
end;

procedure TfrmInspector.SetBoolsAsChecks(Sender: TJvInspectorEventData; var Value: Int64);
begin
  if (Value <> 0) <> BoolsAsChecks then
  begin
    BoolsAsChecks := Value <> 0;
    JvInspector1.BeginUpdate;
    try
      ChangeChkState(JvInspector1.Root);
    finally
      JvInspector1.EndUpdate;
    end;
  end;
end;

function TextIndex(const S: string; const List: array of string): Integer;
begin
  Result := High(List);
  while (Result >= 0) and not AnsiSameText(S, List[Result]) do
    Dec(Result);
end;

procedure TfrmInspector.OnINISection(var SectionName: string; var Parse: Boolean);
begin
  case TextIndex(SectionName, ['', 'Global', 'Section2', 'TypedKeys', 'EmptySection']) of
    0:
      SectionName := '(no section)';
    1:
      SectionName := 'First section';
    2:
      SectionName := 'Second section';
    3:
      SectionName := 'Typed elements';
    4:
      SectionName := 'Empty section, has no keys';
  else
    Parse := False;
  end;
end;

procedure TfrmInspector.OnINIKey(const SectionName: string; var ItemName: string; var ATypeInfo: PTypeInfo;
  var Allow: Boolean);
begin
  case TextIndex(SectionName, ['', 'Global', 'Section2', 'TypedKeys', 'EmptySection']) of
    0:
      case TextIndex(ItemName, ['Key1WithoutSection', 'Key2WithoutSection']) of
        0:
          ItemName := 'First key';
        1:
          ItemName := 'Second key';
      else
        Allow := False;
      end;
    1:
      case TextIndex(ItemName, ['Key1', 'Key2']) of
        0:
          ItemName := 'First key';
        1:
          ItemName := 'Second key';
      else
        Allow := False;
      end;
    2:
      case TextIndex(ItemName, ['Key1', 'Key2']) of
        0:
          ItemName := 'First key';
        1:
          ItemName := 'Second key';
      else
        Allow := False;
      end;
    3:
      case TextIndex(ItemName, ['Options', 'IsValid', 'Float', 'Range_Int', 'SomeEnum', 'NewEnum']) of
        0:
          ATypeInfo := TypeInfo(TTestOptions);
        1:
          begin
            ItemName := 'Valid info';
            ATypeInfo := TypeInfo(Boolean);
          end;
        2:
          begin
            ItemName := 'Test float value';
            ATypeInfo := TypeInfo(Double);
          end;
        3:
          begin
            ItemName := 'Last digit';
            ATypeInfo := TypeInfo(TTestRange);
          end;
        4:
          begin
            ItemName := 'Required number of items';
            ATypeInfo := TypeInfo(TTestEnum);
          end;
        5:
          begin
            ItemName := 'Who or what is cool?';
            ATypeInfo := GeneratedTestEnum;
          end;
      else
        Allow := False;
      end;
  else
    Allow := False;
  end;
end;

procedure TfrmInspector.FormShow(Sender: TObject);
begin
  AddFormAndControls;
  JvInspector1.EndUpdate;
end;

initialization
  GeneratedTestEnum := JclGenerateEnumType('TestEnum',
    ['Me, myself and I', 'Marcel Bestebroer', 'Project JEDI', 'JEDI-VCL Inspector']);
  ADate := Now;

  TJvInspectorAlignItem.RegisterAsDefaultItem;
  TJvInspectorAnchorsItem.RegisterAsDefaultItem;
  TJvInspectorColorItem.RegisterAsDefaultItem;
  TJvInspectorTImageIndexItem.RegisterAsDefaultItem;

finalization
  RemoveTypeInfo(GeneratedTestEnum);

end.

