New Tab Control... well, finished anyways

And then the tab control was finally finished and across the lands, there was a greaaaaat rubbing of parts.

So… here is what the tab control looks like now:


2 Likes

How about some of the important changes:

  • Obviously, there is now an orientation
  • All tab panels are ScrollPanels.
  • You can set the layout of the tab panels by calling: setTabPanelLayout(index, layout); and the layout the child elements by calling layoutTabPanelChildren(index);
  • There are a bunch of extra setings for styles, positioning, etc
  • You can set the selected tab via setSelectedTab(index);
  • Next/Previous arrows now autohide when appropriate, limiting the functionality to what’s in view.
  • The rest is the same… you can still opt for slide effects, use fixed sized tabs, etc.

I was playing with this a little during my lunch break :slight_smile: Big improvments! But …

The fact tabs are now ScrollPanels is causing me a problem. I use tabs a lot, and now I have lots of unwanted scrollbars. In my tab content I never want scrolling, I want the layout to adjust and everything to resize (this is using my own layout system, that MIGHT be causing the problem - not sure yet). I am happy to turn off scrolling complete if there is some official way of doing it, but would end up extending TabControl and doing that by default anyway.

Also the slidetray. I was hoping it would now act as I had previously patched it, with the buttons only sliding until they are just visible (to the pixel), but it is still not as how I would expect it. Now again this might be my styles, or it might be my own extensions. I intend to investigate this further later tonight, i’ll post later with more details on this.

EDIT: This one is starting to look partially related to my styles (not yet sure what). The default style works better, but there are still some issues with the “revealing”. On the first click to the right, the LEFT arrow does not appear. Click again and it will. Also, when clicking the RIGHT arrow, the very last last click reveals the button but the arrow stays visible, clicking it again moves it a single pixel, clicking it again moves it the width of a tab (it should disappear as soon as it is fully revealed). With my own style, I see buttons revealing/hiding to weird places.

EDIT 2. Minor thing, the zorder of the initially selected tab looks wrong, it sets behind the next tab button. Select another tab and go back to it and it corrects itself.

Sorry for the complaints

RR

@rockfire said: I was playing with this a little during my lunch break :) Big improvments! But ...

The fact tabs are now ScrollPanels is causing me a problem. I use tabs a lot, and now I have lots of unwanted scrollbars. In my tab content I never want scrolling, I want the layout to adjust and everything to resize (this is using my own layout system, that MIGHT be causing the problem - not sure yet). I am happy to turn off scrolling complete if there is some official way of doing it, but would end up extending TabControl and doing that by default anyway.

Also the slidetray. I was hoping it would now act as I had previously patched it, with the buttons only sliding until they are just visible (to the pixel), but it is still not as how I would expect it. Now again this might be my styles, or it might be my own extensions. I intend to investigate this further later tonight, i’ll post later with more details on this.

EDIT: This one is starting to look partially related to my styles (not yet sure what). The default style works better, but there are still some issues with the “revealing”. On the first click to the right, the LEFT arrow does not appear. Click again and it will. Also, when clicking the RIGHT arrow, the very last last click reveals the button but the arrow stays visible, clicking it again moves it a single pixel, clicking it again moves it the width of a tab (it should disappear as soon as it is fully revealed). With my own style, I see buttons revealing/hiding to weird places.

EDIT 2. Minor thing, the zorder of the initially selected tab looks wrong, it sets behind the next tab button. Select another tab and go back to it and it corrects itself.

Sorry for the complaints

RR

Are you sure you are looking at the latest commit? A few of these were updated before posting this. I’ll look into getting the remainder done.

EDIT: The one that comes to mind right away was the scroll panels. The original commit was adding content to the wrong place and so scroll happened whether or not content was in the available area.

EDIT 2: Not complaints! Every bit helps me… as I get overloaded with stuff to do.

EDIT 3: Where is the patch for slide tray? I missed that one completely too >.<

Are you sure you are looking at the latest commit? A few of these were updated before posting this. I’ll look into getting the remainder done.

I wasn’t, but am now. I can’t tell you if it’s any better yet, I’m in the middle of fixing up my layout version of TabControl so it works with the latest changes. When my code is no longer in the “OMG everything is broken” state, i’ll come back to you :slight_smile:

The one that comes to mind right away was the scroll panels. The original commit was adding content to the wrong place and so scroll happened whether or not content was in the available area.

That sort of sounds like it, again i’ll come back to you when I can. I notice though that TabControl.TabPanel uses Window.resizeBorders for resize borders, but uses Tab.panelImg for the image. This implies you must use an image with the same borders as window (i don’t, use large borders for windows and smaller ones for inner borders).

I am not really convinced by this change. I preferred the old TabPanel that was just an Element. If you want scrollable content then add a ScrollPanel yourself. What was the reasoning behind it?

Not complaints! Every bit helps me… as I get overloaded with stuff to do.

:slight_smile:

Where is the patch for slide tray? I missed that one completely too >.<

Totally my fault, I am not surprised you missed it. It was BURIED in the wall of text that was my first post about layout managers (please dont reread that post, it’s hard to notice!). The actual patch is here. Skimming it, it does a few things. It’s probably mostly not relevant now, but may help. One thing it does is try disable the buttons while a slider is active. This was because if you clicked on a slide button while a slider was already active, it sort of loses the plot. This involved a complicated hack to get notifcation when an Effect ended. The rest was about using different calculations for working out how far to slide.

EDIT: I’ve just found commenting out in TabControl.java …

[java]

// tabSlider.setTrayPadding(-(tabResizeBorders.z/5*2));
[/java]

… partially fixes the problem (but creates another in that of course buttons now no longer overlap). This makes the edges of the revealed tab line up properly. The left/right arrow buttons still act incorrectly though.

1 Like
@rockfire said: That sort of sounds like it, again i'll come back to you when I can. I notice though that TabControl.TabPanel uses Window.resizeBorders for resize borders, but uses Tab.panelImg for the image. This implies you must use an image with the same borders as window (i don't, use large borders for windows and smaller ones for inner borders).

This was a total oversight… not intentional.

@rockfire said: I am not really convinced by this change. I preferred the old TabPanel that was just an Element. If you want scrollable content then add a ScrollPanel yourself. What was the reasoning behind it?

There was reasoning behind it??! O.o

Actually, what I wanted was the choice to select either for each tab… what I have finished so far… is… not that =)

@rockfire said: Totally my fault, I am not surprised you missed it. It was BURIED in the wall of text that was my first post about layout managers (please dont reread that post, it's hard to notice!). The actual patch is here. Skimming it, it does a few things. It's probably mostly not relevant now, but may help. One thing it does is try disable the buttons while a slider is active. This was because if you clicked on a slide button while a slider was already active, it sort of loses the plot. This involved a complicated hack to get notifcation when an Effect ended. The rest was about using different calculations for working out how far to slide.

Thanks!

EDIT: This now uses a GameTimer associated with the Slide Effectto ensure that everything is timed properly (i.e. no button clicks while effect is running, evals happen after the slide, etc)

EDIT 2: If you ever hit something like this, Use the following: (note there is also an overridable timer.timerUpdateHook(float tpf);… also note tpf is effected by the Interpolation you select for the GameTimer (linear is default)


GameTimer timer = new GameTimer(someDuration) {
    @Override
    public void onComplete(float time) {
        // Execute code here...
    }
}

// Execute at some point
timer.reset(false);
screen.getAnimManager().addGameTimer(timer);
@rockfire said: EDIT: I've just found commenting out in TabControl.java ..

[java]

// tabSlider.setTrayPadding(-(tabResizeBorders.z/5*2));
[/java]

… partially fixes the problem (but creates another in that of course buttons now no longer overlap). This makes the edges of the revealed tab line up properly. The left/right arrow buttons still act incorrectly though.

Ugh… left overs from testing… that is not supposed to be this way. This is supposed to be a configurable value via styles. NOT this =)

Within the week… most of the quirks should be worked out. (hopefully) Keep letting me know what you find, and I’ll post as I commit updates.

Got it!

Two last little things tonight …

tabTrayOverlap and labelPadding are both unstyleable (is that a word?). The overlap is fixed at 3 pixels, but the borders of my content are 2 pixels thick, so I get 1 pixel overlapping too far.

1 Like
@rockfire said: Got it!

Two last little things tonight …

tabTrayOverlap and labelPadding are both unstyleable (is that a word?). The overlap is fixed at 3 pixels, but the borders of my content are 2 pixels thick, so I get 1 pixel overlapping too far.

Yes indeed… they will both also be in the style def.

@rockfire
Ok… couple of these are sorted out:

  1. multiple overloaded addTab methods
    — public void addTab(String title);
    — public void addTab(String title, ButtonAdapter tab);
    — public void addTab(String title, boolean useScrollPanel);
    — public void addTab(String title, ButtonAdapter tab, boolean useScrollPanel, boolean isCustomButton)

Basically allows you to use the custom button as a tab for adding different listeners. This will override the sizes, however it leaves the style info in place. Also allows you to define whether or not to use a scrollpanel or panel… the default is panel.

  1. the missing style info was added.

I’ll get the rest added tomorrow or later this evening.

@t0neg0d said: @rockfire Ok... couple of these are sorted out:
  1. multiple overloaded addTab methods
    — public void addTab(String title);
    — public void addTab(String title, ButtonAdapter tab);
    — public void addTab(String title, boolean useScrollPanel);
    — public void addTab(String title, ButtonAdapter tab, boolean useScrollPanel, boolean isCustomButton)

Basically allows you to use the custom button as a tab for adding different listeners. This will override the sizes, however it leaves the style info in place. Also allows you to define whether or not to use a scrollpanel or panel… the default is panel…

Looks good. I think a few more accessors are needed to make this usable though.

  • orientation is private. I need this when creating my custom button (can work around this by capturing it in the constructor).
  • I have no way of finding the button index that was clicked. I think slide tray needs a public accessor for “radioButtons”, and also the currently selected index. No work around for this (except reflection) as it’s not possible to override the creation of the slide tray.
@rockfire said: Looks good. I think a few more accessors are needed to make this usable though.
  • orientation is private. I need this when creating my custom button (can work around this by capturing it in the constructor).
  • I have no way of finding the button index that was clicked. I think slide tray needs a public accessor for “radioButtons”, and also the currently selected index. No work around for this (except reflection) as it’s not possible to override the creation of the slide tray.
  1. Np there
  2. Actually, there always has been… but I’ll make it a bit more obvious. How would like this handled? Currently, you can call:

[java]
int bIndex = (Integer)el.getElementUserData();
[/java]

Just let me know how you would like this to work.

Eh… added an abstract method:

public abstract void onTabSelect(int index);

@t0neg0d said: Eh... added an abstract method:

public abstract void onTabSelect(int index);

That works :slight_smile: I was thinking a int getSelectedTab() method (as you already have a setSelectedTab(int)), but this works too.

@rockfire
I’m pretty sure I have the slide tray limiting to the visual range of the tray elements now. Should work for both Horizontal and Vertical.

Let me know if you hit any problems with it.

Sorry :\ Uhm, sort of better, sort of worse. At first I thought it was working, as at least the tabs were getting fully revealed, but they were just in a different position to what I expected. My attempt had them only slide enough to make them completely visible (i.e. their edge was touching the bounds of the slide tray), is that what you are expecting too?

Also, sometimes the last tab acts as before with a single pixel to slide, then the arrow button disappears. It also got very confused and let me slide way past where I should have been able to to. It almost seems like it acts a little different every time. I’ll play more.

Anyway, here is video showing what it’s doing right now

[video]http://youtu.be/R0_piCf2Va4[/video]

EDIT: The video doesnt really show the 1 pixel extra click that is needed, but it is there

EDIT: It acts different with own style too. In this one, the right arrow seems to get “stuck” and wont slide at all, and the button stays visible.

@rockfire said: Sorry : Uhm, sort of better, sort of worse. At first I thought it was working, as at least the tabs were getting fully revealed, but they were just in a different position to what I expected. My attempt had them only slide enough to make them completely visible (i.e. their edge was touching the bounds of the slide tray), is that what you are expecting too?

Also, sometimes the last tab acts as before with a single pixel to slide, then the arrow button disappears. It also got very confused and let me slide way past where I should have been able to to. It almost seems like it acts a little different every time. I’ll play more.

Anyway, here is video showing what it’s doing right now

[video]http://youtu.be/R0_piCf2Va4[/video]

EDIT: The video doesnt really show the 1 pixel extra click that is needed, but it is there

EDIT: It acts different with own style too. In this one, the right arrow seems to get “stuck” and wont slide at all, and the button stays visible.

Heh! Back to the drawing board >.<

How about vertical?

@t0neg0d said: Heh! Back to the drawing board >.<

How about vertical?

:\

Almost exactly the same behaviour. This time I left saw the slide up button make it slide down.

@rockfire said: :\n Almost exactly the same behaviour. This time I left saw the slide up button make it slide down.

What’s funny is how difficult this very simple thing is to implement with two separate origins and the trayPadding.

EDIT: If you wouldn’t mind, have a look at getNextOffset and see if you can figure out what the hell I have done wrong =)

Ok its getting late, but here is what I’ve got so far. I took my old patch and tried work out a new getNextOffset() from it. This MOSTLY fixes all the issues I was seeing, but there it still seems to have a little problem where it misses a slide, and from that point it gets confused.

One issue that fixed a lot of the problems was rounding. Casting a bunch of stuff to int made some weird issues go away.

[java]
private float getNextOffset(boolean dir) {
float over = 0f;
float diff;
if (dir) {
if (currentElementIndex + 1 < trayElements.size()) {
float w = (int)(orientation == Orientation.HORIZONTAL ? getWidth() : getHeight());
float x = (int)(trayElements.get(currentElementIndex).getX());
for (int i = currentElementIndex; i < trayElements.size(); i++) {
float cw = orientation == Orientation.HORIZONTAL
? (int)(trayElements.get(i).getWidth())
: (int)(trayElements.get(i).getHeight());
x += cw;
if (x > w) {
over = (x - w);
break;
}
x += trayPadding;

                 }
             }
         } else {
             if (currentElementIndex &lt; trayElements.size()) {
                 Element trayEl = trayElements.get(currentElementIndex);
                 // TODO this is not quite right, i think borders need to be accounted for
                 over = orientation == Orientation.HORIZONTAL
                         ? (int)(trayEl.getWidth() - trayEl.getX()  + trayPadding)
                         : (int)(trayEl.getHeight() - trayEl.getX()  + trayPadding);
             }
         }
         if (over &gt; 0) {
             diff = over;
         } else if (orientation == Orientation.HORIZONTAL) {
             diff = (trayElements.get(currentElementIndex - 1).getWidth() + trayPadding);
         } else {
             diff = (trayElements.get(currentElementIndex - 1).getHeight() + trayPadding);
         }

         return diff;
     }

[/java]

the following fixes the problem where the right hand arrow doesn’t disappear when it should. There was strange hard coded ‘5’ there, i suspect to account for rounding.

[java]
private void hideShowButtons() {
if (currentElementIndex == 0)
btnPrevElement.hide();
else
btnPrevElement.show();
Element el = trayElements.get(trayElements.size()-1);
if (orientation == Orientation.HORIZONTAL) {
// Added border to calculate and got rid of ‘5’
if (el.getX()+el.getWidth()-el.borders.z <= elTray.getWidth())
btnNextElement.hide();
else
btnNextElement.show();
} else {
if (el.getY() >= 0)
btnNextElement.hide();
else
btnNextElement.show();
}
if (!trayElements.isEmpty())
currentOffset = (elTray.getHeight()-trayElements.get(0).getY());
}

[/java]

This also seems to make it consistent between the default style and my own. I’ll carry on tomorrow if you don’t reply, I reckon it’s pretty close.

Nn

PS: I should note I have only concentrated on horizontal with the slide effect on. Will try the other configurations tomorrow as well.

1 Like

Another update. This fixes 99% of it. There is still one issue that you’ll see in the video below that seems to happen (so far only to vertical tabs), after you’ve resize the tab controls container a bit.

Patch can be found here

A lot of it was down to rounding, the root cause being TabControl when it set the sizes, setting them to rounded values helped a lot. Also the GameTimer used to show/hide buttons needed to be 0.26, i.e. longer than the effect. I’m not sure if this is the right approach. Can you guarantee that a timer used that will always run after the effect is finished? Is there no way to execute an actual method when the event really finished (i.e. part of the batch?).

When sliding is turned off it now uses exactly the same code so both should behave identically.

Note i accidentally left setAsContainer() commented out in that patch, i often use that and setting a patterned background to layout stuff. I think someone else has mentioned this, but a debug mode that highlights bounds of all elements would be cool.

I’ll have another go at that last resizing issue tonight!

[video]http://youtu.be/-SsWlFAFqY4[/video]

RR