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)
|
||||||
|
}
|
||||||
|
}
|
201
gui.go
201
gui.go
@ -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
56
view.go
@ -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
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user