Skip to content

Tabs

Behavior of Tabs prior to gooey 2025.4

Behavior of tabs was improved in gooey 2025.4; however, this introduced some breaking changes. Throughout this article, I will highlight certain differences, in case you are working with an older version. However, it is strongly recommended to update gooey to the latest version.

When we saw the basic structure of panels, we saw the panel body, and we said it hosted the widgets added to the panel. In reality, the panel will host widgets either in a common widgets body area, or in a specific tab. Additionally, the panel contains a tab group control which allows you to switch between tabs. The schematics are as follows:

Panel structure Panel structure

If we stripped down the panel, we could see the following simplified structure:

Panel structure Panel structure

The panel tabs

All panels in gooey have at least one tab (tab index 0, by default) and can have multiple tabs. Whenever you add widgets with the add() method we've seen before, you are really adding to the current tab. If you've just created the panel, the current tab will be the tab with index 0. The add() method has an optional argument to specify to which tab you want to add the widget.

As expected, gooey will only render the current tab. To change between tabs, you can use the built-in tab group control, build one yourself or programatically change tabs.

The common widgets area

Additionally, there is a "special" tab in which common widgets are rendered. The objective of this tab is to render things that we need no matter which tab we are displaying. In particular, things like the panel title, the close button and the actual tab group control, are actually added and rendered in this area - thus being always available.

You can add other widgets to the common widgets area by using tab index -1.

The tab group control

Panels in gooey have a ready-made group of buttons that are automatically managed when adding / removing tabs. By default, the tab group control will only show if there's more than one tab created; however, you can control its visibility by using the setTabControlVisible() panel method.

You can also use various other methods to customize how tab buttons appear, whether the tab group control is horizontal or vertical, etc.

Example

Let's keep building our space colony UI example from the Intro to panels tutorial. We want it to have three tabs (one for unit info, another one for an upgrade shop, and a third one for shields. Let's use the addTab method from the UIPanel constructor to add them:

1
2
3
4
5
6
    var _panel = new UIPanel("MyPanel", 0, 0, 300, 500, spr_Panel_2, UI_RELATIVE_TO.MIDDLE_CENTER);
    _panel.setTitle("SPACE COLONY").setImageAlpha(0.8);
    _panel.setResizeBorderWidth(12);
    _panel.setCloseButtonSprite(spr_CloseButton).setCloseButtonOffset({x: -16, y: 8});

    _panel.addTab(2);

In the above code we are adding two tabs (since all panels have one "default" tab, tab 0, built in. This yields the following image:

Panel Tabs - First step

We can see that the tab control has automatically appeared. However, there are some problems:

1) We have not specified any sprite for the tab buttons; this makes them unusable (remember that gooey works exclusively with sprites, hence if there's no sprite the button will not work, since the height of the buttons will be set to 0). 2) The tab control appears at the top of the panel.

To fix this, let's now specify the sprites we want to use (again, courtesy of Wenrexa), and specify the offset of the tab control group relative to the anchor point:

    with (_panel) {
        setTabSprites(spr_Button_Normal);
        setTabSpritesSelected(spr_Button_Active)
        setTabSpritesMouseover(spr_Button_Hover);
    }

    _panel.setTabOffset({x: 0, y: _panel.getDragBarHeight()});

Offset of tab group control

Prior to gooey 2025.4, tab control would always be rendered at the drag bar height. Starting from 2025.4, you can specific a custom offset, however you need to do this manually. Also, bear in mind that x-offset for horizontal tab groups and y-offset for vertical tab groups will be ignored.

After doing this, the panel is looking much better:

Panel Tabs - Setting sprites and offset

We want to also set an appropriate text for each tab. We are going to use some Scribble formatting to include an icon and a name per each tab:

    _panel.setTabText(0, "[spr_Icon_Menu] Info");
    _panel.setTabText(1, "[spr_Icon_Money] Shop");
    _panel.setTabText(2, "[spr_Icon_Shield] Shields");  

Now, let's add some widgets to each tab so we can see how gooey manages them. We can supply a second argument to the add() method to add a widget to a specific tab:

    _panel.add(new UIButton("Button_1", 0, 0, 200, 200, "First", blue_panel, UI_RELATIVE_TO.MIDDLE_CENTER), 0);
    _panel.add(new UIButton("Button_2", 0, 0, 200, 200, "Second", green_panel, UI_RELATIVE_TO.MIDDLE_CENTER), 1);
    _panel.add(new UIButton("Button_3", 0, 0, 200, 200, "Third", red_panel, UI_RELATIVE_TO.MIDDLE_CENTER), 2);

Finally, let's add a widget to the common widgets zone (we can specify tab index -1 for this):

    _panel.add(new UIButton("Button_General", 0, -30, 250, 50, "[c_black]Accept", grey_button00, UI_RELATIVE_TO.BOTTOM_CENTER), -1);

Let's test the result! Click on each of the tab buttons in the tab control to see the corresponding widgets appear:

We can see that the Accept button appears no matter which tab we're on, and the button that appears corresponds to the tab we selected (since those were added to a specific tab).

Customizing the appearance of tabs

There's more customization we can have when rendering our tabs:

Orientation

We can control whether tabs are rendered horizontally or vertically, by using setVerticalTabs(). By default, tabs are horizontal.

Anchor point

We can control where tabs are rendered, by setting the anchor point for the tab control, using the regular UI_RELATIVE_TO enum and the setTabControlAlignment() method. This means we can display our horizontal tabs at the bottom, for example, by setting them horizontal and choosing BOTTOM_CENTER.

Tab control anchor point changes in gooey 2025.4

Prior to gooey 2025.4, anchor points for tab controls set to SPECIFIC or SPRITE were not correctly honored (see Size behavior below). However, this behavior changed in 2025.4. Anchor points can now be set and will be correctly honored for those types of size behaviors. Note that tab controls set to MAX (the default) will only honor the "vertical component" of the anchor point (if they are horizontal), or "horizontal component" of the anchor point (if they are vertical).

Size behavior

By default, tab buttons are configured to occupy the complete width (or height, if set to vertical) of the panel. So if we have three buttons like in the interactive example above, we can see that each of the buttons will measure one third of the panel width.

However, we can modify this behavior with the setTabSizeBehavior method. This method accepts an enum named UI_TAB_SIZE_BEHAVIOR, and its possible values are:

Value Description
MAX Sets each tab button size to 1/nth of the panel width (or height). Its size will dynamically be adjusted as you resize the panel. This is the default behavior.
SPECIFIC Sets all buttons to a specific width (or height), in pixels. The size will not dynamically change when you resize the panel. You can set this size by using setTabSpecificSize.
SPRITE Sets each tab to the width (or height) of its individual sprite. This allows to have different sizes per tab. The size will not dynamically change when you resize the panel.

Tab margin and spacing

By default, all tab buttons are rendered one next to the other, and the first tab button appears flush with the edge of the tab control. However, you can define margin and spacing between tabs by using setTabMargin and setTabSpacing methods. This will enable you to define tab controls that have spaces between buttons, and that have some margin from the panel edge.

A customized version of the example

For exemplification, let's take a look at the same example as before, but with customization. We add some lines of code below:

    _panel.setTabControlAlignment(UI_RELATIVE_TO.MIDDLE_RIGHT);
    _panel.setVerticalTabs(true);
    _panel.setTabSizeBehavior(UI_TAB_SIZE_BEHAVIOR.SPECIFIC).setTabSpecificSize(80);
    _panel.setTabSpacing(20);
    _panel.setTabMargin(10);

While we were at it, I changed the buttons on each tab so that you can play around with some of the settings. The first button in tab 0 will switch between vertical and horizontal tabs (by calling setVerticalTabs); the second one will cycle through the different anchor points (by setting setTabControlAlignment); and the third one will change between MAX and SPECIFIC (SPRITE is not included in the example, but works very similar to SPECIFIC).

Tab actuators

You have at your disposal the following methods. that allow you to programatically interact with tabs. I think they are self-explanatory, but you can always review the API reference:

  • For adding tabs, you have already seen that we have addTab(). We can specify the number of tabs to add.
  • For changing tabs, we have nextTab() and previousTab(), as well as gotoTab(), the last of which expects an index.
  • You can delete a tab by using removeTab(), by specifying the index.

Wrapping up

Tabs bring great flexibility for creating more complex panels for your UI. With several customization options, you can bring your UI to life.