Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bug] SplitLayout causes the text input to lose focus on adding/removing rows to a table widget #717

Open
WinPooh32 opened this issue Oct 16, 2023 · 13 comments
Assignees
Labels
bug Something isn't working

Comments

@WinPooh32
Copy link

What happend?

I'm trying to filter table rows by a user-typed text. The text input widget loses focus when table rows are changed. It happens only when the table is a sub-widget of the SplitLayout. (v0.7.0)

At the master version it loses focus only when table is removed from the layout (table without rows causes panic on any version).

Code example

main.go
package main

import (
	"fmt"
	"strings"

	g "github.com/AllenDang/giu"
)

var (
	names  []string
	filter string
)

func buildTable() g.Widget {
	rows := make([]*g.TableRowWidget, 0, len(names))

	for i, name := range names {
		if filter != "" && !strings.Contains(name, filter) {
			continue
		}

		row := g.TableRow(
			g.Label(fmt.Sprintf("%d", i)),
			g.Label(name),
		)

		rows = append(rows, row)
	}

	if len(rows) == 0 {
		return nil
	}

	return g.Table().FastMode(false).Rows(rows...)
}

var sashPos float32 = 100

func loop() {
	g.SingleWindow().Layout(
		g.SplitLayout(
			g.DirectionHorizontal,
			&sashPos,
			g.Label("Note: FastTable only works if all rows have same height"),
			g.Layout{
				g.InputText(&filter).Hint("Filter..."),
				buildTable(),
			},
		),
	)
}

func main() {
	names = make([]string, 10000)
	for i := range names {
		names[i] = fmt.Sprintf("Huge list name demo 范例 %d", i)
	}

	wnd := g.NewMasterWindow("Huge list demo", 800, 600, 0)
	wnd.Run(loop)
}

To Reproduce

  1. Run my demo
  2. Type qwerty to the text input form.

Version

(latest)

OS

Ubuntu 20.04.6

@WinPooh32 WinPooh32 added the bug Something isn't working label Oct 16, 2023
@gucio321
Copy link
Collaborator

@WinPooh32 try to set ID of your input text manually

@WinPooh32
Copy link
Author

@WinPooh32 try to set ID of your input text manually

g.InputText(&filter).Hint("Filter...").Label("##custom_id")

Changes nothing.

@AllenDang
Copy link
Owner

@WinPooh32 use ID(...) instead of Label(...)

@WinPooh32
Copy link
Author

@WinPooh32 use ID(...) instead of Label(...)

There is no ID method at the InputText.
I set ID() for table and it helps. But it panics if there are no rows at the table.

My code:

	if len(rows) == 0 {
		return g.Table().Rows(g.TableRow(g.Dummy(0, 0))).ID("table1234")
	}

	return g.Table()..Rows(rows...).ID("table1234")

@WinPooh32
Copy link
Author

But when rows are filled by buttons, focus is lost on every table change. IDs do not help:

main.go
package main

import (
	"fmt"
	"strings"

	g "github.com/AllenDang/giu"
	"github.com/AllenDang/imgui-go"
)

var (
	names  []string
	filter string
)

func buildTable() g.Widget {
	rows := make([]*g.TableRowWidget, 0, len(names))

	for i, name := range names {
		if filter != "" && !strings.Contains(name, filter) {
			continue
		}

		row := g.TableRow(
			g.Button(fmt.Sprintf("%d %s", i, name)),
		)

		rows = append(rows, row)
	}

	if len(rows) == 0 {
		return g.Table().Rows(g.TableRow(g.Dummy(0, 0))).ID("table1234")
	}

	return g.Table().Rows(rows...).ID("table1234")
}

var sashPos float32 = 100

func loop() {
	g.SingleWindow().Layout(
		g.SplitLayout(
			g.DirectionHorizontal,
			&sashPos,
			g.Label("Note: FastTable only works if all rows have same height"),
			g.Layout{
				g.InputText(&filter).Hint("Filter..."),
				buildTable(),
			},
		).ID("123456789"),
	)
}

func main() {
	names = make([]string, 10000)
	for i := range names {
		names[i] = fmt.Sprintf("Huge list name demo 范例 %d", i)
	}

	wnd := g.NewMasterWindow("Huge list demo", 800, 600, 0)

	imgui.StyleColorsLight()

	wnd.Run(loop)
}

@AllenDang
Copy link
Owner

because your ID is the same for all rows and buttons, make them unique by add index into ID.

@WinPooh32
Copy link
Author

because your ID is the same for all rows and buttons, make them unique by add index into ID.

I have set ID only for buttons (rows have not method ID(...)), but nothing changed:

g.Button("").ID(fmt.Sprintf("%d", i)),

full example:

main.go
package main

import (
	"fmt"
	"strings"

	g "github.com/AllenDang/giu"
	"github.com/AllenDang/imgui-go"
)

var (
	names  []string
	filter string
)

func buildTable() g.Widget {
	rows := make([]*g.TableRowWidget, 0, len(names))

	for i, name := range names {
		if filter != "" && !strings.Contains(name, filter) {
			continue
		}

		row := g.TableRow(
			g.Button("").ID(fmt.Sprintf("%d", i)),
		)

		rows = append(rows, row)
	}

	if len(rows) == 0 {
		return g.Table().Rows(g.TableRow(g.Button("").ID(fmt.Sprintf("%d", -1)))).ID("table1")
	}

	return g.Table().Rows(rows...).ID("table1")
}

var sashPos float32 = 100

func loop() {
	g.SingleWindow().Layout(
		g.SplitLayout(
			g.DirectionHorizontal,
			&sashPos,
			g.Label("Note: FastTable only works if all rows have same height"),
			g.Layout{
				g.InputText(&filter).Hint("Filter..."),
				buildTable(),
			},
		).ID("123456789"),
	)
}

func main() {
	names = make([]string, 10000)
	for i := range names {
		names[i] = fmt.Sprintf("Huge list name demo 范例 %d", i)
	}

	wnd := g.NewMasterWindow("Huge list demo", 800, 600, 0)

	imgui.StyleColorsLight()

	wnd.Run(loop)
}

@gucio321
Copy link
Collaborator

well strange... SO its not problem of ID

@gucio321
Copy link
Collaborator

my research:

  • It happens specificly with SplitLayout
  • It happens only for buttons

@gucio321
Copy link
Collaborator

A minimalistic reproduction code:

package main

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

var (
	filter  string
	sashPos float32 = 100
)

func buildTable() g.Widget {
	if filter != "" {
		return g.Layout{}
	}

	return g.Button("btn")
}

func loop() {
	g.SingleWindow().Layout(
		g.SplitLayout(
			g.DirectionHorizontal,
			&sashPos,
			g.Layout{},
			g.Layout{
				g.InputText(&filter).Hint("Filter..."),
				// If I put it here, it works?
				// giu.Custom(func() {
				// 	buildTable().Build()
				// })
				buildTable(),
			},
		),
	)
}

func main() {
	wnd := g.NewMasterWindow("Huge list demo", 800, 600, 0)

	wnd.Run(loop)
}

also @WinPooh32 if you put your table builder in giu.Custom it starts to work (no idea why...)

@gucio321
Copy link
Collaborator

haha I've just lookad at this code and got the answer - I'll write it here after a qucik play with dlv

@gucio321 gucio321 self-assigned this Dec 19, 2023
@gucio321
Copy link
Collaborator

ok, nevermind, I have no idea why it doesn't wokr...

@Orygin
Copy link

Orygin commented Dec 26, 2023

Hello, I am also experiencing this issue, but in a slight variation.
TabBars loose track of the active tab when inside a splitlayout when the layout is modified.
A variation of your reproducing code as such triggers the issue:

func loop() {
	g.SingleWindow().Layout(
		g.SplitLayout(
			g.DirectionHorizontal,
			&sashPos,
			g.Layout{},
			g.Layout{
				g.TabBar().TabItems(
					g.TabItem("A"),
					g.TabItem("B").Layout(
						g.InputText(&filter).Hint("Filter..."),
						buildTable(),
					),
				),
			},
		),
	)
}

The problem also goes away when using Custom().
I had this issue on v0.6.2 and v0.7.0 as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants