Class Helper's with FireMonkey

Posted by on in Blogs
One of FireMonkeys really cool features is the way objects can be parented to other objects, and I've been using this a lot in demo's I've been writing recently. Supporting this are properites for TFMXObject.ChildrenCount and TFMXObject.Children (introduced on TFMXObject). Using these properties you can find out how many Children a specific object has at run time.

However, as Children can also parent other objects, if you want to find out how many objects of a specific type you have in your chain you have to loop the children recursively to do this. OK, so this is not to hard to code, but its more than 1 line of code and as this is the second demo I've worked on where I've wanted to find out how many objects of a specific type are present so it got me thinking... how can I make this easy to code to?

I finally decided on using the Class Helper language feature to create a new bit of functionality that expands TFMXObject in the project to make this easy.

Class helpers expand the functionality of a Record or a Class by adding new methods. For my version, I wanted to pass in a Class Type and find how many objects of this type were found. I added a method ChildrenCountOfType to do this which accepted a ClassType and then returned a total.

I also added a ChildOfTypeAtIndex, although its crude in implementation, it does loop in order and find the controls one by one, using a hierarchical tree to give an order, but it served my purpose to give me a way to loop the control.

The code for my class helper is as follows...
unit MyFMXObjectHelper;
interface

uses FMX.Types;

type
TFMXObjectHelper = class helper for TFMXObject
function ChildrenCountOfType(aType : TClass): Integer;
function ChildrenOfTypeAtIndex(aType : TClass; Index : Integer): TFMXObject;
end;

implementation

{ TFMXObjectHelper }

function TFMXObjectHelper.ChildrenCountOfType(aType: TClass): Integer;
var
Idx: Integer;
Obj: TFmxObject;
begin
Result := 0;
for Idx := 0 to Pred(Self.ChildrenCount) do begin
Obj := Self.Children[Idx];
if Obj is aType then
Inc(Result);

Result := Result + Obj.ChildrenCountOfType(aType);
end;
end;

function TFMXObjectHelper.ChildrenOfTypeAtIndex(aType: TClass;
Index: Integer): TFMXObject;
var
I, Remaining: Integer;
Obj: TFmxObject;
CurrItem: TFmxObject;
Nodes: Integer;
begin
Remaining := Index;

for I := 0 to Pred(Self.ChildrenCount) do begin
CurrItem := Self.Children[I];

if (CurrItem is aType) then begin
if (Remaining <= 0) then
Exit(CurrItem)
else
Dec(Remaining,1);
end;

Nodes := CurrItem.ChildrenCountOfType(aType);
if (Nodes <= Remaining) then
Dec(Remaining,Nodes)
else begin
Obj := CurrItem.ChildrenOfTypeAtIndex(aType, Remaining);
Exit(Obj);
end;
end;
end;

end.


With my class helper compiling, I added the unit to my uses clause and recompiled, immediately my TFMXObject had new functionality ready for use... now just to use it. :-)

My form has a control called tvAssociations (a TreeView) that I wanted to look all the node (ignoring the hierarchy. As TTreeView is of type TFMXObject, I added the following code for it to work.





for I := 0 to Pred(tvAssociations.ChildrenCountOfType(TTreeViewItem)) do begin
Item := tvAssociations.ChildrenOfTypeAtIndex(TTreeViewItem,I);
//do some stuff with the item
end;


Simples!!


About
Gold User, Rank: 19, Points: 169
Product Marketing Manager & Associate Product Manager, InterBase. @DelphiABall

Comments

  • Guest

    [...] up on DelphiFeeds.com, I see a member of Embarcadero Developer Relations (Stephen Ball) has just blogged some example code. In it, he demonstrates a class helper that adds methods for enumerating a [...]

  • Guest
    Stephen Ball Tuesday, 3 July 2012

    Hi Chris, thanks for commenting on the Blog post by writing your own, as you say, its was just an example of the language feature in action; but great to see other examples of how to work and achieve the same goal with different language features that takes this kind of principle and pushes it further..

  • Please login first in order for you to submit comments
  • Page :
  • 1

Check out more tips and tricks in this development video: