summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--cmd/aerc/main.go71
-rw-r--r--lib/ui/fill.go27
-rw-r--r--lib/ui/interactive.go5
-rw-r--r--lib/ui/ui.go19
-rw-r--r--widgets/aerc.go91
5 files changed, 130 insertions, 83 deletions
diff --git a/cmd/aerc/main.go b/cmd/aerc/main.go
index 009b5eb..3030ee9 100644
--- a/cmd/aerc/main.go
+++ b/cmd/aerc/main.go
@@ -8,31 +8,12 @@ import (
 	"time"
 
 	"github.com/mattn/go-isatty"
-	tb "github.com/nsf/termbox-go"
 
 	"git.sr.ht/~sircmpwn/aerc2/config"
 	libui "git.sr.ht/~sircmpwn/aerc2/lib/ui"
 	"git.sr.ht/~sircmpwn/aerc2/widgets"
 )
 
-type fill rune
-
-func (f fill) Draw(ctx *libui.Context) {
-	for x := 0; x < ctx.Width(); x += 1 {
-		for y := 0; y < ctx.Height(); y += 1 {
-			ctx.SetCell(x, y, rune(f), tb.ColorDefault, tb.ColorDefault)
-		}
-	}
-}
-
-func (f fill) OnInvalidate(callback func(d libui.Drawable)) {
-	// no-op
-}
-
-func (f fill) Invalidate() {
-	// no-op
-}
-
 func main() {
 	var logOut io.Writer
 	var logger *log.Logger
@@ -49,62 +30,12 @@ func main() {
 		panic(err)
 	}
 
-	tabs := libui.NewTabs()
-	tabs.Add(fill('★'), "白い星")
-	tabs.Add(fill('☆'), "empty stars")
-
-	grid := libui.NewGrid().Rows([]libui.GridSpec{
-		libui.GridSpec{libui.SIZE_EXACT, 1},
-		libui.GridSpec{libui.SIZE_WEIGHT, 1},
-		libui.GridSpec{libui.SIZE_EXACT, 1},
-	}).Columns([]libui.GridSpec{
-		libui.GridSpec{libui.SIZE_EXACT, 20},
-		libui.GridSpec{libui.SIZE_WEIGHT, 1},
-	})
-
-	// TODO: move sidebar into tab content, probably
-	grid.AddChild(libui.NewText("aerc").
-		Strategy(libui.TEXT_CENTER).
-		Color(tb.ColorBlack, tb.ColorWhite))
-	// sidebar placeholder:
-	grid.AddChild(libui.NewBordered(
-		fill('.'), libui.BORDER_RIGHT)).At(1, 0).Span(2, 1)
-	grid.AddChild(tabs.TabStrip).At(0, 1)
-	grid.AddChild(tabs.TabContent).At(1, 1)
-
-	statusbar := libui.NewStack()
-	grid.AddChild(statusbar).At(2, 1)
-
-	statusline := widgets.NewStatusLine()
-	statusline.Push("test status!", 6*time.Second)
-	statusline.Push("test error!", 3*time.Second).
-		Color(tb.ColorRed, tb.ColorBlack)
-	statusbar.Push(statusline)
-
-	exline := widgets.NewExLine(func(command string) {
-		statusbar.Pop()
-		logger.Printf("TODO: execute command: %s\n", command)
-	}, func() {
-		statusbar.Pop()
-	})
-	statusbar.Push(exline)
-
-	ui, err := libui.Initialize(conf, grid)
+	ui, err := libui.Initialize(conf, widgets.NewAerc(logger))
 	if err != nil {
 		panic(err)
 	}
 	defer ui.Close()
 
-	// TODO: this should be a stack
-	ui.AddInteractive(exline)
-
-	go (func() {
-		for {
-			time.Sleep(1 * time.Second)
-			tabs.Select((tabs.Selected + 1) % 2)
-		}
-	})()
-
 	for !ui.Exit {
 		if !ui.Tick() {
 			// ~60 FPS
diff --git a/lib/ui/fill.go b/lib/ui/fill.go
new file mode 100644
index 0000000..3c6f0a5
--- /dev/null
+++ b/lib/ui/fill.go
@@ -0,0 +1,27 @@
+package ui
+
+import (
+	tb "github.com/nsf/termbox-go"
+)
+
+type Fill rune
+
+func NewFill(f rune) Fill {
+	return Fill(f)
+}
+
+func (f Fill) Draw(ctx *Context) {
+	for x := 0; x < ctx.Width(); x += 1 {
+		for y := 0; y < ctx.Height(); y += 1 {
+			ctx.SetCell(x, y, rune(f), tb.ColorDefault, tb.ColorDefault)
+		}
+	}
+}
+
+func (f Fill) OnInvalidate(callback func(d Drawable)) {
+	// no-op
+}
+
+func (f Fill) Invalidate() {
+	// no-op
+}
diff --git a/lib/ui/interactive.go b/lib/ui/interactive.go
index 8bdf592..efab828 100644
--- a/lib/ui/interactive.go
+++ b/lib/ui/interactive.go
@@ -13,3 +13,8 @@ type Simulator interface {
 	// Queues up the given input events for simulation
 	Simulate(events []tb.Event)
 }
+
+type DrawableInteractive interface {
+	Drawable
+	Interactive
+}
diff --git a/lib/ui/ui.go b/lib/ui/ui.go
index 9ea037c..e9b4e9b 100644
--- a/lib/ui/ui.go
+++ b/lib/ui/ui.go
@@ -8,16 +8,16 @@ import (
 
 type UI struct {
 	Exit    bool
-	Content Drawable
+	Content DrawableInteractive
 	ctx     *Context
 
-	interactive []Interactive
-
 	tbEvents      chan tb.Event
 	invalidations chan interface{}
 }
 
-func Initialize(conf *config.AercConfig, content Drawable) (*UI, error) {
+func Initialize(conf *config.AercConfig,
+	content DrawableInteractive) (*UI, error) {
+
 	if err := tb.Init(); err != nil {
 		return nil, err
 	}
@@ -52,6 +52,7 @@ func (state *UI) Tick() bool {
 	case event := <-state.tbEvents:
 		switch event.Type {
 		case tb.EventKey:
+			// TODO: temporary
 			if event.Key == tb.KeyEsc {
 				state.Exit = true
 			}
@@ -60,11 +61,7 @@ func (state *UI) Tick() bool {
 			state.ctx = NewContext(event.Width, event.Height)
 			state.Content.Invalidate()
 		}
-		if state.interactive != nil {
-			for _, i := range state.interactive {
-				i.Event(event)
-			}
-		}
+		state.Content.Event(event)
 	case <-state.invalidations:
 		state.Content.Draw(state.ctx)
 		tb.Flush()
@@ -73,7 +70,3 @@ func (state *UI) Tick() bool {
 	}
 	return true
 }
-
-func (state *UI) AddInteractive(i Interactive) {
-	state.interactive = append(state.interactive, i)
-}
diff --git a/widgets/aerc.go b/widgets/aerc.go
new file mode 100644
index 0000000..2168e61
--- /dev/null
+++ b/widgets/aerc.go
@@ -0,0 +1,91 @@
+package widgets
+
+import (
+	"log"
+	"time"
+
+	tb "github.com/nsf/termbox-go"
+
+	libui "git.sr.ht/~sircmpwn/aerc2/lib/ui"
+)
+
+type Aerc struct {
+	grid        *libui.Grid
+	tabs        *libui.Tabs
+	statusbar   *libui.Stack
+	statusline  *StatusLine
+	interactive libui.Interactive
+}
+
+func NewAerc(logger *log.Logger) *Aerc {
+	tabs := libui.NewTabs()
+	tabs.Add(libui.NewFill('★'), "白い星")
+	tabs.Add(libui.NewFill('☆'), "empty stars")
+
+	grid := libui.NewGrid().Rows([]libui.GridSpec{
+		libui.GridSpec{libui.SIZE_EXACT, 1},
+		libui.GridSpec{libui.SIZE_WEIGHT, 1},
+		libui.GridSpec{libui.SIZE_EXACT, 1},
+	}).Columns([]libui.GridSpec{
+		libui.GridSpec{libui.SIZE_EXACT, 20},
+		libui.GridSpec{libui.SIZE_WEIGHT, 1},
+	})
+
+	// TODO: move sidebar into tab content, probably
+	grid.AddChild(libui.NewText("aerc").
+		Strategy(libui.TEXT_CENTER).
+		Color(tb.ColorBlack, tb.ColorWhite))
+	// sidebar placeholder:
+	grid.AddChild(libui.NewBordered(
+		libui.NewFill('.'), libui.BORDER_RIGHT)).At(1, 0).Span(2, 1)
+	grid.AddChild(tabs.TabStrip).At(0, 1)
+	grid.AddChild(tabs.TabContent).At(1, 1)
+
+	statusbar := libui.NewStack()
+	grid.AddChild(statusbar).At(2, 1)
+
+	statusline := NewStatusLine()
+	statusline.Push("test status!", 6 * time.Second)
+	statusline.Push("test error!", 3 * time.Second).
+		Color(tb.ColorRed, tb.ColorBlack)
+	statusbar.Push(statusline)
+
+	exline := NewExLine(func(command string) {
+		statusbar.Pop()
+		logger.Printf("TODO: execute command: %s\n", command)
+	}, func() {
+		statusbar.Pop()
+	})
+	statusbar.Push(exline)
+
+	go (func() {
+		for {
+			time.Sleep(1 * time.Second)
+			tabs.Select((tabs.Selected + 1) % 2)
+		}
+	})()
+
+	return &Aerc{
+		grid:        grid,
+		interactive: exline,
+		statusbar:   statusbar,
+		statusline:  statusline,
+		tabs:        tabs,
+	}
+}
+
+func (aerc *Aerc) OnInvalidate(onInvalidate func(d libui.Drawable)) {
+	aerc.grid.OnInvalidate(onInvalidate)
+}
+
+func (aerc *Aerc) Invalidate() {
+	aerc.grid.Invalidate()
+}
+
+func (aerc *Aerc) Draw(ctx *libui.Context) {
+	aerc.grid.Draw(ctx)
+}
+
+func (aerc *Aerc) Event(event tb.Event) bool {
+	return aerc.interactive.Event(event)
+}