mirror of
https://github.com/jroimartin/gocui.git
synced 2025-04-26 13:48:49 +08:00
First approach for drawing intersections
This commit is contained in:
parent
81cf9a04eb
commit
e0a4242e35
48
_demos/demo1.go
Normal file
48
_demos/demo1.go
Normal 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)
|
||||
}
|
||||
}
|
211
gui.go
211
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) {
|
||||
|
56
view.go
56
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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user