First approach for drawing intersections

This commit is contained in:
Roi Martin (@nibble_ds) 2013-12-29 21:29:29 +01:00
parent 81cf9a04eb
commit e0a4242e35
3 changed files with 252 additions and 63 deletions

48
_demos/demo1.go Normal file
View File

@ -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)
}
}

201
gui.go
View File

@ -13,8 +13,8 @@ const (
RuneCornerTopRight = '┐' RuneCornerTopRight = '┐'
RuneCornerBottomLeft = '└' RuneCornerBottomLeft = '└'
RuneCornerBottomRight = '┘' RuneCornerBottomRight = '┘'
RuneEdgeVertical = '│' RuneSideVertical = '│'
RuneEdgeHorizontal = '─' RuneSideHorizontal = '─'
RuneIntersection = '┼' RuneIntersection = '┼'
RuneIntersectionLeft = '├' RuneIntersectionLeft = '├'
RuneIntersectionRight = '┤' RuneIntersectionRight = '┤'
@ -30,6 +30,7 @@ type Gui struct {
events chan termbox.Event events chan termbox.Event
views []*View views []*View
currentView *View currentView *View
BgColor, FgColor termbox.Attribute
} }
func NewGui() (g *Gui) { func NewGui() (g *Gui) {
@ -38,6 +39,8 @@ func NewGui() (g *Gui) {
func (g *Gui) Init() (err error) { func (g *Gui) Init() (err error) {
g.events = make(chan termbox.Event, 20) g.events = make(chan termbox.Event, 20)
g.BgColor = termbox.ColorWhite
g.FgColor = termbox.ColorBlack
return termbox.Init() 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 || if x0 < -1 || y0 < -1 || x1 < -1 || y1 < -1 ||
x0 > maxX || y0 > maxY || x1 > maxX || y1 > maxY || x0 > maxX || y0 > maxY || x1 > maxX || y1 > maxY ||
x0 >= x1 || y0 >= y1 { x0 >= x1 || y0 >= y1 {
return nil, errors.New("Invalid position") return nil, errors.New("invalid points")
} }
for _, vi := range g.views { for _, v := range g.views {
if name == vi.name { if name == v.Name {
return nil, errors.New("Invalid name") return nil, errors.New("invalid name")
} }
} }
@ -104,6 +107,19 @@ func (g *Gui) MainLoop() (err error) {
return nil 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) { func (g *Gui) consumeevents() (err error) {
for { for {
select { select {
@ -132,25 +148,192 @@ func (g *Gui) handleEvent(ev *termbox.Event) (err error) {
func (g *Gui) draw() (err error) { func (g *Gui) draw() (err error) {
for _, v := range g.views { for _, v := range g.views {
if err := v.Draw(); err != nil { if err := g.drawView(v); err != nil {
return err return err
} }
} }
return nil return nil
}
func (g *Gui) drawView(v *View) (err error) {
return nil
} }
func (g *Gui) resize() (err error) { func (g *Gui) resize() (err error) {
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault) termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
for _, v := range g.views { if err := g.resizeView(); err != nil {
if err := v.Resize(); err != nil {
return err return err
} }
if err := g.drawFrames(); err != nil {
return err
}
if err := g.drawFrameIntersections(); err != nil {
return err
} }
return nil return nil
} }
func (g *Gui) drawFrames() (err error) {
maxX, maxY := termbox.Size()
for _, v := range g.views {
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) { func (g *Gui) onKey(ev *termbox.Event) (err error) {
switch ev.Key { switch ev.Key {
case termbox.KeyCtrlC: case termbox.KeyCtrlC:

56
view.go
View File

@ -5,8 +5,8 @@ import (
) )
type View struct { type View struct {
name string Name string
x0, y0, x1, y1 int X0, Y0, X1, Y1 int
cx, cy int cx, cy int
BgColor, FgColor termbox.Attribute BgColor, FgColor termbox.Attribute
SelBgColor, SelFgColor termbox.Attribute SelBgColor, SelFgColor termbox.Attribute
@ -14,11 +14,11 @@ type View struct {
func NewView(name string, x0, y0, x1, y1 int) (v *View) { func NewView(name string, x0, y0, x1, y1 int) (v *View) {
v = &View{ v = &View{
name: name, Name: name,
x0: x0, X0: x0,
y0: y0, Y0: y0,
x1: x1, X1: x1,
y1: y1, Y1: y1,
BgColor: termbox.ColorBlack, BgColor: termbox.ColorBlack,
FgColor: termbox.ColorWhite, FgColor: termbox.ColorWhite,
SelBgColor: termbox.ColorBlack, SelBgColor: termbox.ColorBlack,
@ -39,45 +39,3 @@ func (v *View) SetCell(x, y int, ch rune) {
} }
termbox.SetCell(x, y, ch, fgColor, bgColor) 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
}