Skip to content

Tabs.md

cfloutier edited this page Apr 27, 2024 · 7 revisions

Tabs

What is inside the K2Tabs

Tabs has been rewritten 4 times ! it was the first element I worked on and I was struggling with UI Toolkit logic and behavior. The solutions thats were mainly used didn't satisfied what I wanted to have to be easy to configure and maintains.

The tabs in K2D2 have quite a complexity because each one holds a pilot that can be visible or not and active or not. each page have to show this 2 informations and dealing with only css to do that made the problem more complex.

I finally had to separate the work into many differents classes :

  • TabbedPage : maintains the a global logic. It creates TabButton depending on TabPages found in it's content.
  • TabPage : is a VisualElement used to identiy a page and create it's associated TabButton. Thats where we can edit this in the UIBuilder
  • TabButton : created by the is TabbedPage in the TabsBar
  • TabsBar : have the responsability of showing and hiding pages and changing buttons look on user inputs

K2Page

And finally the Mod pages could overload the K2Page base class. This is not a visual element as it should be linked more with the plugin logic.

This class can be used to have a different behavior it the page is shown or not to avoid computing things that is not shown to the user.

this init of the ui should be done by overiding the virtual bool onInit()

and if update is needed on each frame you can overide the virtual bool onUpdateUI()

The K2Page also check the presence in the Xml Tree of children named "page" and "content" to show a settings page when the setting button is clicked. It is a behavior that I needed for K2D2 mod but it is fully optional. the Tabs System can be used without that.

simple example

    public class TimerPanel: K2Page
    {
        public TimerPanel()
        {
            // this code is used to find the TapPage in the Xml tree
            code = "timer";
        }

        Label my_label;

        public override bool onInit()
        {
            // find the element in the tree
            my_label = panel.Q<Label>("timer_label");     
            return true;
        }

        public override bool onUpdateUI()
        {
            // called on each frame when the UI is visible 
            if (!base.onUpdateUI())
                // the base class return false if the UI is hidden
                return false;

            Debug.Log("calling update");
            my_label.text = $"time is {Time.time:n1} s";

            return true;
        }
    }

After 4 attemps I finally found a quite solid logic.

Clone this wiki locally