Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 5 of 5 total
Thread Best way to reference children
Wed, Feb 4 2015 4:59 AMPermanent Link

Matthew Jones

Okay, I've been pondering my first component, and it will be a panel
replicator. Basically, most of my applications use a panel as the
parent of a number of child panels each of which varies according to an
array of information. So on our web shop, each panel has the product
name, a summary, and an image. (See secure.banxia.com for an example).

Now, this is easy for me currently as it is all in code. I have an
object which contains references to the sub-items. I have a
TProductPanel, and it can use

  TitleLabel.Caption := 'Hello';

A better example:

procedure OnMouseOver();
begin
   TProductPanel(m_xProductDisplay[TComponent(Sender).Tag]).Selected
        := True;
end;

procedure TProductPanel.SetSelected(bValue : Boolean);
begin
   m_bSelected := bValue;
   if m_bSelected then
   begin
       MainPanel.Color := clMintCream;
   end
   else
   begin
       MainPanel.Color := clWhite;
   end;
end;

Now, assuming that my new component has the parent panel and a single
"row panel", I'm trying to work out how to allow the user to reference
the panels to make them do something.

I suppose I could have a "fill event" or it could be done manually, but
either way I have no way to know what the user put on the panel, it
could be 3 labels and an image, or 4 edit boxes and a button.

MyComponent.Panel[1].Button[1].Caption := 'Press me';
(MyComponent.Panel[1].GetComponent['btnLabel'] as TButton).Caption :=
'Press me';

I can't keep the same names, but could use a suffix, so the "btnOne"
could be "btnOne_1" and thus searched for.

If anyone has thoughts about this, I'd appreciate hearing them!

Matthew
Wed, Feb 4 2015 7:23 AMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Matthew,

<< Now, assuming that my new component has the parent panel and a single
"row panel", I'm trying to work out how to allow the user to reference the
panels to make them do something. >>

Are you talking about something similar to the TDBCtrlGrid control in Delphi
?  If so, then that's do-able, but there's a lot of questions one would need
to answer before starting.  For example, do you want the child panels to be
resizable, limited to one child panel, and a target for dropped controls at
design-time ?

Probably the best place to start would be the TListControl control.  It
effectively replicates a single TListItem control within the context of the
client bounds, and is virtual so it is very efficient.  In your case, you
would make your child control mimic the behavior(s) of the TListItem control
in terms of nesting, clicking, etc.

When you start getting into coding parent/child controls, it is important to
understand how the control event dispatching works in EWB 2.  The rules are
fairly simple:

If an element is contained within an element that has a "controller"
component associated with it, then this controller component will receive
all dispatched events (mouse, keyboard, etc.) for any child elements
contained within the controller element.  As far as you're concerned, a
controller component is an instance of a TControl component (or descendant).

A controller component is associated with an element by creating the element
as its base element.  The base TInterfaceController class (ancestor of
TControl) handles this all transparently, provided that you simply use an
override of its protected CreateElement method to create the base element.
By default, the CreateElement method creates a simple "div" element that can
be used for just about anything, so in most cases you don't need to even do
anything with the CreateElement method.

Tim Young
Elevate Software
www.elevatesoft.com
Wed, Feb 4 2015 8:08 AMPermanent Link

Matthew Jones

I think I'm going to have to think hard about this. In essence, the
control is a big listbox, but with the idea that you can just drag
anything you want onto the list item, and that is automatically
replicated to each. I've seen this done in some systems by specifying
an "external" TPanel onto which you put the items, and the list
replicates that. That would work nicely actually so long as the list is
able to set the Tag of each one to the index in the list. Then the
normal event handlers can see which item it should be referencing.

Anyway, I will take time to read and understand your response.

Matthew
Wed, Feb 4 2015 10:07 AMPermanent Link

Matthew Jones

Tim Young [Elevate Software] wrote:

> Are you talking about something similar to the TDBCtrlGrid control in
> Delphi ?  If so, then that's do-able, but there's a lot of questions
> one would need to answer before starting.  For example, do you want
> the child panels to be resizable, limited to one child panel, and a
> target for dropped controls at design-time ?

Okay, now found out what the TDBCtrlGrid is, and yes, that sort of
thing. A parent panel that contains another panel that you can drop
anything onto, and then resize to suit. The width of the child panel is
automatically that of the parent, and the depth of the child is set at
design time (though could, I guess, be runtime, but let's not get to
ahead of ourselves!). Auto-layout would be nice, but probably free
anyway. https://secure.banxia.com/ shows the sort of thing I'm doing
with this. The main product list(s) use this, and if you click on the
"Connect" product, then you can see two panels each with an option on.
Hmm, dynamic height for the panels seems important, seeing that...

> When you start getting into coding parent/child controls, it is
> important to understand how the control event dispatching works in
> EWB 2.  The rules are fairly simple:
>
> If an element is contained within an element that has a "controller"
> component associated with it, then this controller component will
> receive all dispatched events (mouse, keyboard, etc.) for any child
> elements contained within the controller element.

I don't think I follow - how do you actually mean? As a concrete
example, the TImage on the panel has a mouseover event. Right now I
replicate that event into the multiple instances of the panel. If the
TListControl is handling events, how does it get to see them, and how
can they be passed to the original handlers? The TListControl doesn't
have a mouseover event.



> A controller component is associated with an element by creating the
> element as its base element.  The base TInterfaceController class
> (ancestor of TControl) handles this all transparently, provided that
> you simply use an override of its protected CreateElement method to
> create the base element.

I think I need more explanation of this too! Feel free to point me at
code. Actually, I'm on a train tomorrow, I'll print and read the
existing code.
Wed, Feb 4 2015 11:38 AMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Matthew,

<< Okay, now found out what the TDBCtrlGrid is, and yes, that sort of thing.
A parent panel that contains another panel that you can drop anything onto,
and then resize to suit. The width of the child panel is automatically that
of the parent, and the depth of the child is set at design time (though
could, I guess, be runtime, but let's not get to ahead of ourselves!).
Auto-layout would be nice, but probably free anyway.
https://secure.banxia.com/ shows the sort of thing I'm doing with this. The
main product list(s) use this, and if you click on the "Connect" product,
then you can see two panels each with an option on. Hmm, dynamic height for
the panels seems important, seeing that... >>

Forget about the layout/sizing for now - EWB 2 can handle any of that
without issue.

<< I don't think I follow - how do you actually mean? As a concrete example,
the TImage on the panel has a mouseover event. Right now I replicate that
event into the multiple instances of the panel. If the TListControl is
handling events, how does it get to see them, and how can they be passed to
the original handlers? The TListControl doesn't have a mouseover event. >>

Actually, yes, the TListControl does have OnMouse* events.  They're just
defined in the base TControl class, and aren't actually published until the
TListBox class.  EWB 2 uses a class design of "keep protected, publish as
late as possible".  This allows for the maximum amount of customization
without having any undesired properties appearing in the Object Inspector.

As a component developer, you should *never* use the standard event
properties for dealing with events.  You should use the protected Do*
methods in TControl for this (DoClick, DoMouseDown, DoMouseOver, etc).
These are the methods that *trigger* the events, and they, themselves, are
called by the main event manager.

However, the issue here is the dynamic nature of the controls residing on
the child panels.  If you really want to be able to put anything on each
child panel, then it may be better to handle the child panels in a similar
manner to the TPagePanel control, with it's dynamic pages that can act as
containers.  If you were to do things this way, then you *would* just hook
up the event handlers for the controls at design-time.

Are the controls that are on the child panels always going to be the same ?
If so, then you may want to consider making the child panel a standard
control, but just replicating instances of them in the container of your
choice at runtime.  This will allow you to keep the details of the way that
the child panel controls are handled.

<< I think I need more explanation of this too! Feel free to point me at
code. Actually, I'm on a train tomorrow, I'll print and read the existing
code. >>

Check out the TInterfaceController class in the WebUI unit, followed by the
TControl class in the WebCtrls unit.  Those two classes form the entire
basis for dealing with the UI, and they use the TElement class as the
building block for all UI elements that make up each control.

Tim Young
Elevate Software
www.elevatesoft.com
Image