Custom Property Editor

Are there any examples on how to create my own IDE Property Editor?


Thanks,

Rhett Price
IndySoft

It's not trivial. You should set three events in the object inspector component:


OnGetButtonType (and return the btDialog type)
OnGetEnableExternalEditor (and return True to enable a custom editor)
OnCallEditor (which you will use to implement your own custom dialog to edit the property)

Thanks for the help Wagner. I will give it a shot. Maybe there is a better way to do this. I have some custom components I've written in this structure that utilize Collections. 

Example:
TComponentA
  TMyCollection
    TMyCollectionItem  (instance1 for component A)    
    TMyCollectionItem  (instance2 for component A)

TComponentB
  TMyCollection
    TMyCollectionItem  (instance1 for component B)    
    TMyCollectionItem  (instance2 for component B)

Then a "Connection" component that brings them togeter.
TConnectorComponent
  Start (property name) : TMyCollectionItem 
  EndAt (property name) : TMyCollectionItem

The above three are non-visualcomponents. The first two contain collections, the last is intended to "link" collectionitems From component A to B

Think of A and B as devices with input ports and TConnectorComponent is a patch cord connecting the two.

Since TMyCollectionItems are deeper within the Components collection, they are not visible to the Start/End properties of the TConnectorComponent.

Ultimately I'd like to be able to pull a list of all TMyCollectionItem(s) that are within the same form as TConnectorComponent and populate the Start.End list with something like this:

(assuming this is how we named the components relative to their T-Type.

ComponentA.MyCollection.MyCollectionItem1A
ComponentA.MyCollection.MyCollectionItem2A
ComponentB.MyCollection.MyCollectionItem1B
ComponentB.MyCollection.MyCollectionItem2B

or 

ComponentA.MyCollectionItem1A
ComponentA.MyCollectionItem2A
ComponentB.MyCollectionItem1B
ComponentB.MyCollectionItem2B

or even just the DisplayNames of all the MyCollectionItems , etc.

My thought is to do this I might have to write my own property editor?

Thanks,

Rhett Price
IndySoft

Hi Wagner - your post got me exactly what I needed. Think I'm good! Thanks so much. Man I love Scripter Studio!!


- Rhett

Glad to help, Rhett. Let me know if you still need further assistance on this.

Hi Wagner, Are namespaces supported for uses? This is what occurs when a namespace unit is included then a dblclick to enter code for a button. The event is injected into the uses clause within the namespace string.

http://cloudapp.indysoft.com/cfec7bea5f2e

- Rhett

Unfortunately not, unit names should not contain dots.

Got it. Thanks.


Two things that may, or may not, be related... 

1 - Units not included to support all IDEObjectInspect events

It appears when you choose to use the following events in the IDEObjectInspector

IDEInspectorCompare
IDEInspectorFillEventList
IDEInspectorFilter
IDEInspectorGetEditorClass

The following units must be added to your uses clause:

PropertyList, PropertyInspEditors, TypInfo

I'm not sure if that is intentional or should be added when the component drops. Thought to mention.




2 - Unclear on how to use the custom dropdown option in the inspector


We have set a property in the ObjectInspector to reference an instance of a TGrpButtonItem control.

We've converted the property to use a Dropdown and override the list to populate it with a list of all TGrpButtonItems found in the application (By name) 

When selecting the item from the combo dropdown we are seeing an error 

"raised excveption class EConvertError with message "Port1A" is not a valid integer value"

The execution order leading to the issue...

Our inspector event... (currently contains an entry to just log that it fired and give us a breakpoint to trace)

procedure TForm1.IDEInspector2SetValue(Sender: TObject; TheIndex: Integer;
  var Value: string; var EnableDefault: Boolean);
begin
  ListBox1.Items.Add('SettingValue');
end;


The above fires then passes up to :


procedure TAdvCustomComponentInspector.SetValue(TheIndex: Integer; const Value: string);
var
  i: Integer;
  P: TProperty;
  Val,Name: string;
  EnableDefault: Boolean;
begin
  with FPropertyList do
  begin
    EnableDefault:=True;
    Val:=Value;
    if Assigned(OnSetValue) then
      OnSetValue(Self,TheIndex,Val,EnableDefault);
    if EnableDefault and ValidPropIndex(TheIndex) then
    begin
      Val:=Translate(Val,False);
      Name:=Properties[TheIndex].FullName;
      for i:=0 to Pred(PropertyListCount) do
      begin
        P:=PropertyLists.FindProperty(Name);
        if Assigned(P) then
          SetPropertyValue(P, Val);
      end;
    end;
    Change(TheIndex);
  end;
end;


It appears this may be looking for a pointer reference to the object represented by my string.

My thinking is to do a FindComponent(Value) then assign a pointer... that said, this is within a function that is expecting a string... so then that doesn't seem correct either;

I'm not sure if adding those uses (since I am referencing properties, etc) led to this or not, so I'm a little confused.

Thanks,

Rhett

Those units need to be manually added yes.

Take a look at method TProperty.SetStringValue in unit PropertyList. There you might have a better understanding on how it works.
Basically, if you are trying to set a component reference, you should pass the name of the component, exactly like you would do in object inspector directly (you would type the name of the component).

Ah, ok that makes sense. Thanks!


- Rhett