Skip to content

Commit

Permalink
Allow the scrollbar to hide if the data fits in the space available.
Browse files Browse the repository at this point in the history
This is a new option provided to the scrollbar widget. If enabled, the
scrollbar will simply render its data widget if the data available would
fit in the space provided to the scrollbar. Note that this adjusts the
focus path of certain elements in the UI... This is fragile. I really
need a better way e.g. labelling widgets within containers like columns
or piles, rather than using a numeric index.
  • Loading branch information
gcla committed Dec 18, 2019
1 parent 72c0588 commit d299bf4
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 16 deletions.
14 changes: 7 additions & 7 deletions ui/ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -2825,19 +2825,19 @@ func Build() (*gowid.App, error) {
maxViewPath = []interface{}{2, 0} // list, structure or hex - whichever one is selected

mainviewPaths = [][]interface{}{
{2, 0}, // packet list
{4}, // packet structure
{6}, // packet hex
{2}, // packet list
{4}, // packet structure
{6}, // packet hex
}

altview1Paths = [][]interface{}{
{2, 0, 0, 0}, // packet list
{2, 0, 2}, // packet structure
{2, 2}, // packet hex
{2, 0, 0}, // packet list
{2, 0, 2}, // packet structure
{2, 2}, // packet hex
}

altview2Paths = [][]interface{}{
{2, 0, 0}, // packet list
{2, 0}, // packet list
{2, 2, 0}, // packet structure
{2, 2, 2}, // packet hex
}
Expand Down
68 changes: 59 additions & 9 deletions widgets/withscrollbar/withscrollbar.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,52 @@ import (
//======================================================================

type Widget struct {
*columns.Widget
always *columns.Widget // use if scrollbar is to be shown
w IScrollSubWidget
sb *vscroll.Widget
goUpDown int // positive means down
pgUpDown int // positive means down
opt Options
}

var _ gowid.IWidget = (*Widget)(nil)

type Options struct {
HideIfContentFits bool
}

type IScrollValues interface {
ScrollPosition() int
ScrollLength() int
}

type IScrollSubWidget interface {
gowid.IWidget
IScrollValues
// Implemented by widgets that can scroll
type IScrollOneLine interface {
Up(lines int, size gowid.IRenderSize, app gowid.IApp)
Down(lines int, size gowid.IRenderSize, app gowid.IApp)
}

type IScrollOnePage interface {
UpPage(num int, size gowid.IRenderSize, app gowid.IApp)
DownPage(num int, size gowid.IRenderSize, app gowid.IApp)
}

func New(w IScrollSubWidget) *Widget {
type IScrollSubWidget interface {
gowid.IWidget
IScrollValues
IScrollOneLine
IScrollOnePage
}

func New(w IScrollSubWidget, opts ...Options) *Widget {
var opt Options
if len(opts) > 0 {
opt = opts[0]
}

sb := vscroll.NewExt(vscroll.VerticalScrollbarUnicodeRunes)
res := &Widget{
Widget: columns.New([]gowid.IContainerWidget{
always: columns.New([]gowid.IContainerWidget{
&gowid.ContainerWidget{
IWidget: w,
D: gowid.RenderWithWeight{W: 1},
Expand All @@ -55,6 +76,7 @@ func New(w IScrollSubWidget) *Widget {
sb: sb,
goUpDown: 0,
pgUpDown: 0,
opt: opt,
}
sb.OnClickAbove(gowid.MakeWidgetCallback("cb", res.clickUp))
sb.OnClickBelow(gowid.MakeWidgetCallback("cb", res.clickDown))
Expand Down Expand Up @@ -84,7 +106,19 @@ func CalculateMenuRows(vals IScrollValues, rows int, focus gowid.Selector, app g
return vals.ScrollPosition(), 1, vals.ScrollLength() - (vals.ScrollPosition() + 1)
}

func (w *Widget) contentFits(size gowid.IRenderSize) bool {
res := true
if rower, ok := size.(gowid.IRows); ok {
res = (w.w.ScrollLength() <= rower.Rows())
}
return res
}

func (w *Widget) UserInput(ev interface{}, size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) bool {
if w.opt.HideIfContentFits && w.contentFits(size) {
return w.w.UserInput(ev, size, focus, app)
}

box, ok := size.(gowid.IRenderBox)
if !ok {
panic(gowid.WidgetSizeError{Widget: w, Size: size, Required: "gowid.IRenderBox"})
Expand All @@ -96,14 +130,18 @@ func (w *Widget) UserInput(ev interface{}, size gowid.IRenderSize, focus gowid.S
w.sb.Middle = y
w.sb.Bottom = z

res := w.Widget.UserInput(ev, size, focus, app)
res := w.always.UserInput(ev, size, focus, app)
if res {
w.Widget.SetFocus(app, 0)
w.always.SetFocus(app, 0)
}
return res
}

func (w *Widget) Render(size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) gowid.ICanvas {
if w.opt.HideIfContentFits && w.contentFits(size) {
return w.w.Render(size, focus, app)
}

box, ok := size.(gowid.IRenderBox)
if !ok {
panic(gowid.WidgetSizeError{Widget: w, Size: size, Required: "gowid.IRenderBox"})
Expand Down Expand Up @@ -136,11 +174,23 @@ func (w *Widget) Render(size gowid.IRenderSize, focus gowid.Selector, app gowid.
w.sb.Middle = y
w.sb.Bottom = z

canvas := w.Widget.Render(size, focus, app)
canvas := w.always.Render(size, focus, app)

return canvas
}

func (w *Widget) RenderSize(size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) gowid.IRenderBox {
if w.opt.HideIfContentFits && w.contentFits(size) {
return w.w.RenderSize(size, focus, app)
}

return w.always.RenderSize(size, focus, app)
}

func (w *Widget) Selectable() bool {
return w.w.Selectable()
}

//======================================================================
// Local Variables:
// mode: Go
Expand Down
82 changes: 82 additions & 0 deletions widgets/withscrollbar/withscrollbar_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package withscrollbar

import (
"fmt"
"strings"
"testing"

"github.com/gcla/gowid"
"github.com/gcla/gowid/gwtest"
"github.com/gcla/gowid/widgets/button"
"github.com/gcla/gowid/widgets/list"
"github.com/gcla/gowid/widgets/text"
"github.com/stretchr/testify/assert"
)

type scrollingListBox struct {
*list.Widget
}

func (t *scrollingListBox) Up(lines int, size gowid.IRenderSize, app gowid.IApp) {}
func (t *scrollingListBox) Down(lines int, size gowid.IRenderSize, app gowid.IApp) {}
func (t *scrollingListBox) UpPage(num int, size gowid.IRenderSize, app gowid.IApp) {}
func (t *scrollingListBox) DownPage(num int, size gowid.IRenderSize, app gowid.IApp) {}

func (t *scrollingListBox) ScrollLength() int {
return 8
}

func (t *scrollingListBox) ScrollPosition() int {
return 0
}

func Test1(t *testing.T) {
bws := make([]gowid.IWidget, 8)
for i := 0; i < len(bws); i++ {
bws[i] = button.NewBare(text.New(fmt.Sprintf("%03d", i)))
}

walker := list.NewSimpleListWalker(bws)
lbox := &scrollingListBox{Widget: list.New(walker)}
sbox := New(lbox)

canvas1 := sbox.Render(gowid.MakeRenderBox(4, 8), gowid.NotSelected, gwtest.D)
res := strings.Join([]string{
"000▲",
"001█",
"002 ",
"003 ",
"004 ",
"005 ",
"006 ",
"007▼",
}, "\n")
assert.Equal(t, res, canvas1.String())

sbox = New(lbox, Options{
HideIfContentFits: true,
})

canvas1 = sbox.Render(gowid.MakeRenderBox(4, 8), gowid.NotSelected, gwtest.D)
res = strings.Join([]string{
"000 ",
"001 ",
"002 ",
"003 ",
"004 ",
"005 ",
"006 ",
"007 ",
}, "\n")
assert.Equal(t, res, canvas1.String())

canvas1 = sbox.Render(gowid.MakeRenderBox(4, 5), gowid.NotSelected, gwtest.D)
res = strings.Join([]string{
"000▲",
"001█",
"002 ",
"003 ",
"004▼",
}, "\n")
assert.Equal(t, res, canvas1.String())
}

0 comments on commit d299bf4

Please sign in to comment.