rivo / tview

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

border color doesn't seem to work for Modal primitive #877

Closed justmeandopensource closed 1 year ago

justmeandopensource commented 1 year ago

Hi, First of all thanks for this wonderful library. I am trying to show a Modal dialog with the specified border color.

modal := tview.NewModal()
modal.SetText("Delete the transaction?")
modal.AddButtons([]string{"Yes", "No"})
modal.SetBackgroundColor(tcell.Color235)
modal.SetBorder(true)
modal.SetBorderColor(tview.Styles.SecondaryTextColor)

But the border is always white. It works for other primitives though.

table := tview.Table()
table.SetBorderColor(tview.Styles.SecondaryTextColor)

It could be me not understanding the library better. Could someone please share some light on this? Thanks

digitallyserviced commented 1 year ago

@justmeandopensource You are using a primitive that makes the idea of a Modal easy to use without manually creating the primitive structure that you could do yourself. While it does offer a Modal type of dialog, it is not mean to be super-all-encompassing. Especially because you can make your own/refactor/duplicate primitive which gives you all the Modal stuff and more control. It is a simple class/primitive to begin with, all it does is wrap/helper method the views needed.

Below is the NewModal function and you can see it creates a non-public frame that you cannot control or modify.

The reason you see the white border is because of the frame that a Modal uses.

Your best bet is the actually make a copy of the whole Modal file, and rename/refactor it to be YourModal with possibly public properties for the frame, or getter/setter methods to set/update/get at what would allow you to modify those styles/attributes.

func NewModal() *Modal {
    m := &Modal{
        Box:       NewBox(),
        textColor: Styles.PrimaryTextColor,
    }
    m.form = NewForm().
        SetButtonsAlign(AlignCenter).
        SetButtonBackgroundColor(Styles.PrimitiveBackgroundColor).
        SetButtonTextColor(Styles.PrimaryTextColor)
    m.form.SetBackgroundColor(Styles.ContrastBackgroundColor).SetBorderPadding(0, 0, 0, 0)
    m.form.SetCancelFunc(func() {
        if m.done != nil {
            m.done(-1, "")
        }
    })
    m.frame = NewFrame(m.form).SetBorders(0, 0, 1, 0, 0, 0)
    m.frame.SetBorder(true).
        SetBackgroundColor(Styles.ContrastBackgroundColor).
        SetBorderPadding(1, 1, 1, 1)
    return m
}

Just make your own Modal primitive basically using a 1:1 of the original, and hack in your own styling/theming methods.

digitallyserviced commented 1 year ago

Also taken from the wiki modal page. Here is a very simple grid that centers itself and you can put your own primitivs/views into.

@justmeandopensource

The same effect can be achieved by using the Grid class instead of Flex:

// Returns a new primitive which puts the provided primitive in the center and
// sets its size to the given width and height.
modal := func(p tview.Primitive, width, height int) tview.Primitive {
    return tview.NewGrid().
        SetColumns(0, width, 0).
        SetRows(0, height, 0).
        AddItem(p, 1, 1, 1, 1, 0, 0, true)
}

See also: https://pkg.go.dev/github.com/rivo/tview#Modal

justmeandopensource commented 1 year ago

@digitallyserviced Thanks for the clarification. It now makes sense.