2014-01-14 20:11:12 +01:00
|
|
|
// Copyright 2014 The gocui Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
2013-12-27 21:36:26 +01:00
|
|
|
package gocui
|
|
|
|
|
|
|
|
import (
|
2014-01-09 20:20:14 +01:00
|
|
|
"bufio"
|
|
|
|
"bytes"
|
2014-01-06 18:36:38 +01:00
|
|
|
"errors"
|
2014-01-09 20:20:14 +01:00
|
|
|
"io"
|
|
|
|
|
2013-12-31 21:23:28 +01:00
|
|
|
"github.com/nsf/termbox-go"
|
2013-12-27 21:36:26 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
type View struct {
|
2014-01-16 23:01:53 +01:00
|
|
|
name string
|
|
|
|
x0, y0, x1, y1 int
|
|
|
|
ox, oy int
|
|
|
|
cx, cy int
|
2014-01-10 12:38:08 +01:00
|
|
|
buffer []rune
|
|
|
|
bgColor, fgColor Attribute
|
|
|
|
selBgColor, selFgColor Attribute
|
2014-01-16 23:01:53 +01:00
|
|
|
|
|
|
|
Highlight bool
|
2013-12-27 21:36:26 +01:00
|
|
|
}
|
|
|
|
|
2014-01-16 00:28:16 +01:00
|
|
|
func newView(name string, x0, y0, x1, y1 int) *View {
|
|
|
|
v := &View{
|
2014-01-16 23:01:53 +01:00
|
|
|
name: name,
|
|
|
|
x0: x0,
|
|
|
|
y0: y0,
|
|
|
|
x1: x1,
|
|
|
|
y1: y1,
|
2013-12-28 18:49:01 +01:00
|
|
|
}
|
|
|
|
return v
|
2013-12-27 21:36:26 +01:00
|
|
|
}
|
2014-01-06 18:36:38 +01:00
|
|
|
|
2014-01-09 20:20:14 +01:00
|
|
|
func (v *View) Size() (x, y int) {
|
2014-01-16 23:01:53 +01:00
|
|
|
return v.x1 - v.x0 - 1, v.y1 - v.y0 - 1
|
|
|
|
}
|
|
|
|
|
|
|
|
func (v *View) Name() string {
|
|
|
|
return v.name
|
2014-01-09 20:20:14 +01:00
|
|
|
}
|
|
|
|
|
2014-01-16 00:28:16 +01:00
|
|
|
func (v *View) setRune(x, y int, ch rune) error {
|
2014-01-09 20:20:14 +01:00
|
|
|
maxX, maxY := v.Size()
|
|
|
|
if x < 0 || x >= maxX || y < 0 || y >= maxY {
|
|
|
|
return errors.New("invalid point")
|
|
|
|
}
|
2014-01-09 21:55:23 +01:00
|
|
|
|
|
|
|
var fgColor, bgColor Attribute
|
2014-01-16 23:01:53 +01:00
|
|
|
if v.Highlight && y == v.cy {
|
2014-01-10 12:38:08 +01:00
|
|
|
fgColor = v.selFgColor
|
|
|
|
bgColor = v.selBgColor
|
2014-01-09 21:55:23 +01:00
|
|
|
} else {
|
2014-01-10 12:38:08 +01:00
|
|
|
fgColor = v.fgColor
|
|
|
|
bgColor = v.bgColor
|
2014-01-09 21:55:23 +01:00
|
|
|
}
|
2014-01-16 23:01:53 +01:00
|
|
|
termbox.SetCell(v.x0+x+1, v.y0+y+1, ch,
|
2014-01-09 21:55:23 +01:00
|
|
|
termbox.Attribute(fgColor), termbox.Attribute(bgColor))
|
2014-01-09 20:20:14 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2014-01-16 00:28:16 +01:00
|
|
|
func (v *View) SetCursor(x, y int) error {
|
2014-01-09 20:20:14 +01:00
|
|
|
maxX, maxY := v.Size()
|
|
|
|
if x < 0 || x >= maxX || y < 0 || y >= maxY {
|
2014-01-06 18:36:38 +01:00
|
|
|
return errors.New("invalid point")
|
|
|
|
}
|
2014-01-16 23:01:53 +01:00
|
|
|
v.cx = x
|
|
|
|
v.cy = y
|
2014-01-06 18:36:38 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2014-01-16 23:01:53 +01:00
|
|
|
func (v *View) Cursor() (x, y int) {
|
|
|
|
return v.cx, v.cy
|
|
|
|
}
|
|
|
|
|
2014-01-13 20:15:39 +01:00
|
|
|
func (v *View) SetOrigin(x, y int) {
|
2014-01-16 23:01:53 +01:00
|
|
|
v.ox = x
|
|
|
|
v.oy = y
|
|
|
|
}
|
|
|
|
|
|
|
|
func (v *View) Origin() (x, y int) {
|
|
|
|
return v.ox, v.oy
|
2014-01-13 20:15:39 +01:00
|
|
|
}
|
|
|
|
|
2014-01-06 18:36:38 +01:00
|
|
|
func (v *View) Write(p []byte) (n int, err error) {
|
2014-01-09 20:20:14 +01:00
|
|
|
pr := bytes.Runes(p)
|
|
|
|
v.buffer = append(v.buffer, pr...)
|
|
|
|
return len(pr), nil
|
|
|
|
}
|
|
|
|
|
2014-01-16 00:28:16 +01:00
|
|
|
func (v *View) draw() error {
|
2014-01-09 20:20:14 +01:00
|
|
|
maxX, maxY := v.Size()
|
|
|
|
buf := bytes.NewBufferString(string(v.buffer))
|
|
|
|
br := bufio.NewReader(buf)
|
2014-01-10 12:38:08 +01:00
|
|
|
|
2014-01-13 20:21:49 +01:00
|
|
|
y := 0
|
|
|
|
for i := 0; ; i++ {
|
2014-01-09 20:20:14 +01:00
|
|
|
line, _, err := br.ReadLine()
|
|
|
|
if err == io.EOF {
|
|
|
|
break
|
|
|
|
} else if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2014-01-16 23:01:53 +01:00
|
|
|
if i < v.oy {
|
2014-01-13 20:15:39 +01:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
x := 0
|
2014-01-13 20:21:49 +01:00
|
|
|
for j, ch := range bytes.Runes(line) {
|
2014-01-16 23:01:53 +01:00
|
|
|
if j < v.ox {
|
2014-01-13 20:15:39 +01:00
|
|
|
continue
|
|
|
|
}
|
2014-01-13 20:21:49 +01:00
|
|
|
if x >= 0 && x < maxX && y >= 0 && y < maxY {
|
2014-01-16 00:28:16 +01:00
|
|
|
if err := v.setRune(x, y, ch); err != nil {
|
2014-01-09 20:20:14 +01:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2014-01-13 20:15:39 +01:00
|
|
|
x++
|
2014-01-09 20:20:14 +01:00
|
|
|
}
|
2014-01-13 20:21:49 +01:00
|
|
|
y++
|
2014-01-09 20:20:14 +01:00
|
|
|
}
|
|
|
|
return nil
|
2014-01-06 18:36:38 +01:00
|
|
|
}
|
2014-01-10 12:38:08 +01:00
|
|
|
|
|
|
|
func (v *View) Clear() {
|
|
|
|
v.buffer = nil
|
2014-01-13 20:15:39 +01:00
|
|
|
v.clearRunes()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (v *View) clearRunes() {
|
2014-01-10 12:38:08 +01:00
|
|
|
maxX, maxY := v.Size()
|
|
|
|
for x := 0; x < maxX; x++ {
|
|
|
|
for y := 0; y < maxY; y++ {
|
2014-01-16 23:01:53 +01:00
|
|
|
termbox.SetCell(v.x0+x+1, v.y0+y+1, 0,
|
2014-01-10 12:38:08 +01:00
|
|
|
termbox.Attribute(v.fgColor), termbox.Attribute(v.bgColor))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|