rivo / tview

Terminal UI library with rich, interactive widgets — written in Golang
MIT License
11.17k stars 574 forks source link

Setting a border on a Flex will hide the children. #831

Closed tcurdt closed 1 year ago

tcurdt commented 1 year ago

I am not sure what I am missing here - but as soon as I set a border the children disappear.

    layoutCol2 := tview.NewFlex().
        SetDirection(tview.FlexRow).
        AddItem(identification, 2, 0, false).
        AddItem(value, 1, 0, false).
        AddItem(details, 6, 0, false).
        AddItem(help, 1, 0, false).
        SetBorder(true)
Screenshot 2023-03-26 at 04 00 06

The same happens when setting a padding.

    layoutCol2 := tview.NewFlex().
        SetDirection(tview.FlexRow).
        AddItem(identification, 2, 0, false).
        AddItem(value, 1, 0, false).
        AddItem(details, 6, 0, false).
        AddItem(help, 1, 0, false).
        SetBorderPadding(1, 1, 1, 1)

Without it looks like this:

    layoutCol2 := tview.NewFlex().
        SetDirection(tview.FlexRow).
        AddItem(identification, 2, 0, false).
        AddItem(value, 1, 0, false).
        AddItem(details, 6, 0, false).
        AddItem(help, 1, 0, false)
Screenshot 2023-03-26 at 04 02 02
tcurdt commented 1 year ago

Interesting. This seems to be related to the builder pattern. This works:

layoutCol2 := tview.NewFlex().
        SetDirection(tview.FlexRow).
        AddItem(identification, 2, 0, false).
        AddItem(value, 1, 0, false).
        AddItem(details, 6, 0, false).
        AddItem(help, 1, 0, false)

layoutCol2.SetBorder(true)
layoutCol2.SetBorderPadding(1, 1, 1, 1)
tcurdt commented 1 year ago

Unfortunately setting a padding reveals an area where I cannot set a background color. Here the left and right padding is just white instead of black.

Screenshot 2023-03-26 at 18 19 30
digitallyserviced commented 1 year ago

@tcurdt What items are you adding to the flex? I have had similar issues because the Frame i was adding would just bail on drawing because it did not have enough room. But that was really only the Frame type widget.

Can you provide more detailed code example? Including the widgets you are adding to the flex? Have you tried a grid?

andreas-habel commented 1 year ago

I have the same issue here with a list:

package main

import (
    "github.com/rivo/tview"
)

func main() {
    app := tview.NewApplication()

    list := tview.NewList().
        AddItem("List item 1", "Some explanatory text", 'a', nil).
        AddItem("Quit", "Press to exit", 'q', func() {
            app.Stop()
        }).
        SetBorder(true)

    box := tview.NewFlex().
        AddItem(list, 0, 1, true)

    if err := app.SetRoot(box, true).Run(); err != nil {
        panic(err)
    }
}

image

//snip

    list := tview.NewList().
        AddItem("List item 1", "Some explanatory text", 'a', nil).
        AddItem("Quit", "Press to exit", 'q', func() {
            app.Stop()
        })

    list.SetBorder(true)

//snip

image

kiyutink commented 1 year ago

Hey folks, .SetBorder returns a *tview.Box for any primitive, because .Border is a method that comes from embedding a *Box into all the other primitives (see example for list).

What's happening is that by calling .Border at the end, the returned value captured in the variable is not a list, but a box. I imagine using this approach is the best bet here

With list that would mean instead of this:

list := tview.NewList().
  AddItem("List item 1", "Some explanatory text", 'a', nil).
  SetBorder(true)

Do this:

list := tview.NewList().
  AddItem("List item 1", "Some explanatory text", 'a', nil)
list.SetBorder(true)
tcurdt commented 1 year ago

The work around is clear. But I think the point is that the API suggest the use of a builder pattern - and that has issues.

rivo commented 1 year ago

@tcurdt True. See also https://github.com/rivo/tview/issues/141#issuecomment-410437784 for some context.

rivo commented 1 year ago

The latest commit clarifies this in the package documentation. It should appear here once that page is updated. Unfortunately, there's no good way to implement this in Go without duplicating a lot of code.

tcurdt commented 1 year ago

I might just drop using the builder all together. Thanks for clarifying this in the docs.

For this https://github.com/rivo/tview/issues/831#issuecomment-1484148541 I should probably open another issue.