1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
// Copyright 2019-2022 Graham Clark. All rights reserved. Use of this source code
// is governed by the MIT license that can be found in the LICENSE file.
// Package boxadapter provides a widget that will allow a box widget to be used
// in a flow context. Based on urwid's BoxAdapter - http://urwid.org/reference/widget.html#boxadapter.
package boxadapter
import (
"fmt"
"github.com/gcla/gowid"
tcell "github.com/gdamore/tcell/v2"
)
//======================================================================
type Widget struct {
gowid.IWidget
rows int
*gowid.Callbacks
gowid.SubWidgetCallbacks
}
type IBoxAdapter interface {
Rows() int
}
type IBoxAdapterWidget interface {
gowid.ICompositeWidget
IBoxAdapter
}
func New(inner gowid.IWidget, rows int) *Widget {
res := &Widget{
IWidget: inner,
rows: rows,
}
res.SubWidgetCallbacks = gowid.SubWidgetCallbacks{CB: &res.Callbacks}
var _ gowid.IWidget = res
var _ gowid.IComposite = res
var _ IBoxAdapter = res
return res
}
func (w *Widget) String() string {
return fmt.Sprintf("boxadapter[%v]", w.SubWidget())
}
func (w *Widget) SubWidget() gowid.IWidget {
return w.IWidget
}
func (w *Widget) SetSubWidget(wi gowid.IWidget, app gowid.IApp) {
w.IWidget = wi
gowid.RunWidgetCallbacks(w, gowid.SubWidgetCB{}, app, w)
}
func (w *Widget) Rows() int {
return w.rows
}
func (w *Widget) SetRows(rows int, app gowid.IApp) {
w.rows = rows
}
func (w *Widget) RenderSize(size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) gowid.IRenderBox {
return RenderSize(w, size, focus, app)
}
func (w *Widget) Render(size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) gowid.ICanvas {
return Render(w, size, focus, app)
}
func (w *Widget) SubWidgetSize(size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) gowid.IRenderSize {
return SubWidgetSize(w, size, focus, app)
}
func (w *Widget) UserInput(ev interface{}, size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) bool {
return UserInput(w, ev, size, focus, app)
}
//======================================================================
// SubWidgetSize is the same as RenderSize for this widget - the inner widget will
// be rendered as a box with the specified number of columns and the widget's
// set number of rows.
func SubWidgetSize(w IBoxAdapter, size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) gowid.IRenderSize {
return RenderSize(w, size, focus, app)
}
func RenderSize(w IBoxAdapter, size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) gowid.IRenderBox {
switch sz := size.(type) {
case gowid.IRenderFlowWith:
return gowid.RenderBox{
C: sz.FlowColumns(),
R: w.Rows(),
}
default:
panic(gowid.WidgetSizeError{Widget: w, Size: size, Required: "gowid.IRenderFlow"})
}
}
func Render(w IBoxAdapterWidget, size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) gowid.ICanvas {
rsize := RenderSize(w, size, focus, app)
res := w.SubWidget().Render(rsize, focus, app)
return res
}
// Ensure that a valid mouse interaction with a flow widget will result in a
// mouse interaction with the subwidget
func UserInput(w IBoxAdapterWidget, ev interface{}, size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) bool {
if _, ok := size.(gowid.IRenderFlowWith); !ok {
panic(gowid.WidgetSizeError{Widget: w, Size: size, Required: "gowid.IRenderFlow"})
}
box := RenderSize(w, size, focus, app)
if evm, ok := ev.(*tcell.EventMouse); ok {
_, my := evm.Position()
if my < box.BoxRows() && my >= 0 {
return gowid.UserInputIfSelectable(w.SubWidget(), ev, box, focus, app)
}
} else {
return gowid.UserInputIfSelectable(w.SubWidget(), ev, box, focus, app)
}
return false
}
//======================================================================
// Local Variables:
// mode: Go
// fill-column: 110
// End:
|