package tview import ( "github.com/gdamore/tcell" ) // Modal is a centered message window used to inform the user or prompt them // for an immediate decision. It needs to have at least one button (added via // AddButtons()) or it will never disappear. type Modal struct { *Frame // The form embedded in the modal's frame. form *Form // The message text (original, not word-wrapped). text string // The text color. textColor tcell.Color // The optional callback for when the user clicked one of the buttons. It // receives the index of the clicked button and the button's label. done func(buttonIndex int, buttonLabel string) } // NewModal returns a new modal message window. func NewModal() *Modal { m := &Modal{ textColor: tcell.ColorWhite, } m.form = NewForm(). SetButtonsAlign(AlignCenter). SetButtonBackgroundColor(tcell.ColorBlack). SetButtonTextColor(tcell.ColorWhite) m.form.SetBackgroundColor(tcell.ColorBlue).SetBorderPadding(0, 0, 0, 0) m.Frame = NewFrame(m.form) m.Box.SetBorder(true).SetBackgroundColor(tcell.ColorBlue) return m } // SetTextColor sets the color of the message text. func (m *Modal) SetTextColor(color tcell.Color) *Modal { m.textColor = color return m } // SetDoneFunc sets a handler which is called when one of the buttons was // pressed. It receives the index of the button as well as its label text. The // handler is also called when the user presses the Escape key. The index will // then be negative and the label text an emptry string. func (m *Modal) SetDoneFunc(handler func(buttonIndex int, buttonLabel string)) *Modal { m.done = handler return m } // SetText sets the message text of the window. The text may contain line // breaks. Note that words are wrapped, too, based on the final size of the // window. func (m *Modal) SetText(text string) *Modal { m.text = text return m } // AddButtons adds buttons to the window. There must be at least one button and // a "done" handler so the window can be closed again. func (m *Modal) AddButtons(labels []string) *Modal { for index, label := range labels { func(i int, l string) { m.form.AddButton(label, func() { if m.done != nil { m.done(i, l) } }) }(index, label) } return m } // Focus is called when this primitive receives focus. func (m *Modal) Focus(delegate func(p Primitive)) { delegate(m.form) } // HasFocus returns whether or not this primitive has focus. func (m *Modal) HasFocus() bool { return m.form.HasFocus() } // Draw draws this primitive onto the screen. func (m *Modal) Draw(screen tcell.Screen) { // Calculate the width of this modal. buttonsWidth := 0 for _, button := range m.form.buttons { buttonsWidth += len([]rune(button.label)) + 4 + 2 } buttonsWidth -= 2 screenWidth, screenHeight := screen.Size() width := screenWidth / 3 if width < buttonsWidth { width = buttonsWidth } // width is now without the box border. // Reset the text and find out how wide it is. m.Frame.ClearText() lines := WordWrap(m.text, width) for _, line := range lines { m.Frame.AddText(line, true, AlignCenter, m.textColor) } // Set the modal's position and size. height := len(lines) + 6 x := (screenWidth - width) / 2 y := (screenHeight - height) / 2 m.SetRect(x, y, width, height) // Draw the frame. m.Frame.Draw(screen) }