mirror of https://github.com/mum4k/termdash.git
Container handles resize correctly.
And making container thread unsafe, thread safety will be implemented at the top.
This commit is contained in:
parent
abdbd82b29
commit
2d4d903f87
|
@ -24,7 +24,6 @@ package container
|
|||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
"sync"
|
||||
|
||||
"github.com/mum4k/termdash/area"
|
||||
"github.com/mum4k/termdash/draw"
|
||||
|
@ -33,7 +32,7 @@ import (
|
|||
|
||||
// Container wraps either sub containers or widgets and positions them on the
|
||||
// terminal.
|
||||
// This is thread-safe and must not be copied.
|
||||
// This is not thread-safe.
|
||||
type Container struct {
|
||||
// parent is the parent container, nil if this is the root container.
|
||||
parent *Container
|
||||
|
@ -52,9 +51,6 @@ type Container struct {
|
|||
// area is the area of the terminal this container has access to.
|
||||
area image.Rectangle
|
||||
|
||||
// mu locks the container while it is being drawn or while it receives input events.
|
||||
mu sync.Mutex
|
||||
|
||||
// opts are the options provided to the container.
|
||||
opts *options
|
||||
}
|
||||
|
@ -157,9 +153,6 @@ func (c *Container) createSecond() *Container {
|
|||
|
||||
// Draw draws this container and all of its sub containers.
|
||||
func (c *Container) Draw() error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
return drawTree(c)
|
||||
}
|
||||
|
||||
|
@ -167,9 +160,6 @@ func (c *Container) Draw() error {
|
|||
// Keyboard events are forwarded to the widget in the currently focused
|
||||
// container, assuming that the widget registered for keyboard events.
|
||||
func (c *Container) Keyboard(k *terminalapi.Keyboard) error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
w := c.focusTracker.active().opts.widget
|
||||
if w == nil || !w.Options().WantKeyboard {
|
||||
return nil
|
||||
|
@ -186,9 +176,6 @@ func (c *Container) Keyboard(k *terminalapi.Keyboard) error {
|
|||
// widget. Only mouse events that fall within the widget's canvas are forwarded
|
||||
// and the coordinates are adjusted relative to the widget's canvas.
|
||||
func (c *Container) Mouse(m *terminalapi.Mouse) error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
c.focusTracker.mouse(m)
|
||||
|
||||
target := pointCont(c, m.Position)
|
||||
|
|
|
@ -30,7 +30,20 @@ import (
|
|||
// drawTree draws this container and all of its sub containers.
|
||||
func drawTree(c *Container) error {
|
||||
var errStr string
|
||||
preOrder(c, &errStr, visitFunc(func(c *Container) error {
|
||||
|
||||
root := rootCont(c)
|
||||
size := root.term.Size()
|
||||
root.area = image.Rect(0, 0, size.X, size.Y)
|
||||
|
||||
preOrder(root, &errStr, visitFunc(func(c *Container) error {
|
||||
first, second := c.split()
|
||||
if c.first != nil {
|
||||
c.first.area = first
|
||||
}
|
||||
|
||||
if c.second != nil {
|
||||
c.second.area = second
|
||||
}
|
||||
return drawCont(c)
|
||||
}))
|
||||
if errStr != "" {
|
||||
|
|
|
@ -386,3 +386,149 @@ func TestDrawWidget(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDrawHandlesTerminalResize(t *testing.T) {
|
||||
termSize := image.Point{60, 10}
|
||||
got, err := faketerm.New(termSize)
|
||||
if err != nil {
|
||||
t.Errorf("faketerm.New => unexpected error: %v", err)
|
||||
}
|
||||
|
||||
cont := New(
|
||||
got,
|
||||
SplitVertical(
|
||||
Left(
|
||||
SplitHorizontal(
|
||||
Top(
|
||||
PlaceWidget(fakewidget.New(widgetapi.Options{})),
|
||||
),
|
||||
Bottom(
|
||||
PlaceWidget(fakewidget.New(widgetapi.Options{})),
|
||||
),
|
||||
),
|
||||
),
|
||||
Right(
|
||||
SplitVertical(
|
||||
Left(
|
||||
PlaceWidget(fakewidget.New(widgetapi.Options{})),
|
||||
),
|
||||
Right(
|
||||
PlaceWidget(fakewidget.New(widgetapi.Options{})),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// The following tests aren't hermetic, they all access the same container
|
||||
// and fake terminal in order to retain state between resizes.
|
||||
tests := []struct {
|
||||
desc string
|
||||
resize *image.Point // if not nil, the fake terminal will be resized.
|
||||
want func(size image.Point) *faketerm.Terminal
|
||||
}{
|
||||
{
|
||||
desc: "handles the initial draw request",
|
||||
want: func(size image.Point) *faketerm.Terminal {
|
||||
ft := faketerm.MustNew(size)
|
||||
|
||||
fakewidget.MustDraw(
|
||||
ft,
|
||||
testcanvas.MustNew(image.Rect(0, 0, 30, 5)),
|
||||
widgetapi.Options{},
|
||||
)
|
||||
fakewidget.MustDraw(
|
||||
ft,
|
||||
testcanvas.MustNew(image.Rect(0, 5, 30, 10)),
|
||||
widgetapi.Options{},
|
||||
)
|
||||
fakewidget.MustDraw(
|
||||
ft,
|
||||
testcanvas.MustNew(image.Rect(30, 0, 45, 10)),
|
||||
widgetapi.Options{},
|
||||
)
|
||||
fakewidget.MustDraw(
|
||||
ft,
|
||||
testcanvas.MustNew(image.Rect(45, 0, 60, 10)),
|
||||
widgetapi.Options{},
|
||||
)
|
||||
return ft
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "increase in size",
|
||||
resize: &image.Point{80, 10},
|
||||
want: func(size image.Point) *faketerm.Terminal {
|
||||
ft := faketerm.MustNew(size)
|
||||
|
||||
fakewidget.MustDraw(
|
||||
ft,
|
||||
testcanvas.MustNew(image.Rect(0, 0, 40, 5)),
|
||||
widgetapi.Options{},
|
||||
)
|
||||
fakewidget.MustDraw(
|
||||
ft,
|
||||
testcanvas.MustNew(image.Rect(0, 5, 40, 10)),
|
||||
widgetapi.Options{},
|
||||
)
|
||||
fakewidget.MustDraw(
|
||||
ft,
|
||||
testcanvas.MustNew(image.Rect(40, 0, 60, 10)),
|
||||
widgetapi.Options{},
|
||||
)
|
||||
fakewidget.MustDraw(
|
||||
ft,
|
||||
testcanvas.MustNew(image.Rect(60, 0, 80, 10)),
|
||||
widgetapi.Options{},
|
||||
)
|
||||
return ft
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "decrease in size",
|
||||
resize: &image.Point{50, 10},
|
||||
want: func(size image.Point) *faketerm.Terminal {
|
||||
ft := faketerm.MustNew(size)
|
||||
|
||||
fakewidget.MustDraw(
|
||||
ft,
|
||||
testcanvas.MustNew(image.Rect(0, 0, 25, 5)),
|
||||
widgetapi.Options{},
|
||||
)
|
||||
fakewidget.MustDraw(
|
||||
ft,
|
||||
testcanvas.MustNew(image.Rect(0, 5, 25, 10)),
|
||||
widgetapi.Options{},
|
||||
)
|
||||
fakewidget.MustDraw(
|
||||
ft,
|
||||
testcanvas.MustNew(image.Rect(25, 0, 37, 10)),
|
||||
widgetapi.Options{},
|
||||
)
|
||||
fakewidget.MustDraw(
|
||||
ft,
|
||||
testcanvas.MustNew(image.Rect(37, 0, 50, 10)),
|
||||
widgetapi.Options{},
|
||||
)
|
||||
return ft
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
if tc.resize != nil {
|
||||
if err := got.Resize(*tc.resize); err != nil {
|
||||
t.Fatalf("Resize => unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
if err := cont.Draw(); err != nil {
|
||||
t.Fatalf("Draw => unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if diff := faketerm.Diff(tc.want(got.Size()), got); diff != "" {
|
||||
t.Errorf("Draw => %v", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue