From e0a4242e352ddcf0066b58c692cca0a2e8025c12 Mon Sep 17 00:00:00 2001 From: "Roi Martin (@nibble_ds)" Date: Sun, 29 Dec 2013 21:29:29 +0100 Subject: [PATCH] First approach for drawing intersections --- _demos/demo1.go | 48 +++++++++++ gui.go | 211 ++++++++++++++++++++++++++++++++++++++++++++---- view.go | 56 ++----------- 3 files changed, 252 insertions(+), 63 deletions(-) create mode 100644 _demos/demo1.go diff --git a/_demos/demo1.go b/_demos/demo1.go new file mode 100644 index 0000000..1d728a0 --- /dev/null +++ b/_demos/demo1.go @@ -0,0 +1,48 @@ +package main + +import ( + "log" + + "github.com/jroimartin/gocui" +) + +func main() { + var err error + + g := gocui.NewGui() + if err := g.Init(); err != nil { + log.Panicln(err) + } + defer g.Close() + + maxX, maxY := g.Size() + if _, err := g.AddView("v1", -1, -1, 10, 10); err != nil { + log.Panicln(err) + } + if _, err := g.AddView("v2", maxX-10, -1, maxX, 10); err != nil { + log.Panicln(err) + } + if _, err := g.AddView("v3", maxX/2-5, -1, maxX/2+5, 10); err != nil { + log.Panicln(err) + } + if _, err := g.AddView("v4", -1, maxY/2-5, 10, maxY/2+5); err != nil { + log.Panicln(err) + } + if _, err := g.AddView("v5", maxX-10, maxY/2-5, maxX, maxY/2+5); err != nil { + log.Panicln(err) + } + if _, err := g.AddView("v6", -1, maxY-10, 10, maxY); err != nil { + log.Panicln(err) + } + if _, err := g.AddView("v7", maxX-10, maxY-10, maxX, maxY); err != nil { + log.Panicln(err) + } + if _, err := g.AddView("v8", maxX/2-5, maxY-10, maxX/2+5, maxY); err != nil { + log.Panicln(err) + } + + err = g.MainLoop() + if err != nil && err != gocui.ErrorQuit { + log.Panicln(err) + } +} diff --git a/gui.go b/gui.go index 96761c0..01ec8b3 100644 --- a/gui.go +++ b/gui.go @@ -13,8 +13,8 @@ const ( RuneCornerTopRight = '┐' RuneCornerBottomLeft = '└' RuneCornerBottomRight = '┘' - RuneEdgeVertical = '│' - RuneEdgeHorizontal = '─' + RuneSideVertical = '│' + RuneSideHorizontal = '─' RuneIntersection = '┼' RuneIntersectionLeft = '├' RuneIntersectionRight = '┤' @@ -27,9 +27,10 @@ const ( ) type Gui struct { - events chan termbox.Event - views []*View - currentView *View + events chan termbox.Event + views []*View + currentView *View + BgColor, FgColor termbox.Attribute } func NewGui() (g *Gui) { @@ -38,6 +39,8 @@ func NewGui() (g *Gui) { func (g *Gui) Init() (err error) { g.events = make(chan termbox.Event, 20) + g.BgColor = termbox.ColorWhite + g.FgColor = termbox.ColorBlack return termbox.Init() } @@ -55,12 +58,12 @@ func (g *Gui) AddView(name string, x0, y0, x1, y1 int) (v *View, err error) { if x0 < -1 || y0 < -1 || x1 < -1 || y1 < -1 || x0 > maxX || y0 > maxY || x1 > maxX || y1 > maxY || x0 >= x1 || y0 >= y1 { - return nil, errors.New("Invalid position") + return nil, errors.New("invalid points") } - for _, vi := range g.views { - if name == vi.name { - return nil, errors.New("Invalid name") + for _, v := range g.views { + if name == v.Name { + return nil, errors.New("invalid name") } } @@ -104,6 +107,19 @@ func (g *Gui) MainLoop() (err error) { return nil } +func (g *Gui) SetCell(x, y int, ch rune) { + termbox.SetCell(x, y, ch, g.FgColor, g.BgColor) +} + +func (g *Gui) GetCell(x, y int) (ch rune, err error) { + maxX, maxY := termbox.Size() + if x < 0 || y < 0 || x >= maxX || y >= maxY { + return 0, errors.New("invalid point") + } + c := termbox.CellBuffer()[y*maxX+x] + return c.Ch, nil +} + func (g *Gui) consumeevents() (err error) { for { select { @@ -132,23 +148,190 @@ func (g *Gui) handleEvent(ev *termbox.Event) (err error) { func (g *Gui) draw() (err error) { for _, v := range g.views { - if err := v.Draw(); err != nil { + if err := g.drawView(v); err != nil { return err } } return nil +} + +func (g *Gui) drawView(v *View) (err error) { + return nil +} + +func (g *Gui) resize() (err error) { + termbox.Clear(termbox.ColorDefault, termbox.ColorDefault) + if err := g.resizeView(); err != nil { + return err + } + if err := g.drawFrames(); err != nil { + return err + } + if err := g.drawFrameIntersections(); err != nil { + return err + } + return nil } -func (g *Gui) resize() (err error) { - termbox.Clear(termbox.ColorDefault, termbox.ColorDefault) +func (g *Gui) drawFrames() (err error) { + maxX, maxY := termbox.Size() for _, v := range g.views { - if err := v.Resize(); err != nil { - return err + if v.Y0 != -1 { + if v.X0 != -1 { + g.SetCell(v.X0, v.Y0, RuneCornerTopLeft) + } + if v.X1 != maxX { + g.SetCell(v.X1, v.Y0, RuneCornerTopRight) + } + } + if v.Y1 != maxY { + if v.X0 != -1 { + g.SetCell(v.X0, v.Y1, RuneCornerBottomLeft) + } + if v.X1 != maxX { + g.SetCell(v.X1, v.Y1, RuneCornerBottomRight) + } + } + for x := v.X0 + 1; x < v.X1; x++ { + if v.Y0 != -1 { + g.SetCell(x, v.Y0, RuneSideHorizontal) + } + if v.Y1 != maxY { + g.SetCell(x, v.Y1, RuneSideHorizontal) + } + } + for y := v.Y0 + 1; y < v.Y1; y++ { + if v.X0 != -1 { + g.SetCell(v.X0, y, RuneSideVertical) + } + if v.X1 != maxX { + g.SetCell(v.X1, y, RuneSideVertical) + } } } return nil +} +func (g *Gui) drawFrameIntersections() (err error) { + for _, v := range g.views { + // ┌ + if ch, err := g.GetCell(v.X0, v.Y0); err == nil { + switch ch { + case RuneCornerTopLeft: // '┌' + // Nothing + case RuneCornerTopRight: // '┐' + g.SetCell(v.X0, v.Y0, RuneIntersectionTop) + case RuneCornerBottomLeft: // '└' + g.SetCell(v.X0, v.Y0, RuneIntersectionLeft) + case RuneCornerBottomRight: // '┘' + g.SetCell(v.X0, v.Y0, RuneIntersection) + case RuneSideVertical: // '│' + g.SetCell(v.X0, v.Y0, RuneIntersectionLeft) + case RuneSideHorizontal: // '─' + g.SetCell(v.X0, v.Y0, RuneIntersectionTop) + case RuneIntersection: // '┼' + // Nothing + case RuneIntersectionLeft: // '├' + // Nothing + case RuneIntersectionRight: // '┤' + g.SetCell(v.X0, v.Y0, RuneIntersection) + case RuneIntersectionTop: // '┬' + // Nothing + case RuneIntersectionBottom: // '┴' + g.SetCell(v.X0, v.Y0, RuneIntersection) + } + } + + // ┐ + if ch, err := g.GetCell(v.X1, v.Y0); err == nil { + switch ch { + case RuneCornerTopLeft: // '┌' + g.SetCell(v.X1, v.Y0, RuneIntersectionTop) + case RuneCornerTopRight: // '┐' + // Nothing + case RuneCornerBottomLeft: // '└' + g.SetCell(v.X1, v.Y0, RuneIntersection) + case RuneCornerBottomRight: // '┘' + g.SetCell(v.X1, v.Y0, RuneIntersectionRight) + case RuneSideVertical: // '│' + g.SetCell(v.X1, v.Y0, RuneIntersectionRight) + case RuneSideHorizontal: // '─' + g.SetCell(v.X1, v.Y0, RuneIntersectionTop) + case RuneIntersection: // '┼' + // Nothing + case RuneIntersectionLeft: // '├' + g.SetCell(v.X1, v.Y0, RuneIntersection) + case RuneIntersectionRight: // '┤' + // Nothing + case RuneIntersectionTop: // '┬' + // Nothing + case RuneIntersectionBottom: // '┴' + g.SetCell(v.X1, v.Y0, RuneIntersection) + } + } + + // └ + if ch, err := g.GetCell(v.X0, v.Y1); err == nil { + switch ch { + case RuneCornerTopLeft: // '┌' + g.SetCell(v.X0, v.Y1, RuneIntersectionLeft) + case RuneCornerTopRight: // '┐' + g.SetCell(v.X0, v.Y1, RuneIntersection) + case RuneCornerBottomLeft: // '└' + // Nothing + case RuneCornerBottomRight: // '┘' + g.SetCell(v.X0, v.Y1, RuneIntersectionBottom) + case RuneSideVertical: // '│' + g.SetCell(v.X0, v.Y1, RuneIntersectionLeft) + case RuneSideHorizontal: // '─' + g.SetCell(v.X0, v.Y1, RuneIntersectionBottom) + case RuneIntersection: // '┼' + // Nothing + case RuneIntersectionLeft: // '├' + // Nothing + case RuneIntersectionRight: // '┤' + g.SetCell(v.X0, v.Y1, RuneIntersection) + case RuneIntersectionTop: // '┬' + g.SetCell(v.X0, v.Y1, RuneIntersection) + case RuneIntersectionBottom: // '┴' + // Nothing + } + } + + // ┘ + if ch, err := g.GetCell(v.X1, v.Y1); err == nil { + switch ch { + case RuneCornerTopLeft: // '┌' + g.SetCell(v.X1, v.Y1, RuneIntersection) + case RuneCornerTopRight: // '┐' + g.SetCell(v.X1, v.Y1, RuneIntersectionRight) + case RuneCornerBottomLeft: // '└' + g.SetCell(v.X1, v.Y1, RuneIntersectionBottom) + case RuneCornerBottomRight: // '┘' + // Nothing + case RuneSideVertical: // '│' + g.SetCell(v.X1, v.Y1, RuneIntersectionRight) + case RuneSideHorizontal: // '─' + g.SetCell(v.X1, v.Y1, RuneIntersectionBottom) + case RuneIntersection: // '┼' + // Nothing + case RuneIntersectionLeft: // '├' + g.SetCell(v.X1, v.Y1, RuneIntersection) + case RuneIntersectionRight: // '┤' + // Nothing + case RuneIntersectionTop: // '┬' + g.SetCell(v.X1, v.Y1, RuneIntersection) + case RuneIntersectionBottom: // '┴' + // Nothing + } + } + } + return nil +} + +func (g *Gui) resizeView() (err error) { + return nil } func (g *Gui) onKey(ev *termbox.Event) (err error) { diff --git a/view.go b/view.go index 22bf894..5f1dc3f 100644 --- a/view.go +++ b/view.go @@ -5,8 +5,8 @@ import ( ) type View struct { - name string - x0, y0, x1, y1 int + Name string + X0, Y0, X1, Y1 int cx, cy int BgColor, FgColor termbox.Attribute SelBgColor, SelFgColor termbox.Attribute @@ -14,11 +14,11 @@ type View struct { func NewView(name string, x0, y0, x1, y1 int) (v *View) { v = &View{ - name: name, - x0: x0, - y0: y0, - x1: x1, - y1: y1, + Name: name, + X0: x0, + Y0: y0, + X1: x1, + Y1: y1, BgColor: termbox.ColorBlack, FgColor: termbox.ColorWhite, SelBgColor: termbox.ColorBlack, @@ -39,45 +39,3 @@ func (v *View) SetCell(x, y int, ch rune) { } termbox.SetCell(x, y, ch, fgColor, bgColor) } - -func (v *View) Draw() (err error) { - maxX, maxY := termbox.Size() - if v.y0 != -1 { - if v.x0 != -1 { - v.SetCell(v.x0, v.y0, RuneCornerTopLeft) - } - if v.x1 != maxX { - v.SetCell(v.x1, v.y0, RuneCornerTopRight) - } - } - if v.y0 != maxY { - if v.x0 != -1 { - v.SetCell(v.x0, v.y1, RuneCornerBottomLeft) - } - if v.x1 != maxX { - v.SetCell(v.x1, v.y1, RuneCornerBottomRight) - } - } - for x := v.x0 + 1; x < v.x1; x++ { - if v.y0 != -1 { - v.SetCell(x, v.y0, RuneEdgeHorizontal) - } - if v.y1 != maxY { - v.SetCell(x, v.y1, RuneEdgeHorizontal) - } - } - for y := v.y0 + 1; y < v.y1; y++ { - if v.x0 != -1 { - v.SetCell(v.x0, y, RuneEdgeVertical) - } - if v.x1 != maxX { - v.SetCell(v.x1, y, RuneEdgeVertical) - } - } - return nil -} - -func (v *View) Resize() (err error) { - //TODO - return nil -}