Newsgroups : Borland : borland.public.delphi.nativeapi.win32 : 2007 Jun : Delphi 7 Component Editor Woes...

www.cryer.info
Managed Newsgroup Archive

Delphi 7 Component Editor Woes...

Subject:Delphi 7 Component Editor Woes...
Posted by:"Welton" (welton at labdaq dot com)
Date:Wed, 20 Jun 2007 16:44:23

I'm not sure if this is the right forum for this message, but the
borland.public.delphi.vcl.components.writing forum seems to be gone.
Apologies for the cross posting.  I initially posted this in the general
forum, but was instructed that post it here.

I am attempting to write a component (TRuleDomains, a component that has a
list of TRuleDomain components, created using the component editor) and an
associated component editor (TRuleDomainsComponentEditor).  I have the
basics for my component in place, and I have created the component editor.
I can drop my component on a form, double click the form and it displays my
editor.  I can click the Add button on my component editor form, and the new
TRuleDomain items are created.  I can see them listed in the form's class
definition.  However, after I use the editor to add items (TRuleDomain) to
my component, something BAD happens to Delphi.  If I click the File/Close
All menu, it closes the form designer, but does not close the associated
.pas file or the component editor form.  If I try again to close the .pas
file, Delphi gives me --"Field Form1.RuleDomains1 does not have a
corresponding component. Remove the declaration?" errors for each of the
components (TRuleDomains and TRuleDomain) that I have created.  After that,
Delphi will abruptly unload itself from memory.  Delphi just disappears.  I
have included my aapRuleDomains.pas, aapRuleDomainsComponentEditorFrm.pas
and .dfm below.  Can anyone please show me where I am going off the rails?
I've been Googling and reviewing examples of component editors, as well as
looking at some comercial property editors in third party code that we have
licensed, and from what I can see I my code matches the stuff I've been
looking.  I've been going around in circles for three days now.

After playing around with this a little more, I have a little better
idea of what is happening.  I create a new application, drop my TRuleDomains
component onto the form creating RuleDomains1, and then double click my
RuleDomains1 component and the component editor is displayed. When I click
the Add button in the RuleDomains component editor, it creates a new
TRuleDomain component, by calling TRuleDomain.Create(RuleDomains1.Owner),
thereby assigning the owner of RuleDomains1 to the new TRuleDomain instance.
At this point I can see the new TRuleDomain component listed in the form's
component declaration section (above the private declaration section.)  If I
view the form's .dfm, I can see the TRuleDomains definition as well as the
TRuleDomain definition, however, when if this form is saved, and I view the
.dfm, the TRuleDomains definition is there, but not the TRuleDomain
definition.  In short, it appears that any TRuleDomain component that is
created by the component editor doesn't really get added to the .dfm file.
What can I do to make sure the both the .pas and .dfm files are correctly
updated when I create a new component through a component editor?


Any help would be greatly appreciated.

TIA,
    Welton

-------------------------------------------------------------------------

unit aapRuleDomains;

interface

uses
  SysUtils, Classes, DesignEditors;

type
  TDomainDataFormat = (ddfString, ddfInteger, ddfBoolean, ddfDateTime,
ddfList, ddfNameValue);

  TAllowedOperator = (acEqual, acNotEqual, acBetween, acNotBetween, acOneOf,
acNotOneOf);

  TAllowedOperators = set of TAllowedOperator;

  TRuleDomain = class(TComponent)
  private
    fFieldName: string;
    fDomainDataFormat: TDomainDataFormat;
    fAllowedOperators: TAllowedOperators;
    fDefinition: string;

    procedure SetDomainDataFormat(const Value: TDomainDataFormat);
    procedure SetFieldName(const Value: string);
    procedure SetAllowedOperators(const Value: TAllowedOperators);
    procedure SetDefinition(const Value: string);

  public
    procedure Assign(aSource: TPersistent); override;

  published
    property DomainDataFormat: TDomainDataFormat read fDomainDataFormat
write SetDomainDataFormat;
    property FieldName: string read fFieldName write SetFieldName;
    property Definition: string read fDefinition write SetDefinition;
    property AllowedOperator: TAllowedOperators read fAllowedOperators write
SetAllowedOperators;

  end;

  TRuleDomains = class(TComponent)
  private
    fItems: TList;

    function GetCount: integer;
    function GetItems(Index: integer): TRuleDomain;
    procedure SetItems(Index: integer; const Value: TRuleDomain);

  protected

  public
    constructor Create(aOwner: TComponent); override;
    destructor Destroy; override;

    function AddItem: TRuleDomain;
    procedure DeleteItem(Index: integer);

    property Items[Index: integer]: TRuleDomain read GetItems write
SetItems;
    property Count: integer read GetCount;

  end;

  TRuleDomainsComponentEditor = class(TComponentEditor)
  public
    procedure ExecuteVerb(Index: integer); override;
    function GetVerb(Index: integer): string; override;
    function GetVerbCount: integer; override;

  end;

procedure Register;

implementation

uses
  DesignIntf,
  aapRuleDomainsComponentEditorFrm;

procedure Register;
begin
  RegisterComponents('Antek', [TRuleDomains]);
  RegisterNoIcon([TRuleDomain]);
  RegisterComponentEditor(TRuleDomains, TRuleDomainsComponentEditor);
end;

{ TRuleDomains }

function TRuleDomains.AddItem: TRuleDomain;
begin
  result := TRuleDomain.Create(Self.Owner);

  fItems.Add(result);
end;

constructor TRuleDomains.Create(aOwner: TComponent);
begin
  inherited;

  fItems := TList.Create;
end;

procedure TRuleDomains.DeleteItem(Index: integer);
begin
  fItems.Delete(Index);
end;

destructor TRuleDomains.Destroy;
begin
  while Count > 0 do
    Items[Count - 1].Free;

  FItems.Free;
  FItems := nil;

  inherited;
end;

function TRuleDomains.GetCount: integer;
begin
  result := fItems.Count;
end;

function TRuleDomains.GetItems(Index: integer): TRuleDomain;
begin
  result := TRuleDomain(fItems[Index]);
end;

procedure TRuleDomains.SetItems(Index: integer; const Value: TRuleDomain);
begin
  fItems[Index] := Value;
end;

{ TRuleDomainsComponentEditor }

procedure TRuleDomainsComponentEditor.ExecuteVerb(Index: integer);
begin
  case Index of
    0: ShowRuleDomainsComponentEditorForm(Designer,
TRuleDomains(Component));
  else
    inherited;
  end;
end;

function TRuleDomainsComponentEditor.GetVerb(Index: integer): string;
begin
  case Index of
    0: result := 'Edit...';
    1: result := '-';
  end;
end;

function TRuleDomainsComponentEditor.GetVerbCount: integer;
begin
  result := 1;
end;

{ TRuleDomain }

procedure TRuleDomain.Assign(aSource: TPersistent);
begin
  inherited Assign(aSource);
end;

procedure TRuleDomain.SetAllowedOperators(const Value: TAllowedOperators);
begin
  fAllowedOperators := Value;
end;

procedure TRuleDomain.SetDefinition(const Value: string);
begin
  fDefinition := Value;
end;

procedure TRuleDomain.SetDomainDataFormat(const Value: TDomainDataFormat);
begin
  fDomainDataFormat := Value;
end;

procedure TRuleDomain.SetFieldName(const Value: string);
begin
  fFieldName := Value;
end;

end.

-------------------------------------------------------------------------

unit aapRuleDomainsComponentEditorFrm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, DesignWindows, DesignIntf,
  aapRuleDomains;

type
  TfrmRuleDomainsEditor = class(TDesignWindow)
    pnlButtons: TPanel;
    lbRuleDomains: TListBox;
    btnAdd: TButton;
    btnDelete: TButton;
    btnClose: TButton;

    procedure btnCloseClick(Sender: TObject);
    procedure btnAddClick(Sender: TObject);
    procedure lbRuleDomainsClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);

  private
    fDesigner: IDesigner;
    fRuleDomains: TRuleDomains;

  public

  end;

procedure ShowRuleDomainsComponentEditorForm(aDesigner: IDesigner;
aRuleDomains: TRuleDomains);

implementation

{$R *.dfm}

procedure ShowRuleDomainsComponentEditorForm(aDesigner: IDesigner;
aRuleDomains: TRuleDomains);
var
  i: integer;
  vForm: TfrmRuleDomainsEditor;
  vItem: TRuleDomain;
begin
  vForm := TfrmRuleDomainsEditor.Create(Application);
  vForm.fDesigner := aDesigner;
  vForm.fRuleDomains := aRuleDomains;

  for i := 0 to vForm.fRuleDomains.Count - 1 do
  begin
    vItem := vForm.fRuleDomains.Items[i];

    vForm.lbRuleDomains.Items.AddObject(vItem.Name, vItem);
  end;

  vForm.Show;
end;

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

procedure TfrmRuleDomainsEditor.btnAddClick(Sender: TObject);
var
  vItem: TRuleDomain;
begin
  vItem := fRuleDomains.AddItem;

  vItem.Name := fDesigner.UniqueName('RuleDomain');

  lbRuleDomains.Items.AddObject(vItem.Name, vItem);

  fDesigner.Modified;
end;

procedure TfrmRuleDomainsEditor.lbRuleDomainsClick(Sender: TObject);
var
  i: integer;
begin
  for i := 0 to lbRuleDomains.Count - 1 do
  begin
    if lbRuleDomains.Items[i] <>
TRuleDomain(lbRuleDomains.Items.Objects[i]).Name then
      lbRuleDomains.Items[i] :=
TRuleDomain(lbRuleDomains.Items.Objects[i]).Name;

    if lbRuleDomains.Selected[i] then
      fDesigner.SelectComponent(TPersistent(lbRuleDomains.Items.Objects[i]));
  end;
end;

procedure TfrmRuleDomainsEditor.FormClose(Sender: TObject; var Action:
TCloseAction);
begin
  Action := caFree;
end;

end.

-------------------------------------------------------------------------

object frmRuleDomainsEditor: TfrmRuleDomainsEditor
  Left = 349
  Top = 144
  Width = 272
  Height = 369
  Caption = 'Rule Domains Editor'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  OnClose = FormClose
  PixelsPerInch = 96
  TextHeight = 13
  object pnlButtons: TPanel
    Left = 176
    Top = 0
    Width = 88
    Height = 335
    Align = alRight
    TabOrder = 0
    DesignSize = (
      88
      335)
    object btnAdd: TButton
      Left = 8
      Top = 8
      Width = 75
      Height = 25
      Caption = '&Add'
      TabOrder = 0
      OnClick = btnAddClick
    end
    object btnDelete: TButton
      Left = 8
      Top = 40
      Width = 75
      Height = 25
      Caption = '&Delete'
      TabOrder = 1
    end
    object btnClose: TButton
      Left = 8
      Top = 303
      Width = 75
      Height = 25
      Anchors = [akLeft, akBottom]
      Caption = '&Close'
      TabOrder = 2
      OnClick = btnCloseClick
    end
  end
  object lbRuleDomains: TListBox
    Left = 0
    Top = 0
    Width = 176
    Height = 335
    Align = alClient
    ItemHeight = 13
    TabOrder = 1
    OnClick = lbRuleDomainsClick
  end
end

Replies:

www.cryer.info
Managed Newsgroup Archive