TabControl design

Discussion regarding the development of CEGUI itself - as opposed to questions about CEGUI usage that should be in the help forums.

Moderators: CEGUI MVP, CEGUI Team

User avatar
Sinbad
Not too shy to talk
Not too shy to talk
Posts: 35
Joined: Wed Jan 12, 2005 12:06
Location: Guernsey, Channel Islands
Contact:

TabControl design

Postby Sinbad » Sun Aug 08, 2004 16:04

Hi,

I just thought I'd post how I intended to implement a tab control widget, so you can tell me if I'm going wrong. Bear in mind I'm not trying to create a multi-line tablist, nor am I adding tab scrolling, although both could be added later. I'm hitting a few issues I think because I want to allow people to define the content of the tab panes in XML using the standard child window idiom; however internally it makes more sense for the children to be children of the TabPane (a child of the TabControl) for clipping purposes. Anyway, here's what I think right now:

TabControl is the main class and is derived from Window, this is basically just a parent for the classes that do the real work. It contains within it a number of TabButton (derived from BuutonBase) instances, one for each tab, and a single TabPane instance (derived from Static), the clipping content area of the pane. It stores the currently active tab (as an index), which also maps to the corresponding index of the child of the TabPane.

What I want to do is this: when you add a child window to the TabControl, it actually becomes a child of the internal TabPane (so it becomes a grandchild). Only one child of TabPane will be visible at once. However, in order to delegate the adding / removing of children to the TabPane child, I would need to override addChildWindow, which is unfortunately non-virtual on Window. I only have access to onChildAdded, which is not enough to veto the direct add AFAIK.

The reason I want to do it this way is that it makes it simple in XML. You can write:

Code: Select all

<Window Type="Taharez Tab Control" Name="MyTab">
    <Window Type="Taharez StaticText" Name="YouTextyThing">
        <Property Name="Text" Value="Some Text"/>
...

And what you get is your StaticText object placed automatically in the 'content' area of the control, since it's actually a child of the TabPane. Otherwise, you'd have to define both the TabPane and the TabButtons in the XML which makes it harder and more error prone.

I suppose instead of overriding addChildWindow I could just keep everything as a child of TabControl, and manually shunt other children down into the tab pane area, but this feels wrong to me.

So, can I make addChildWindow (and removeChildWindow) virtual? Obviously when I'm adding the TabButton and TabPane instances as children I'll have to use a method which does not trigger a new tab. Will I also have to do something with getActiveChild(), or is this ok since the active child will be the TabPane, which itself will contain the content areas?

Thanks

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

TabControl design

Postby CrazyEddie » Sun Aug 08, 2004 16:21

Hi,

Your approach sounds good :)

You may virtualise those methods as it's probably the best way to achieve what's needed. The only other solution that I could come up with was to subscribe to the ChildAdded event and mess around detaching the window and re-attaching to the TabPane - but this is not a particularly clean solution (plus removal of those children could be real fun!).

getActiveChild() works as you descrbed, and so should pose no problems.

CE.

User avatar
Sinbad
Not too shy to talk
Not too shy to talk
Posts: 35
Joined: Wed Jan 12, 2005 12:06
Location: Guernsey, Channel Islands
Contact:

TabControl design

Postby Sinbad » Sun Aug 08, 2004 17:29

Cool, I shall commence hacking ;)

User avatar
Sinbad
Not too shy to talk
Not too shy to talk
Posts: 35
Joined: Wed Jan 12, 2005 12:06
Location: Guernsey, Channel Islands
Contact:

TabControl design

Postby Sinbad » Sun Aug 08, 2004 21:04

I decided that overriding addChild_impl and removeChild_impl was a better idea (now I spotted them), which has involved 2 changes; making them virtual and changing 'private' to 'protected'.

I've noticed you use 'private' a lot rather than 'protected', is there a reason for this? I rarely use private myself since it limits what subclasses can do, which can cause extensibility problems. The only time I use private is when I absolutely know that a subclass shouldn't be messing with something, but that's fairly rare.

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

TabControl design

Postby CrazyEddie » Mon Aug 09, 2004 08:33

I wouldn't have thought overriding these _impl methods would have been required :? I'd have thought you could have done the job needed by overriding the normal add/remove methods and doing something like this:

Code: Select all

void TabControl::addChildWindow(Window* window)
{
    d_TabPane->addChildWindow(window);

    // possibly fire normal event, since client thinks window was added here.  May not want to do this though.
    WindowEventArgs args(window);
    onChildAdded(args);
}


Or something similar.

Privacy:
I tend to use private in three instances:
a) The class should not be derived from.
b) The private bits are essential to the way the class/system works.
c) Methods which have been split from the public/protected interface for implementation reasons (my _impl methods).

The addChild_impl and removeChild_impl cases are a bit of b and a bit of c. These methods are not only used for simply adding and removing windows (they also control z-ordering for example); as such it is absolutely essintial that they do the job that they were made to do - which is why they are private / non-virtual.

Maybe you have a really great reason for need this, that I have not considered?

User avatar
Sinbad
Not too shy to talk
Not too shy to talk
Posts: 35
Joined: Wed Jan 12, 2005 12:06
Location: Guernsey, Channel Islands
Contact:

TabControl design

Postby Sinbad » Mon Aug 09, 2004 11:19

It's really a question of scope. The reason I went for the _impl methods is that when I'm overriding something, I want to override the method which has the most limited scope that contains the behaviour I want to change. Otherwise, I have to duplicate behaviour that isn't really to do with the thing I want to override.

Whilst overriding addChildWindow would be fine, it does a few other things which are not directly to do with the actual adding of the window, things like respecting observer patterns etc. Whilst I could have just copied all that, the actual part I want to change is the physical add. If Window::addChildWindow changes to add other non-fundamental-add things (like more event raising, extra triggers etc), my override would have to be updated too, which is potentially error prone. By overriding the _impl version, I know that all I'm supposed to do is add, and I can respect that scope far more easily.

Having said all that, this is your baby so if you'd prefer me to override addChildWindow instead, I'll do that. :)

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

TabControl design

Postby CrazyEddie » Mon Aug 09, 2004 11:49

For the reasons you gave, overriding the _impl methods does make more sense, so feel free to continue with that :) I'm not an ogre (no pun intended, honest!) when it comes to things like this, the whole idea of open source is to get improvments and what have you from the community, I certainly won't stand in the way this..

I will point out that currently these methods are called to implement z-order changes, so actually get called more often than just from addChildWindow and removeChildWindow (but this may not always be the case). Whenever a window/widget is clicked it is actually removed from it's parent and re-added using these _impl methods - admittedly, this is something of a hack and for this reason may well be refactored at a later stage.

The above may need to be considered when you write your overrides.

CE.

User avatar
Sinbad
Not too shy to talk
Not too shy to talk
Posts: 35
Joined: Wed Jan 12, 2005 12:06
Location: Guernsey, Channel Islands
Contact:

TabControl design

Postby Sinbad » Mon Aug 09, 2004 16:33

Oo, yes that's news to me. I'll have to be careful then :)

User avatar
Sinbad
Not too shy to talk
Not too shy to talk
Posts: 35
Joined: Wed Jan 12, 2005 12:06
Location: Guernsey, Channel Islands
Contact:

TabControl design

Postby Sinbad » Tue Aug 10, 2004 23:10

I have the majority of the core lib coding done for this I think, although I'm flying rather blind because I haven't written the Taharez Look classes yet, I'm working on those now. I'm hoping it'll all just click together once I run it, since I've been following your design and coding patterns ;)

Quick question: I have need of a simple 'positioning' widget - it has no visual element but just serves as a grouping element and makes positioning simpler. I was going to use Static, until I realised there doesn't appear to be a concrete Taharez version of this, only of StaticText and StaticImage. Whilst I could fudge it with one of these, is there some other element I should use for this?

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

TabControl design

Postby CrazyEddie » Wed Aug 11, 2004 04:51

Sounds linke things ae coming together nicely :)

For a grouping/positioning widget, you could use either StaticText or Static image with the background and frame disabled (and of course no text or image), failing this a DefaultGUISheet, while the name implies it's supposed to be the root window, this isn't really the case, this window does nothing special, so could be an ideal candidate for grouping.

HTH

CE

User avatar
Sinbad
Not too shy to talk
Not too shy to talk
Posts: 35
Joined: Wed Jan 12, 2005 12:06
Location: Guernsey, Channel Islands
Contact:

TabControl design

Postby Sinbad » Wed Aug 11, 2004 11:40

Thanks, I'll ponder my options and carry on this evening :)

User avatar
spannerman
Home away from home
Home away from home
Posts: 330
Joined: Wed Jan 12, 2005 12:06

TabControl design

Postby spannerman » Wed Aug 11, 2004 13:29

Just wanted to say that Im following your progress and wish you luck.

Like Eddie pointed out, I am in need of a tab control and went about it by faking one using the ListHeader widget, so Im happy to see somebody with the required skills and time creating a 'proper' version.

If Im being presumptuous by thinking you will be releasing your code for this puppy, my apologies.

If I constantly come across somewhat like a vulture circling for free code, thats cos I am :twisted:

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

TabControl design

Postby CrazyEddie » Wed Aug 11, 2004 13:46

@Sinbad:
If it makes the decision of which option to use any easier, some time soon I'm going to change the type name of "DefaultGUISheet" to "DefaultWindow". In addition to this, all the Taharez widget typenames are going to change to "Taharez/<widget-type>" this will keep things in line with the Windows look widget types which I have named in that fasion; I feel this overall approach to widget-type naming is better, plus there will be consistancy across widget sets. Now, due to the wonder that is CEGui :shock:, I can do this without breaking any of the code using the old type names everybody has been using up to now (just need an updated data file containing the required aliases). :)

@spannerman:
I think you'll likely get your free widget code ;)

User avatar
Sinbad
Not too shy to talk
Not too shy to talk
Posts: 35
Joined: Wed Jan 12, 2005 12:06
Location: Guernsey, Channel Islands
Contact:

TabControl design

Postby Sinbad » Wed Aug 11, 2004 15:52

Thanks, that does make it easier. I preferred DefaultGUISheet anyway so it's name change will make the decision more appropriate.

I have to go through the formality of checking with the company who is funding this work before I can officially release it, but I'm almost certain it won't be a problem.

User avatar
spannerman
Home away from home
Home away from home
Posts: 330
Joined: Wed Jan 12, 2005 12:06

TabControl design

Postby spannerman » Wed Aug 11, 2004 17:13

Yikes! ...I was being too presumptuous :oops:


Return to “CEGUI Library Development Discussion”

Who is online

Users browsing this forum: No registered users and 12 guests