AllenDang / giu

Cross platform rapid GUI framework for golang based on Dear ImGui.
MIT License
2.37k stars 135 forks source link

How do I switch tabItems in code #284

Closed yibana closed 3 years ago

yibana commented 3 years ago

How do I switch tabItems in code

AllenDang commented 3 years ago

TabItem().IsOpen(&bool). Try set the bool.

yibana commented 3 years ago

@AllenDang I want the selected state, not open If I use isopen, when it's false I won't see this TabItem

yibana commented 3 years ago

I tried to write it like this, but it doesn't work

package main

import (
    g "github.com/AllenDang/giu"
)
var tab1Flag g.TabItemFlags
var tab2Flag g.TabItemFlags

func loop() {
    g.SingleWindow().Layout(
        g.TabBar().TabItems(
            g.TabItem("tab1").Flags(tab1Flag).Layout(g.Custom(func() {

                if g.IsItemActive(){
                    tab1Flag = g.TabItemFlagsSetSelected
                    tab2Flag = g.TabItemFlagsNone
                }
            }),g.Label("tab1")),
            g.TabItem("tab2").Flags(tab2Flag).Layout(g.Custom(func() {
                if g.IsItemActive(){
                    tab2Flag = g.TabItemFlagsSetSelected
                    tab2Flag = g.TabItemFlagsNone
                }
            }),g.Button("to tab1").OnClick(func() {
                tab1Flag = g.TabItemFlagsSetSelected
                tab2Flag = g.TabItemFlagsNone
            }))),
    )
}

func main() {

    wnd := g.NewMasterWindow("Set tab", 400, 200, g.MasterWindowFlagsNotResizable)
    wnd.Run(loop)
}
AllenDang commented 3 years ago

Try this

package main

import (
    g "github.com/AllenDang/giu"
)

var (
    t1Flags g.TabItemFlags
    t2Flags g.TabItemFlags
)

func loop() {
    g.SingleWindow().Layout(
        g.Row(
            g.Button("T1").OnClick(func() {
                t1Flags |= g.TabItemFlagsSetSelected
                t2Flags ^= g.TabItemFlagsSetSelected
            }),
            g.Button("T2").OnClick(func() {
                t1Flags ^= g.TabItemFlagsSetSelected
                t2Flags |= g.TabItemFlagsSetSelected
            }),
        ),
        g.TabBar().TabItems(
            g.TabItem("T1").Flags(t1Flags).Layout(
                g.Label("Content for t1"),
            ),
            g.TabItem("T2").Flags(t2Flags).Layout(
                g.Label("Content for t2"),
            ),
        ),
    )
}

func main() {
    wnd := g.NewMasterWindow("Hello world", 400, 200, 0)
    wnd.Run(loop)
}
yibana commented 3 years ago

@AllenDang But then I can't click on the TabItem of the TabBar

AllenDang commented 3 years ago

@yibana With my demo code, I can switch tabitem with both click button and the tabitem itself.

yibana commented 3 years ago

@AllenDang If I click the button to switch first, I can't click the Tab #item to switch #

https://user-images.githubusercontent.com/26332832/130233594-6d39bdf7-21cf-44f8-a24f-b69de6471e98.mp4

AllenDang commented 3 years ago

@yibana Sorry for my misunderstanding. Yes, you are right. If the TabItemFlagsSetSelected is set, click to tab item will not success. This is rather a complex issue than I thought. Currently there is no easy way to set active tab items.

yibana commented 3 years ago

@AllenDang I hope to implement these features in the future

AllenDang commented 3 years ago

@yibana wait, i think it related to auto id stuff. i will check it out later.

AllenDang commented 3 years ago

@yibana Sign... no, I'm wrong. Issue still remains.

yibana commented 3 years ago

@AllenDang It's ok, I've changed the code so I don't need to switch tabItem anymore

gucio321 commented 1 year ago

@AllenDang @yibana I got it. My use case is a bit different - I want to restore tab item selection from config file, but it will work in this case as well. Consider the following code:

                giu.TabBar().TabItems(
                    giu.TabItem(a.translator.Translate("Classes list")).Layout(
                        giu.Custom(func() {
                            if giu.IsItemActive() {
                                a.config.ClassicLayoutTab[0] = true
                                a.config.ClassicLayoutTab[1] = false
                                a.config.ClassicLayoutTab[2] = false
                                a.config.ClassicLayoutTab[3] = false
                            }
                        }),
                        // anything you want
                    ).
                        Flags(a.tabItemSelected(a.config.ClassicLayoutTab[0])),

.config.ClassicLayoutTab is an array with len of tab items count and now take a look at a.tabItemSelected function:

func (a *App) tabItemSelected(isSelected bool) giu.TabItemFlags {
    if isSelected && a.config.isJustStarted {
        a.config.isJustStarted = false
        return giu.TabItemFlagsSetSelected
    }

    return giu.TabItemFlagsNone
}

so if you want to change selection, adjust values in an array and set a.config.justStared to true.

I'm going to re-design this code to make it easier to use, but wanted to share it in this issue first :smile: solution above works for me

gucio321 commented 1 year ago

here is a simple object:

package tabbarstate

import "github.com/AllenDang/giu"

// TabBarState is used to save currently selected tab item.
// Read more in comments for each method.
type TabBarState struct {
    CurrentIndex int
    shouldChange bool
}

// New creates a new TabBarState.
func New() *TabBarState {
    return &TabBarState{
        CurrentIndex: 0,
        shouldChange: true,
    }
}

// GetFlags returns a flag for each TabItem.
// For example for the first tab item use:
// giu.TabItem("my tab item").Flags(t.GetFlags(0)) // or 1 - doesn't matter
func (t *TabBarState) GetFlags(itemIdx int) giu.TabItemFlags {
    if !t.shouldChange || itemIdx != t.CurrentIndex {
        return giu.TabItemFlagsNone
    }

    t.shouldChange = false

    return giu.TabItemFlagsSetSelected
}

// Trigger returns another essential part of this controller.
// Call this IMMEDIATELY after imgui.BeginTabItem (or as a first widget in tab item's Layout.
// It is important to pass here the same number as in GetFlags.
func (t *TabBarState) Trigger(tabItem int) giu.Widget {
    return giu.Custom(func() {
        if giu.IsItemActive() {
            t.CurrentIndex = tabItem
        }
    })
}