Terminal-based user interface toolkit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

162 lines
3.3 KiB

package cview
import (
"sync"
"github.com/gdamore/tcell/v2"
)
// Window is a draggable, resizable frame around a primitive. Windows must be
// added to a WindowManager.
type Window struct {
*Box
primitive Primitive
x, y int
width, height int
fullscreen bool
dragX, dragY int
dragWX, dragWY int
sync.RWMutex
}
// NewWindow returns a new window around the given primitive.
func NewWindow(primitive Primitive) *Window {
w := &Window{
Box: NewBox(),
primitive: primitive,
dragWX: -1,
dragWY: -1,
}
w.Box.focus = w
return w
}
// SetPosition sets the position of the window.
func (w *Window) SetPosition(x, y int) {
w.Lock()
defer w.Unlock()
w.x, w.y = x, y
}
// SetSize sets the size of the window.
func (w *Window) SetSize(width, height int) {
w.Lock()
defer w.Unlock()
w.width, w.height = width, height
}
// SetFullscreen sets the flag indicating whether or not the the window should
// be drawn fullscreen.
func (w *Window) SetFullscreen(fullscreen bool) {
w.Lock()
defer w.Unlock()
w.fullscreen = fullscreen
}
// Focus is called when this primitive receives focus.
func (w *Window) Focus(delegate func(p Primitive)) {
w.Lock()
defer w.Unlock()
w.Box.Focus(delegate)
w.primitive.Focus(delegate)
}
// Blur is called when this primitive loses focus.
func (w *Window) Blur() {
w.Lock()
defer w.Unlock()
w.Box.Blur()
w.primitive.Blur()
}
// HasFocus returns whether or not this primitive has focus.
func (w *Window) HasFocus() bool {
w.RLock()
defer w.RUnlock()
focusable := w.primitive.GetFocusable()
if focusable != nil {
return focusable.HasFocus()
}
return w.Box.HasFocus()
}
// Draw draws this primitive onto the screen.
func (w *Window) Draw(screen tcell.Screen) {
if !w.GetVisible() {
return
}
w.RLock()
defer w.RUnlock()
w.Box.Draw(screen)
x, y, width, height := w.GetInnerRect()
w.primitive.SetRect(x, y, width, height)
w.primitive.Draw(screen)
}
// InputHandler returns the handler for this primitive.
func (w *Window) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) {
return w.primitive.InputHandler()
}
// MouseHandler returns the mouse handler for this primitive.
func (w *Window) MouseHandler() func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
return w.WrapMouseHandler(func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
if !w.InRect(event.Position()) {
return false, nil
}
if action == MouseLeftDown || action == MouseMiddleDown || action == MouseRightDown {
setFocus(w)
}
if action == MouseLeftDown {
x, y, width, height := w.GetRect()
mouseX, mouseY := event.Position()
leftEdge := mouseX == x
rightEdge := mouseX == x+width-1
bottomEdge := mouseY == y+height-1
topEdge := mouseY == y
if mouseY >= y && mouseY <= y+height-1 {
if leftEdge {
w.dragX = -1
} else if rightEdge {
w.dragX = 1
}
}
if mouseX >= x && mouseX <= x+width-1 {
if bottomEdge {
w.dragY = -1
} else if topEdge {
if leftEdge || rightEdge {
w.dragY = 1
} else {
w.dragWX = mouseX - x
w.dragWY = mouseY - y
}
}
}
}
_, capture = w.primitive.MouseHandler()(action, event, setFocus)
return true, capture
})
}