Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 9 of 9 total
Thread Layout copying
Fri, Sep 18 2015 8:49 AMPermanent Link

Matthew Jones

I have previously shown how I use TPanels (now TBasicPanels) for a nice
looking list of items. I have a template, and then have code that
copies it each time. This works in EWB2 as well, but for one small flaw
- Layouts.

The Layouts are simply a brilliant thing, and make the panels look very
nice. But when I copy the items on the panel, like labels etc, I also
copy the layout properties, and most important, the LayoutOrder. This
controls the order of everything, and ensures that the layout is as you
want. But, and it is a big but, if you change the layoutorder value to
a value less than the highest, it juggles all the other items. The
effect of this is that you have to create the controls on the panel in
the same order as the layout, or the layout is all over the place.

So, I'm pondering how I can make this work sensibly.

I currently have a TDisplayPanel object that is like:

TDisplayPanel = class
private
 m_xLinePanel: TBasicPanel;
 m_xTitleLabel : TLabel;

public
 property LinePanel: TBasicPanel read m_xLinePanel write m_xLinePanel;
 property TitleLabel : TLabel read m_xTitleLabel write m_xTitleLabel;
end;

The code then does this:

xPanel := TLinePanel.Create(
               DuplicatePanel(pnlDetailMaster, pnlOptionParent));
xPanel.TitleLabel := DuplicateLabel(lblLineTitle, xPanel.LinePanel);

So the other components like TitleLabel are then created this way.

The best option I can think of for the moment is to have an array of
TControl (I hope that is a common ancestor, or TComponent), and a set
of constants for the various controls. I'd then keep the newly created
one and the original reference one in the array, and once they have
been all created.

So I'd have an array of
TComponentPair = class
 m_xOriginalMaster : TControl;
 m_xCopiedControl : TControl;
end;

I would go down the array and find the LayoutOrder 0, then 1, then 2,
etc, and process them in that order. (Noting that with embedded panels,
there may be two or more with LayoutOrder 0).

This is all necessary because I want to create a duplicate of a panel
and its contents, but most critically to be able to reference them
later to set their values etc.

Hmm, I just did a test and EWB supports array properties. Hmm,
unfortunately it doesn't do indexed properties, otherwise that would be
ideal. However, using DisplayControl[dcTitleLabel] is probably not too
bad.

Anyway if anyone has any magic solutions to this, I'd much like to hear
them.

I suspect that doing it this way would make it easier to manage, as I
could prepare the array, and just do a
AddComponent(cdTitleLabel, lblOriginalLabel);
That would mean I could remove some of the manual code, and make it all
more generic.

--

Matthew Jones
Fri, Sep 18 2015 10:37 AMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Matthew,

<< The Layouts are simply a brilliant thing, and make the panels look very nice. But when I copy the items on the panel, like labels etc, I also copy the layout properties, and most important, the LayoutOrder. >>

This is easy: don't copy the LayoutOrder property.  Just let EWB assign a new layout property for any control that you're creating, and it will get added to the end of the child controls for the given container.

<< This controls the order of everything, and ensures that the layout is as you want. But, and it is a big but, if you change the layoutorder value to a value less than the highest, it juggles all the other items. The effect of this is that you have to create the controls on the panel in the same order as the layout, or the layout is all over the place. >>

Yep.  So, just create the controls in the proper layout order, and you're all set.

<< Hmm, I just did a test and EWB supports array properties. Hmm, unfortunately it doesn't do indexed properties,  >>

Of course it supports indexed array properties.  Practically every component in the component library uses indexed array properties, including the base TControl class, which uses them for child controls:

        property ControlCount: Integer read GetControlCount;
        property Controls[AIndex: Integer]: TControl read GetControl;
        property VisibleControlCount: Integer read GetVisibleControlCount;
        property VisibleControls[AIndex: Integer]: TControl read GetVisibleControl;

Tim Young
Elevate Software
www.elevatesoft.com
Fri, Sep 18 2015 11:03 AMPermanent Link

Matthew Jones

Tim Young [Elevate Software] wrote:

> I
> also copy the layout properties, and most important, the LayoutOrder.
> >>
>
> This is easy: don't copy the LayoutOrder property.  Just let EWB
> assign a new layout property for any control that you're creating,
> and it will get added to the end of the child controls for the given
> container.

Thing is, I get the layout looking just so in the IDE, and then if I
copy the components in another order, the layout is a mess. Therefore I
have to create it all in the right order. Or, what I'd like to do, is
have some automatic code that sorts it for me so I can set the layout
in the IDE and the code doesn't break it.


> << Hmm, I just did a test and EWB supports array properties. Hmm,
> unfortunately it doesn't do indexed properties,  >>
>
> Of course it supports indexed array properties.


I meant the alternative type, where the index is specified in the
property itself, not passed as a parameter. In Delphi, this is done
like this:

 property MainLabel : TLabel index cpMainLabel read GetLabel;

So instead of the index being passed in, it is compiled in.

--

Matthew Jones
Fri, Sep 18 2015 11:16 AMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Matthew,

<< Thing is, I get the layout looking just so in the IDE, and then if I copy the components in another order, the layout is a mess. >>

Yes, I got that. Smile

<< Therefore I have to create it all in the right order. Or, what I'd like to do, is have some automatic code that sorts it for me so I can set the layout in the IDE and the code doesn't break it. >>

If you copy the controls in this order:

http://www.elevatesoft.com/manual?action=viewprop&id=ewb2&comp=TControl&prop=Controls

then you'll have the desired result.

Of course, though, this is all problematic because you're trying to create a component without actually creating a component.  My recommendation would be to create an actual TMyPanelControl that encapsulates all of the sub-controls, add it to the component library, and then forget about all of these issues.  You'll then be able to instantiate it as necessary, and you can control how the sub-controls are created/modified in more controlled manner.

<< I meant the alternative type, where the index is specified in the property itself, not passed as a parameter. >>

How would that help with your situation ?

Tim Young
Elevate Software
www.elevatesoft.com
Fri, Sep 18 2015 11:38 AMPermanent Link

Matthew Jones

Tim Young [Elevate Software] wrote:

> My recommendation would be to create an actual TMyPanelControl that
> encapsulates all of the sub-controls, add it to the component
> library, and then forget about all of these issues.

I should perhaps just make them a form and embed them... But it is nice
to be able to use the IDE to pop in another component and then know it
is sorted, rather than making custom components.


> << I meant the alternative type, where the index is specified in the
> property itself, not passed as a parameter. >>
>
> How would that help with your situation ?

Because the array will be to a generic TControl, and I want to have
properties as I do now for the items that make it easy in code.

 // current:
 xPanel.MainLabel.Caption := 'Hello Mum';
 // with array:
 TLabel(xPanel.CompArray[clMainLabel]).Caption := 'Hello';
 // with indexed property:
 xPanel.MainLabel.Caption := 'Hello Mum';

where the index is
 property MainLabel : TLabel index clMainLabel GetAsLabel;

I've used this sort of thing in Delphi quite a lot. It isn't essential
of course, but it makes things look a lot nicer.

--

Matthew Jones
Mon, Sep 21 2015 10:09 AMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Matthew,

<< Because the array will be to a generic TControl, and I want to have properties as I do now for the items that make it easy in code. >>

Yes, and all of this is "nice" because you're working *against* the way that EWB is designed to work by trying to avoid writing a custom control.

For example, I notice that a lot of your "sub-controls" are labels.  These don't even need to be handled as controls with a custom control.  They can be handled as simple sub-elements that are handled internally in the custom control.  Remember, controls are simply wrappers around a TElement with a little bit of sugar on top to handle event dispatching, etc.  But, if you're never going to handle clicks, etc. on a label, then none of that matters.

http://www.elevatesoft.com/manual?action=viewcomp&id=ewb2&comp=TElement

And, you can visually design/place TElements in the control interface designer.

Tim Young
Elevate Software
www.elevatesoft.com
Tue, Sep 22 2015 3:32 AMPermanent Link

Matthew Jones

Tim Young [Elevate Software] wrote:

> Yes, and all of this is "nice" because you're working against the way
> that EWB is designed to work by trying to avoid writing a custom
> control.

I had a think about this last night, and you are of course right. Some
of the panels I use are quite complex sets of the various components,
but a custom control is where I need to go. For this project, I just
need it converted - there's no budget for the time. But also no point
investing any more in fancy systems to make things better. On my other
project I need to get to, I will make a control and then I'll be able
to do it right, and also be able to retro fit it when there is a need.
Thanks.

--

Matthew Jones
Tue, Sep 22 2015 11:05 AMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Matthew,

BTW, I forgot to mention, if you need an example of this, check out this control interface:

tmessagedialogclient.wbi

It is the interface for the *client* area of a message dialog.  You'll notice in the IDE that you can create a new form based upon the TMessageDialog form class, and when you do, that you can't interact with things like the icon or message in the form designer.  This is the beauty of using straight-up UI elements in custom controls, as opposed to sub-controls.  You can essentially make custom controls that have "inert" UI elements, as far as the user of the control is concerned.  This makes it much, much easier to deal with in the form designer because you don't have to worry about accidentally changing something.

Tim Young
Elevate Software
www.elevatesoft.com
Tue, Sep 22 2015 11:32 AMPermanent Link

Matthew Jones

Tim Young [Elevate Software] wrote:

> This makes it much, much easier to deal with in the form designer
> because you don't have to worry about accidentally changing something.

I'm not sure it fits my need though, to be honest. I've had a look
through some interfaces for what are similar things, like tabbed pages,
and the message dialog, but they aren't a simple single component
containing others, but a UI segment that is built up in code. I can see
that is very powerful, but the typical panel I am building can have a
variety of items added according to need. Go to https://dev.banxia.com/
and look at the Frontier Analyst item, and compare to Decision Explorer
Connect. This is the master panel varied according to the data it gets,
and Connect has two lists of radio buttons. Also the links etc vary.
The main product list is also a set of panels. As is the shopping cart
item list (you can't actually buy anything on the dev site so feel free
to play!)

I think that my main madness was not using a simple Form actually.
Copying panels is not sensible when a form could do everything needed,
combined with the new layout facilities. I guess in EWB1 it made more
sense to use a panel as it wasn't so easy to lay out, but EWB2 makes
the layout a doddle.

A form also allows me to use any component as much as needed from what
I can see, rather than having to encapsulate it somehow. Putting a
calendar on one for example, needs to be simple.

Anyway, no hurry right now, the main shop admin system is now
converted, and have to run through that for operation before I go break
the main shop...

--

Matthew Jones
Image