aboutsummaryrefslogtreecommitdiffstats
path: root/Godeps/_workspace/src/github.com/gizak/termui
diff options
context:
space:
mode:
Diffstat (limited to 'Godeps/_workspace/src/github.com/gizak/termui')
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/.gitignore1
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/README.md169
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/barchart.go (renamed from Godeps/_workspace/src/github.com/gizak/termui/bar.go)67
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/block.go286
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/block_common.go (renamed from Godeps/_workspace/src/github.com/gizak/termui/box_others.go)8
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/block_test.go46
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/block_windows.go (renamed from Godeps/_workspace/src/github.com/gizak/termui/box_windows.go)2
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/box.go117
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/buffer.go106
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/canvas.go12
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/canvas_test.go55
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/config26
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/debug/debuger.go117
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/doc.go2
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/events.go455
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/events_test.go28
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/example/barchart.go35
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/example/barchart.pngbin15386 -> 0 bytes
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/example/dashboard.gifbin453764 -> 0 bytes
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/example/dashboard.go148
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/example/gauge.go62
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/example/gauge.pngbin32431 -> 0 bytes
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/example/grid.gifbin800288 -> 0 bytes
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/example/grid.go134
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/example/linechart.go68
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/example/linechart.pngbin139361 -> 0 bytes
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/example/list.go41
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/example/list.pngbin37227 -> 0 bytes
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/example/mbarchart.go50
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/example/mbarchart.pngbin20075 -> 0 bytes
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/example/par.go48
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/example/par.pngbin65773 -> 0 bytes
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/example/sparklines.go65
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/example/sparklines.pngbin43431 -> 0 bytes
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/example/theme.go143
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/example/themedefault.pngbin105508 -> 0 bytes
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/example/themehelloworld.pngbin90111 -> 0 bytes
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/gauge.go90
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/grid.go20
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/grid_test.go98
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/helper.go156
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/helper_test.go58
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/linechart.go (renamed from Godeps/_workspace/src/github.com/gizak/termui/chart.go)153
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/linechart_others.go (renamed from Godeps/_workspace/src/github.com/gizak/termui/chart_others.go)2
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/linechart_windows.go (renamed from Godeps/_workspace/src/github.com/gizak/termui/chart_windows.go)2
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/list.go53
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/mbarchart.go (renamed from Godeps/_workspace/src/github.com/gizak/termui/mbar.go)103
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/p.go71
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/par.go64
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/point.go28
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/pos.go78
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/render.go117
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/sparkline.go83
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/test/runtest.go66
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/textbuilder.go215
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/theme.go58
-rw-r--r--Godeps/_workspace/src/github.com/gizak/termui/widget.go94
57 files changed, 1918 insertions, 1982 deletions
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/.gitignore b/Godeps/_workspace/src/github.com/gizak/termui/.gitignore
index daf913b1b..eb1369fd4 100644
--- a/Godeps/_workspace/src/github.com/gizak/termui/.gitignore
+++ b/Godeps/_workspace/src/github.com/gizak/termui/.gitignore
@@ -22,3 +22,4 @@ _testmain.go
*.exe
*.test
*.prof
+.DS_Store
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/README.md b/Godeps/_workspace/src/github.com/gizak/termui/README.md
index b9bc3024d..0e1d41b08 100644
--- a/Godeps/_workspace/src/github.com/gizak/termui/README.md
+++ b/Godeps/_workspace/src/github.com/gizak/termui/README.md
@@ -1,55 +1,30 @@
# termui [![Build Status](https://travis-ci.org/gizak/termui.svg?branch=master)](https://travis-ci.org/gizak/termui) [![Doc Status](https://godoc.org/github.com/gizak/termui?status.png)](https://godoc.org/github.com/gizak/termui)
-## Update 23/06/2015
-Pull requests and master branch are freezing, waiting for merging from `refactoring` branch.
+<img src="./_example/dashboard.gif" alt="demo cast under osx 10.10; Terminal.app; Menlo Regular 12pt.)" width="80%">
-## Notice
-termui comes with ABSOLUTELY NO WARRANTY, and there is a breaking change coming up (see refactoring branch) which will change the `Bufferer` interface and many others. These changes reduce calculation overhead and introduce a new drawing buffer with better capacibilities. We will step into the next stage (call it beta) after merging these changes.
+`termui` is a cross-platform, easy-to-compile, and fully-customizable terminal dashboard. It is inspired by [blessed-contrib](https://github.com/yaronn/blessed-contrib), but purely in Go.
-## Introduction
-Go terminal dashboard. Inspired by [blessed-contrib](https://github.com/yaronn/blessed-contrib), but purely in Go.
+Now version v2 has arrived! It brings new event system, new theme system, new `Buffer` interface and specific colour text rendering. (some docs are missing, but it will be completed soon!)
-Cross-platform, easy to compile, and fully-customizable.
-
-__Demo:__ (cast under osx 10.10; Terminal.app; Menlo Regular 12pt.)
+## Installation
-<img src="./example/dashboard.gif" alt="demo" width="600">
+`master` mirrors v2 branch, to install:
-__Grid layout:__
+ go get -u github.com/gizak/termui
-Expressive syntax, using [12 columns grid system](http://www.w3schools.com/bootstrap/bootstrap_grid_system.asp)
-```go
- import ui "github.com/gizak/termui"
- // init and create widgets...
+For the compatible reason, you can choose to install the legacy version of `termui`:
- // build
- ui.Body.AddRows(
- ui.NewRow(
- ui.NewCol(6, 0, widget0),
- ui.NewCol(6, 0, widget1)),
- ui.NewRow(
- ui.NewCol(3, 0, widget2),
- ui.NewCol(3, 0, widget30, widget31, widget32),
- ui.NewCol(6, 0, widget4)))
+ go get gopkg.in/gizak/termui.v1
- // calculate layout
- ui.Body.Align()
-
- ui.Render(ui.Body)
-```
-[demo code:](https://github.com/gizak/termui/blob/master/example/grid.go)
-
-<img src="./example/grid.gif" alt="grid" width="500">
-
-## Installation
+## Usage
- go get github.com/gizak/termui
+### Layout
-## Usage
+To use `termui`, the very first thing you may want to know is how to manage layout. `termui` offers two ways of doing this, known as absolute layout and grid layout.
-Each component's layout is a bit like HTML block (box model), which has border and padding.
+__Absolute layout__
-The `Border` property can be chosen to hide or display (with its border label), when it comes to display, the label takes 1 padding space (i.e. in css: `padding: 1;`, innerHeight and innerWidth therefore shrunk by 1).
+Each widget has an underlying block structure which basically is a box model. It has border, label and padding properties. A border of a widget can be chosen to hide or display (with its border label), you can pick a different front/back colour for the border as well. To display such a widget at a specific location in terminal window, you need to assign `.X`, `.Y`, `.Height`, `.Width` values for each widget before send it to `.Render`. Let's demonstrate these by a code snippet:
`````go
import ui "github.com/gizak/termui" // <- ui shortcut, optional
@@ -65,20 +40,20 @@ The `Border` property can be chosen to hide or display (with its border label),
p.Height = 3
p.Width = 50
p.TextFgColor = ui.ColorWhite
- p.Border.Label = "Text Box"
- p.Border.FgColor = ui.ColorCyan
+ p.BorderLabel = "Text Box"
+ p.BorderFg = ui.ColorCyan
g := ui.NewGauge()
g.Percent = 50
g.Width = 50
g.Height = 3
g.Y = 11
- g.Border.Label = "Gauge"
+ g.BorderLabel = "Gauge"
g.BarColor = ui.ColorRed
- g.Border.FgColor = ui.ColorWhite
- g.Border.LabelFgColor = ui.ColorCyan
+ g.BorderFg = ui.ColorWhite
+ g.BorderLabelFg = ui.ColorCyan
- ui.Render(p, g)
+ ui.Render(p, g) // feel free to call Render, it's async and non-block
// event handler...
}
@@ -86,62 +61,74 @@ The `Border` property can be chosen to hide or display (with its border label),
Note that components can be overlapped (I'd rather call this a feature...), `Render(rs ...Renderer)` renders its args from left to right (i.e. each component's weight is arising from left to right).
-## Themes
-
-_All_ colors in _all_ components can be changed at _any_ time, while there provides some predefined color schemes:
-
-```go
-// for now there are only two themes: default and helloworld
-termui.UseTheme("helloworld")
-
-// create components...
-```
-The `default ` theme's settings depend on the user's terminal color scheme, which is saying if your terminal default font color is white and background is white, it will be like:
-
-<img src="./example/themedefault.png" alt="default" type="image/png" width="600">
-
-The `helloworld` color scheme drops in some colors!
-
-<img src="./example/themehelloworld.png" alt="helloworld" type="image/png" width="600">
-
-## Widgets
-
-#### Par
-
-[demo code](https://github.com/gizak/termui/blob/master/example/par.go)
-
-<img src="./example/par.png" alt="par" type="image/png" width="300">
+__Grid layout:__
-#### List
-[demo code](https://github.com/gizak/termui/blob/master/example/list.go)
+<img src="./_example/grid.gif" alt="grid" width="60%">
-<img src="./example/list.png" alt="list" type="image/png" width="200">
+Grid layout uses [12 columns grid system](http://www.w3schools.com/bootstrap/bootstrap_grid_system.asp) with expressive syntax. To use `Grid`, all we need to do is build a widget tree consisting of `Row`s and Cols (Actually a Col is also a `Row` but with a widget endpoint attached).
-#### Gauge
-[demo code](https://github.com/gizak/termui/blob/master/example/gauge.go)
+```go
+ import ui "github.com/gizak/termui"
+ // init and create widgets...
-<img src="./example/gauge.png" alt="gauge" type="image/png" width="350">
+ // build
+ ui.Body.AddRows(
+ ui.NewRow(
+ ui.NewCol(6, 0, widget0),
+ ui.NewCol(6, 0, widget1)),
+ ui.NewRow(
+ ui.NewCol(3, 0, widget2),
+ ui.NewCol(3, 0, widget30, widget31, widget32),
+ ui.NewCol(6, 0, widget4)))
-#### Line Chart
-[demo code](https://github.com/gizak/termui/blob/master/example/linechart.go)
+ // calculate layout
+ ui.Body.Align()
-<img src="./example/linechart.png" alt="linechart" type="image/png" width="450">
+ ui.Render(ui.Body)
+```
-#### Bar Chart
-[demo code](https://github.com/gizak/termui/blob/master/example/barchart.go)
+### Events
-<img src="./example/barchart.png" alt="barchart" type="image/png" width="150">
+`termui` ships with a http-like event mux handling system. All events are channeled up from different sources (typing, click, windows resize, custom event) and then encoded as universal `Event` object. `Event.Path` indicates the event type and `Event.Data` stores the event data struct. Add a handler to a certain event is easy as below:
-#### Mult-Bar / Stacked-Bar Chart
-[demo code](https://github.com/gizak/termui/blob/master/example/mbarchart.go)
+```go
+ // handle key q pressing
+ ui.Handle("/sys/kbd/q", func(ui.Event) {
+ // press q to quit
+ ui.StopLoop()
+ })
+
+ ui.Handle("/sys/kbd/C-x", func(ui.Event) {
+ // handle Ctrl + x combination
+ })
+
+ ui.Handle("/sys/kbd", func(ui.Event) {
+ // handle all other key pressing
+ })
+
+ // handle a 1s timer
+ ui.Handle("/timer/1s", func(e ui.Event) {
+ t := e.Data.(ui.EvtTimer)
+ // t is a EvtTimer
+ if t.Count%2 ==0 {
+ // do something
+ }
+ })
-<img src="./example/mbarchart.png" alt="barchart" type="image/png" width="150">
+ ui.Loop() // block until StopLoop is called
+```
-#### Sparklines
-[demo code](https://github.com/gizak/termui/blob/master/example/sparklines.go)
+### Widgets
-<img src="./example/sparklines.png" alt="sparklines" type="image/png" width="350">
+Click image to see the corresponding demo codes.
+[<img src="./_example/par.png" alt="par" type="image/png" width="45%">](https://github.com/gizak/termui/blob/master/_example/par.go)
+[<img src="./_example/list.png" alt="list" type="image/png" width="45%">](https://github.com/gizak/termui/blob/master/_example/list.go)
+[<img src="./_example/gauge.png" alt="gauge" type="image/png" width="45%">](https://github.com/gizak/termui/blob/master/_example/gauge.go)
+[<img src="./_example/linechart.png" alt="linechart" type="image/png" width="45%">](https://github.com/gizak/termui/blob/master/_example/linechart.go)
+[<img src="./_example/barchart.png" alt="barchart" type="image/png" width="45%">](https://github.com/gizak/termui/blob/master/_example/barchart.go)
+[<img src="./_example/mbarchart.png" alt="barchart" type="image/png" width="45%">](https://github.com/gizak/termui/blob/master/_example/mbarchart.go)
+[<img src="./_example/sparklines.png" alt="sparklines" type="image/png" width="45%">](https://github.com/gizak/termui/blob/master/_example/sparklines.go)
## GoDoc
@@ -150,10 +137,12 @@ The `helloworld` color scheme drops in some colors!
## TODO
- [x] Grid layout
-- [ ] Event system
-- [ ] Canvas widget
-- [ ] Refine APIs
+- [x] Event system
+- [x] Canvas widget
+- [x] Refine APIs
- [ ] Focusable widgets
+## Changelog
+
## License
This library is under the [MIT License](http://opensource.org/licenses/MIT)
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/bar.go b/Godeps/_workspace/src/github.com/gizak/termui/barchart.go
index 57bae0ae8..980e958e2 100644
--- a/Godeps/_workspace/src/github.com/gizak/termui/bar.go
+++ b/Godeps/_workspace/src/github.com/gizak/termui/barchart.go
@@ -1,4 +1,4 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
@@ -39,16 +39,16 @@ type BarChart struct {
// NewBarChart returns a new *BarChart with current theme.
func NewBarChart() *BarChart {
bc := &BarChart{Block: *NewBlock()}
- bc.BarColor = theme.BarChartBar
- bc.NumColor = theme.BarChartNum
- bc.TextColor = theme.BarChartText
+ bc.BarColor = ThemeAttr("barchart.bar.bg")
+ bc.NumColor = ThemeAttr("barchart.num.fg")
+ bc.TextColor = ThemeAttr("barchart.text.fg")
bc.BarGap = 1
bc.BarWidth = 3
return bc
}
func (bc *BarChart) layout() {
- bc.numBar = bc.innerWidth / (bc.BarGap + bc.BarWidth)
+ bc.numBar = bc.innerArea.Dx() / (bc.BarGap + bc.BarWidth)
bc.labels = make([][]rune, bc.numBar)
bc.dataNum = make([][]rune, len(bc.Data))
@@ -69,7 +69,7 @@ func (bc *BarChart) layout() {
bc.max = bc.Data[i]
}
}
- bc.scale = float64(bc.max) / float64(bc.innerHeight-1)
+ bc.scale = float64(bc.max) / float64(bc.innerArea.Dy()-1)
}
func (bc *BarChart) SetMax(max int) {
@@ -80,8 +80,8 @@ func (bc *BarChart) SetMax(max int) {
}
// Buffer implements Bufferer interface.
-func (bc *BarChart) Buffer() []Point {
- ps := bc.Block.Buffer()
+func (bc *BarChart) Buffer() Buffer {
+ buf := bc.Block.Buffer()
bc.layout()
for i := 0; i < bc.numBar && i < len(bc.Data) && i < len(bc.DataLabels); i++ {
@@ -90,46 +90,49 @@ func (bc *BarChart) Buffer() []Point {
// plot bar
for j := 0; j < bc.BarWidth; j++ {
for k := 0; k < h; k++ {
- p := Point{}
- p.Ch = ' '
- p.Bg = bc.BarColor
+ c := Cell{
+ Ch: ' ',
+ Bg: bc.BarColor,
+ }
if bc.BarColor == ColorDefault { // when color is default, space char treated as transparent!
- p.Bg |= AttrReverse
+ c.Bg |= AttrReverse
}
- p.X = bc.innerX + i*(bc.BarWidth+bc.BarGap) + j
- p.Y = bc.innerY + bc.innerHeight - 2 - k
- ps = append(ps, p)
+ x := bc.innerArea.Min.X + i*(bc.BarWidth+bc.BarGap) + j
+ y := bc.innerArea.Min.Y + bc.innerArea.Dy() - 2 - k
+ buf.Set(x, y, c)
}
}
// plot text
for j, k := 0, 0; j < len(bc.labels[i]); j++ {
w := charWidth(bc.labels[i][j])
- p := Point{}
- p.Ch = bc.labels[i][j]
- p.Bg = bc.BgColor
- p.Fg = bc.TextColor
- p.Y = bc.innerY + bc.innerHeight - 1
- p.X = bc.innerX + oftX + k
- ps = append(ps, p)
+ c := Cell{
+ Ch: bc.labels[i][j],
+ Bg: bc.Bg,
+ Fg: bc.TextColor,
+ }
+ y := bc.innerArea.Min.Y + bc.innerArea.Dy() - 1
+ x := bc.innerArea.Min.X + oftX + k
+ buf.Set(x, y, c)
k += w
}
// plot num
for j := 0; j < len(bc.dataNum[i]); j++ {
- p := Point{}
- p.Ch = bc.dataNum[i][j]
- p.Fg = bc.NumColor
- p.Bg = bc.BarColor
+ c := Cell{
+ Ch: bc.dataNum[i][j],
+ Fg: bc.NumColor,
+ Bg: bc.BarColor,
+ }
if bc.BarColor == ColorDefault { // the same as above
- p.Bg |= AttrReverse
+ c.Bg |= AttrReverse
}
if h == 0 {
- p.Bg = bc.BgColor
+ c.Bg = bc.Bg
}
- p.X = bc.innerX + oftX + (bc.BarWidth-len(bc.dataNum[i]))/2 + j
- p.Y = bc.innerY + bc.innerHeight - 2
- ps = append(ps, p)
+ x := bc.innerArea.Min.X + oftX + (bc.BarWidth-len(bc.dataNum[i]))/2 + j
+ y := bc.innerArea.Min.Y + bc.innerArea.Dy() - 2
+ buf.Set(x, y, c)
}
}
- return bc.Block.chopOverflow(ps)
+ return buf
}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/block.go b/Godeps/_workspace/src/github.com/gizak/termui/block.go
index 953136596..418738c8d 100644
--- a/Godeps/_workspace/src/github.com/gizak/termui/block.go
+++ b/Godeps/_workspace/src/github.com/gizak/termui/block.go
@@ -1,142 +1,240 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
package termui
+import "image"
+
+// Hline is a horizontal line.
+type Hline struct {
+ X int
+ Y int
+ Len int
+ Fg Attribute
+ Bg Attribute
+}
+
+// Vline is a vertical line.
+type Vline struct {
+ X int
+ Y int
+ Len int
+ Fg Attribute
+ Bg Attribute
+}
+
+// Buffer draws a horizontal line.
+func (l Hline) Buffer() Buffer {
+ if l.Len <= 0 {
+ return NewBuffer()
+ }
+ return NewFilledBuffer(l.X, l.Y, l.X+l.Len, l.Y+1, HORIZONTAL_LINE, l.Fg, l.Bg)
+}
+
+// Buffer draws a vertical line.
+func (l Vline) Buffer() Buffer {
+ if l.Len <= 0 {
+ return NewBuffer()
+ }
+ return NewFilledBuffer(l.X, l.Y, l.X+1, l.Y+l.Len, VERTICAL_LINE, l.Fg, l.Bg)
+}
+
+// Buffer draws a box border.
+func (b Block) drawBorder(buf Buffer) {
+ if !b.Border {
+ return
+ }
+
+ min := b.area.Min
+ max := b.area.Max
+
+ x0 := min.X
+ y0 := min.Y
+ x1 := max.X - 1
+ y1 := max.Y - 1
+
+ // draw lines
+ if b.BorderTop {
+ buf.Merge(Hline{x0, y0, x1 - x0, b.BorderFg, b.BorderBg}.Buffer())
+ }
+ if b.BorderBottom {
+ buf.Merge(Hline{x0, y1, x1 - x0, b.BorderFg, b.BorderBg}.Buffer())
+ }
+ if b.BorderLeft {
+ buf.Merge(Vline{x0, y0, y1 - y0, b.BorderFg, b.BorderBg}.Buffer())
+ }
+ if b.BorderRight {
+ buf.Merge(Vline{x1, y0, y1 - y0, b.BorderFg, b.BorderBg}.Buffer())
+ }
+
+ // draw corners
+ if b.BorderTop && b.BorderLeft && b.area.Dx() > 0 && b.area.Dy() > 0 {
+ buf.Set(x0, y0, Cell{TOP_LEFT, b.BorderFg, b.BorderBg})
+ }
+ if b.BorderTop && b.BorderRight && b.area.Dx() > 1 && b.area.Dy() > 0 {
+ buf.Set(x1, y0, Cell{TOP_RIGHT, b.BorderFg, b.BorderBg})
+ }
+ if b.BorderBottom && b.BorderLeft && b.area.Dx() > 0 && b.area.Dy() > 1 {
+ buf.Set(x0, y1, Cell{BOTTOM_LEFT, b.BorderFg, b.BorderBg})
+ }
+ if b.BorderBottom && b.BorderRight && b.area.Dx() > 1 && b.area.Dy() > 1 {
+ buf.Set(x1, y1, Cell{BOTTOM_RIGHT, b.BorderFg, b.BorderBg})
+ }
+}
+
+func (b Block) drawBorderLabel(buf Buffer) {
+ maxTxtW := b.area.Dx() - 2
+ tx := DTrimTxCls(DefaultTxBuilder.Build(b.BorderLabel, b.BorderLabelFg, b.BorderLabelBg), maxTxtW)
+
+ for i, w := 0, 0; i < len(tx); i++ {
+ buf.Set(b.area.Min.X+1+w, b.area.Min.Y, tx[i])
+ w += tx[i].Width()
+ }
+}
+
// Block is a base struct for all other upper level widgets,
// consider it as css: display:block.
// Normally you do not need to create it manually.
type Block struct {
+ area image.Rectangle
+ innerArea image.Rectangle
X int
Y int
- Border labeledBorder
- IsDisplay bool
- HasBorder bool
- BgColor Attribute
+ Border bool
+ BorderFg Attribute
+ BorderBg Attribute
+ BorderLeft bool
+ BorderRight bool
+ BorderTop bool
+ BorderBottom bool
+ BorderLabel string
+ BorderLabelFg Attribute
+ BorderLabelBg Attribute
+ Display bool
+ Bg Attribute
Width int
Height int
- innerWidth int
- innerHeight int
- innerX int
- innerY int
PaddingTop int
PaddingBottom int
PaddingLeft int
PaddingRight int
+ id string
+ Float Align
}
// NewBlock returns a *Block which inherits styles from current theme.
func NewBlock() *Block {
- d := Block{}
- d.IsDisplay = true
- d.HasBorder = theme.HasBorder
- d.Border.BgColor = theme.BorderBg
- d.Border.FgColor = theme.BorderFg
- d.Border.LabelBgColor = theme.BorderLabelTextBg
- d.Border.LabelFgColor = theme.BorderLabelTextFg
- d.BgColor = theme.BlockBg
- d.Width = 2
- d.Height = 2
- return &d
-}
-
-// compute box model
-func (d *Block) align() {
- d.innerWidth = d.Width - d.PaddingLeft - d.PaddingRight
- d.innerHeight = d.Height - d.PaddingTop - d.PaddingBottom
- d.innerX = d.X + d.PaddingLeft
- d.innerY = d.Y + d.PaddingTop
-
- if d.HasBorder {
- d.innerHeight -= 2
- d.innerWidth -= 2
- d.Border.X = d.X
- d.Border.Y = d.Y
- d.Border.Width = d.Width
- d.Border.Height = d.Height
- d.innerX++
- d.innerY++
- }
+ b := Block{}
+ b.Display = true
+ b.Border = true
+ b.BorderLeft = true
+ b.BorderRight = true
+ b.BorderTop = true
+ b.BorderBottom = true
+ b.BorderBg = ThemeAttr("border.bg")
+ b.BorderFg = ThemeAttr("border.fg")
+ b.BorderLabelBg = ThemeAttr("label.bg")
+ b.BorderLabelFg = ThemeAttr("label.fg")
+ b.Bg = ThemeAttr("block.bg")
+ b.Width = 2
+ b.Height = 2
+ b.id = GenId()
+ b.Float = AlignNone
+ return &b
+}
- if d.innerHeight < 0 {
- d.innerHeight = 0
- }
- if d.innerWidth < 0 {
- d.innerWidth = 0
- }
+func (b Block) Id() string {
+ return b.id
+}
+// Align computes box model
+func (b *Block) Align() {
+ // outer
+ b.area.Min.X = 0
+ b.area.Min.Y = 0
+ b.area.Max.X = b.Width
+ b.area.Max.Y = b.Height
+
+ // float
+ b.area = AlignArea(TermRect(), b.area, b.Float)
+ b.area = MoveArea(b.area, b.X, b.Y)
+
+ // inner
+ b.innerArea.Min.X = b.area.Min.X + b.PaddingLeft
+ b.innerArea.Min.Y = b.area.Min.Y + b.PaddingTop
+ b.innerArea.Max.X = b.area.Max.X - b.PaddingRight
+ b.innerArea.Max.Y = b.area.Max.Y - b.PaddingBottom
+
+ if b.Border {
+ if b.BorderLeft {
+ b.innerArea.Min.X++
+ }
+ if b.BorderRight {
+ b.innerArea.Max.X--
+ }
+ if b.BorderTop {
+ b.innerArea.Min.Y++
+ }
+ if b.BorderBottom {
+ b.innerArea.Max.Y--
+ }
+ }
}
// InnerBounds returns the internal bounds of the block after aligning and
// calculating the padding and border, if any.
-func (d *Block) InnerBounds() (x, y, width, height int) {
- d.align()
- return d.innerX, d.innerY, d.innerWidth, d.innerHeight
+func (b *Block) InnerBounds() image.Rectangle {
+ b.Align()
+ return b.innerArea
}
// Buffer implements Bufferer interface.
// Draw background and border (if any).
-func (d *Block) Buffer() []Point {
- d.align()
+func (b *Block) Buffer() Buffer {
+ b.Align()
- ps := []Point{}
- if !d.IsDisplay {
- return ps
- }
+ buf := NewBuffer()
+ buf.SetArea(b.area)
+ buf.Fill(' ', ColorDefault, b.Bg)
- if d.HasBorder {
- ps = d.Border.Buffer()
- }
+ b.drawBorder(buf)
+ b.drawBorderLabel(buf)
- for i := 0; i < d.innerWidth; i++ {
- for j := 0; j < d.innerHeight; j++ {
- p := Point{}
- p.X = d.X + 1 + i
- p.Y = d.Y + 1 + j
- p.Ch = ' '
- p.Bg = d.BgColor
- ps = append(ps, p)
- }
- }
- return ps
+ return buf
}
// GetHeight implements GridBufferer.
// It returns current height of the block.
-func (d Block) GetHeight() int {
- return d.Height
+func (b Block) GetHeight() int {
+ return b.Height
}
// SetX implements GridBufferer interface, which sets block's x position.
-func (d *Block) SetX(x int) {
- d.X = x
+func (b *Block) SetX(x int) {
+ b.X = x
}
// SetY implements GridBufferer interface, it sets y position for block.
-func (d *Block) SetY(y int) {
- d.Y = y
+func (b *Block) SetY(y int) {
+ b.Y = y
}
// SetWidth implements GridBuffer interface, it sets block's width.
-func (d *Block) SetWidth(w int) {
- d.Width = w
-}
-
-// chop the overflow parts
-func (d *Block) chopOverflow(ps []Point) []Point {
- nps := make([]Point, 0, len(ps))
- x := d.X
- y := d.Y
- w := d.Width
- h := d.Height
- for _, v := range ps {
- if v.X >= x &&
- v.X < x+w &&
- v.Y >= y &&
- v.Y < y+h {
- nps = append(nps, v)
- }
- }
- return nps
+func (b *Block) SetWidth(w int) {
+ b.Width = w
}
+
+func (b Block) InnerWidth() int {
+ return b.innerArea.Dx()
+}
+
+func (b Block) InnerHeight() int {
+ return b.innerArea.Dy()
+}
+
+func (b Block) InnerX() int {
+ return b.innerArea.Min.X
+}
+
+func (b Block) InnerY() int { return b.innerArea.Min.Y }
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/box_others.go b/Godeps/_workspace/src/github.com/gizak/termui/block_common.go
index bcc3d7ded..0f972cbbd 100644
--- a/Godeps/_workspace/src/github.com/gizak/termui/box_others.go
+++ b/Godeps/_workspace/src/github.com/gizak/termui/block_common.go
@@ -1,4 +1,4 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
@@ -12,3 +12,9 @@ const HORIZONTAL_LINE = '─'
const TOP_LEFT = '┌'
const BOTTOM_RIGHT = '┘'
const BOTTOM_LEFT = '└'
+const VERTICAL_LEFT = '┤'
+const VERTICAL_RIGHT = '├'
+const HORIZONTAL_DOWN = '┬'
+const HORIZONTAL_UP = '┴'
+const QUOTA_LEFT = '«'
+const QUOTA_RIGHT = '»'
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/block_test.go b/Godeps/_workspace/src/github.com/gizak/termui/block_test.go
deleted file mode 100644
index 2de205b21..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/block_test.go
+++ /dev/null
@@ -1,46 +0,0 @@
-package termui
-
-import "testing"
-
-func TestBlock_InnerBounds(t *testing.T) {
- b := NewBlock()
- b.X = 10
- b.Y = 11
- b.Width = 12
- b.Height = 13
-
- assert := func(name string, x, y, w, h int) {
- t.Log(name)
- cx, cy, cw, ch := b.InnerBounds()
- if cx != x {
- t.Errorf("expected x to be %d but got %d", x, cx)
- }
- if cy != y {
- t.Errorf("expected y to be %d but got %d", y, cy)
- }
- if cw != w {
- t.Errorf("expected width to be %d but got %d", w, cw)
- }
- if ch != h {
- t.Errorf("expected height to be %d but got %d", h, ch)
- }
- }
-
- b.HasBorder = false
- assert("no border, no padding", 10, 11, 12, 13)
-
- b.HasBorder = true
- assert("border, no padding", 11, 12, 10, 11)
-
- b.PaddingBottom = 2
- assert("border, 2b padding", 11, 12, 10, 9)
-
- b.PaddingTop = 3
- assert("border, 2b 3t padding", 11, 15, 10, 6)
-
- b.PaddingLeft = 4
- assert("border, 2b 3t 4l padding", 15, 15, 6, 6)
-
- b.PaddingRight = 5
- assert("border, 2b 3t 4l 5r padding", 15, 15, 1, 6)
-}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/box_windows.go b/Godeps/_workspace/src/github.com/gizak/termui/block_windows.go
index dd39019fe..4dbc017de 100644
--- a/Godeps/_workspace/src/github.com/gizak/termui/box_windows.go
+++ b/Godeps/_workspace/src/github.com/gizak/termui/block_windows.go
@@ -1,4 +1,4 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/box.go b/Godeps/_workspace/src/github.com/gizak/termui/box.go
deleted file mode 100644
index 1dcfd8692..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/box.go
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
-// Use of this source code is governed by a MIT license that can
-// be found in the LICENSE file.
-
-package termui
-
-type border struct {
- X int
- Y int
- Width int
- Height int
- FgColor Attribute
- BgColor Attribute
-}
-
-type hline struct {
- X int
- Y int
- Length int
- FgColor Attribute
- BgColor Attribute
-}
-
-type vline struct {
- X int
- Y int
- Length int
- FgColor Attribute
- BgColor Attribute
-}
-
-// Draw a horizontal line.
-func (l hline) Buffer() []Point {
- pts := make([]Point, l.Length)
- for i := 0; i < l.Length; i++ {
- pts[i].X = l.X + i
- pts[i].Y = l.Y
- pts[i].Ch = HORIZONTAL_LINE
- pts[i].Bg = l.BgColor
- pts[i].Fg = l.FgColor
- }
- return pts
-}
-
-// Draw a vertical line.
-func (l vline) Buffer() []Point {
- pts := make([]Point, l.Length)
- for i := 0; i < l.Length; i++ {
- pts[i].X = l.X
- pts[i].Y = l.Y + i
- pts[i].Ch = VERTICAL_LINE
- pts[i].Bg = l.BgColor
- pts[i].Fg = l.FgColor
- }
- return pts
-}
-
-// Draw a box border.
-func (b border) Buffer() []Point {
- if b.Width < 2 || b.Height < 2 {
- return nil
- }
- pts := make([]Point, 2*b.Width+2*b.Height-4)
-
- pts[0].X = b.X
- pts[0].Y = b.Y
- pts[0].Fg = b.FgColor
- pts[0].Bg = b.BgColor
- pts[0].Ch = TOP_LEFT
-
- pts[1].X = b.X + b.Width - 1
- pts[1].Y = b.Y
- pts[1].Fg = b.FgColor
- pts[1].Bg = b.BgColor
- pts[1].Ch = TOP_RIGHT
-
- pts[2].X = b.X
- pts[2].Y = b.Y + b.Height - 1
- pts[2].Fg = b.FgColor
- pts[2].Bg = b.BgColor
- pts[2].Ch = BOTTOM_LEFT
-
- pts[3].X = b.X + b.Width - 1
- pts[3].Y = b.Y + b.Height - 1
- pts[3].Fg = b.FgColor
- pts[3].Bg = b.BgColor
- pts[3].Ch = BOTTOM_RIGHT
-
- copy(pts[4:], (hline{b.X + 1, b.Y, b.Width - 2, b.FgColor, b.BgColor}).Buffer())
- copy(pts[4+b.Width-2:], (hline{b.X + 1, b.Y + b.Height - 1, b.Width - 2, b.FgColor, b.BgColor}).Buffer())
- copy(pts[4+2*b.Width-4:], (vline{b.X, b.Y + 1, b.Height - 2, b.FgColor, b.BgColor}).Buffer())
- copy(pts[4+2*b.Width-4+b.Height-2:], (vline{b.X + b.Width - 1, b.Y + 1, b.Height - 2, b.FgColor, b.BgColor}).Buffer())
-
- return pts
-}
-
-type labeledBorder struct {
- border
- Label string
- LabelFgColor Attribute
- LabelBgColor Attribute
-}
-
-// Draw a box border with label.
-func (lb labeledBorder) Buffer() []Point {
- ps := lb.border.Buffer()
- maxTxtW := lb.Width - 2
- rs := trimStr2Runes(lb.Label, maxTxtW)
-
- for i, j, w := 0, 0, 0; i < len(rs); i++ {
- w = charWidth(rs[i])
- ps = append(ps, newPointWithAttrs(rs[i], lb.X+1+j, lb.Y, lb.LabelFgColor, lb.LabelBgColor))
- j += w
- }
-
- return ps
-}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/buffer.go b/Godeps/_workspace/src/github.com/gizak/termui/buffer.go
new file mode 100644
index 000000000..60e77863a
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gizak/termui/buffer.go
@@ -0,0 +1,106 @@
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Use of this source code is governed by a MIT license that can
+// be found in the LICENSE file.
+
+package termui
+
+import "image"
+
+// Cell is a rune with assigned Fg and Bg
+type Cell struct {
+ Ch rune
+ Fg Attribute
+ Bg Attribute
+}
+
+// Buffer is a renderable rectangle cell data container.
+type Buffer struct {
+ Area image.Rectangle // selected drawing area
+ CellMap map[image.Point]Cell
+}
+
+// At returns the cell at (x,y).
+func (b Buffer) At(x, y int) Cell {
+ return b.CellMap[image.Pt(x, y)]
+}
+
+// Set assigns a char to (x,y)
+func (b Buffer) Set(x, y int, c Cell) {
+ b.CellMap[image.Pt(x, y)] = c
+}
+
+// Bounds returns the domain for which At can return non-zero color.
+func (b Buffer) Bounds() image.Rectangle {
+ x0, y0, x1, y1 := 0, 0, 0, 0
+ for p := range b.CellMap {
+ if p.X > x1 {
+ x1 = p.X
+ }
+ if p.X < x0 {
+ x0 = p.X
+ }
+ if p.Y > y1 {
+ y1 = p.Y
+ }
+ if p.Y < y0 {
+ y0 = p.Y
+ }
+ }
+ return image.Rect(x0, y0, x1, y1)
+}
+
+// SetArea assigns a new rect area to Buffer b.
+func (b *Buffer) SetArea(r image.Rectangle) {
+ b.Area.Max = r.Max
+ b.Area.Min = r.Min
+}
+
+// Sync sets drawing area to the buffer's bound
+func (b Buffer) Sync() {
+ b.SetArea(b.Bounds())
+}
+
+// NewCell returns a new cell
+func NewCell(ch rune, fg, bg Attribute) Cell {
+ return Cell{ch, fg, bg}
+}
+
+// Merge merges bs Buffers onto b
+func (b *Buffer) Merge(bs ...Buffer) {
+ for _, buf := range bs {
+ for p, v := range buf.CellMap {
+ b.Set(p.X, p.Y, v)
+ }
+ b.SetArea(b.Area.Union(buf.Area))
+ }
+}
+
+// NewBuffer returns a new Buffer
+func NewBuffer() Buffer {
+ return Buffer{
+ CellMap: make(map[image.Point]Cell),
+ Area: image.Rectangle{}}
+}
+
+// Fill fills the Buffer b with ch,fg and bg.
+func (b Buffer) Fill(ch rune, fg, bg Attribute) {
+ for x := b.Area.Min.X; x < b.Area.Max.X; x++ {
+ for y := b.Area.Min.Y; y < b.Area.Max.Y; y++ {
+ b.Set(x, y, Cell{ch, fg, bg})
+ }
+ }
+}
+
+// NewFilledBuffer returns a new Buffer filled with ch, fb and bg.
+func NewFilledBuffer(x0, y0, x1, y1 int, ch rune, fg, bg Attribute) Buffer {
+ buf := NewBuffer()
+ buf.Area.Min = image.Pt(x0, y0)
+ buf.Area.Max = image.Pt(x1, y1)
+
+ for x := buf.Area.Min.X; x < buf.Area.Max.X; x++ {
+ for y := buf.Area.Min.Y; y < buf.Area.Max.Y; y++ {
+ buf.Set(x, y, Cell{ch, fg, bg})
+ }
+ }
+ return buf
+}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/canvas.go b/Godeps/_workspace/src/github.com/gizak/termui/canvas.go
index 614635ee4..4173780f3 100644
--- a/Godeps/_workspace/src/github.com/gizak/termui/canvas.go
+++ b/Godeps/_workspace/src/github.com/gizak/termui/canvas.go
@@ -1,4 +1,4 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
@@ -63,12 +63,10 @@ func (c Canvas) Unset(x, y int) {
}
// Buffer returns un-styled points
-func (c Canvas) Buffer() []Point {
- ps := make([]Point, len(c))
- i := 0
+func (c Canvas) Buffer() Buffer {
+ buf := NewBuffer()
for k, v := range c {
- ps[i] = newPoint(v+brailleBase, k[0], k[1])
- i++
+ buf.Set(k[0], k[1], Cell{Ch: v + brailleBase})
}
- return ps
+ return buf
}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/canvas_test.go b/Godeps/_workspace/src/github.com/gizak/termui/canvas_test.go
deleted file mode 100644
index 021949ced..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/canvas_test.go
+++ /dev/null
@@ -1,55 +0,0 @@
-package termui
-
-import (
- "testing"
-
- "github.com/davecgh/go-spew/spew"
-)
-
-func TestCanvasSet(t *testing.T) {
- c := NewCanvas()
- c.Set(0, 0)
- c.Set(0, 1)
- c.Set(0, 2)
- c.Set(0, 3)
- c.Set(1, 3)
- c.Set(2, 3)
- c.Set(3, 3)
- c.Set(4, 3)
- c.Set(5, 3)
- spew.Dump(c)
-}
-
-func TestCanvasUnset(t *testing.T) {
- c := NewCanvas()
- c.Set(0, 0)
- c.Set(0, 1)
- c.Set(0, 2)
- c.Unset(0, 2)
- spew.Dump(c)
- c.Unset(0, 3)
- spew.Dump(c)
-}
-
-func TestCanvasBuffer(t *testing.T) {
- c := NewCanvas()
- c.Set(0, 0)
- c.Set(0, 1)
- c.Set(0, 2)
- c.Set(0, 3)
- c.Set(1, 3)
- c.Set(2, 3)
- c.Set(3, 3)
- c.Set(4, 3)
- c.Set(5, 3)
- c.Set(6, 3)
- c.Set(7, 2)
- c.Set(8, 1)
- c.Set(9, 0)
- bufs := c.Buffer()
- rs := make([]rune, len(bufs))
- for i, v := range bufs {
- rs[i] = v.Ch
- }
- spew.Dump(string(rs))
-}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/config b/Godeps/_workspace/src/github.com/gizak/termui/config
new file mode 100644
index 000000000..18fd6a401
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gizak/termui/config
@@ -0,0 +1,26 @@
+#!/usr/bin/env perl6
+
+use v6;
+
+my $copyright = '// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Use of this source code is governed by a MIT license that can
+// be found in the LICENSE file.
+
+';
+
+sub MAIN('update-docstr', Str $srcp) {
+ if $srcp.IO.f {
+ $_ = $srcp.IO.slurp;
+ if m/^ \/\/\s Copyright .+? \n\n/ {
+ unless ~$/ eq $copyright {
+ s/^ \/\/\s Copyright .+? \n\n /$copyright/;
+ spurt $srcp, $_;
+ say "[updated] doc string for:"~$srcp;
+ }
+ } else {
+ say "[added] doc string for "~$srcp~" (no match found)";
+ $_ = $copyright ~ $_;
+ spurt $srcp, $_;
+ }
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/debug/debuger.go b/Godeps/_workspace/src/github.com/gizak/termui/debug/debuger.go
new file mode 100644
index 000000000..f723b9686
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gizak/termui/debug/debuger.go
@@ -0,0 +1,117 @@
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Use of this source code is governed by a MIT license that can
+// be found in the LICENSE file.
+
+package debug
+
+import (
+ "fmt"
+ "net/http"
+
+ "golang.org/x/net/websocket"
+)
+
+type Server struct {
+ Port string
+ Addr string
+ Path string
+ Msg chan string
+ chs []chan string
+}
+
+type Client struct {
+ Port string
+ Addr string
+ Path string
+ ws *websocket.Conn
+}
+
+var defaultPort = ":8080"
+
+func NewServer() *Server {
+ return &Server{
+ Port: defaultPort,
+ Addr: "localhost",
+ Path: "/echo",
+ Msg: make(chan string),
+ chs: make([]chan string, 0),
+ }
+}
+
+func NewClient() Client {
+ return Client{
+ Port: defaultPort,
+ Addr: "localhost",
+ Path: "/echo",
+ }
+}
+
+func (c Client) ConnectAndListen() error {
+ ws, err := websocket.Dial("ws://"+c.Addr+c.Port+c.Path, "", "http://"+c.Addr)
+ if err != nil {
+ return err
+ }
+ defer ws.Close()
+
+ var m string
+ for {
+ err := websocket.Message.Receive(ws, &m)
+ if err != nil {
+ fmt.Print(err)
+ return err
+ }
+ fmt.Print(m)
+ }
+}
+
+func (s *Server) ListenAndServe() error {
+ http.Handle(s.Path, websocket.Handler(func(ws *websocket.Conn) {
+ defer ws.Close()
+
+ mc := make(chan string)
+ s.chs = append(s.chs, mc)
+
+ for m := range mc {
+ websocket.Message.Send(ws, m)
+ }
+ }))
+
+ go func() {
+ for msg := range s.Msg {
+ for _, c := range s.chs {
+ go func(a chan string) {
+ a <- msg
+ }(c)
+ }
+ }
+ }()
+
+ return http.ListenAndServe(s.Port, nil)
+}
+
+func (s *Server) Log(msg string) {
+ go func() { s.Msg <- msg }()
+}
+
+func (s *Server) Logf(format string, a ...interface{}) {
+ s.Log(fmt.Sprintf(format, a...))
+}
+
+var DefaultServer = NewServer()
+var DefaultClient = NewClient()
+
+func ListenAndServe() error {
+ return DefaultServer.ListenAndServe()
+}
+
+func ConnectAndListen() error {
+ return DefaultClient.ConnectAndListen()
+}
+
+func Log(msg string) {
+ DefaultServer.Log(msg)
+}
+
+func Logf(format string, a ...interface{}) {
+ DefaultServer.Logf(format, a...)
+}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/doc.go b/Godeps/_workspace/src/github.com/gizak/termui/doc.go
index 43f886f55..b80e46415 100644
--- a/Godeps/_workspace/src/github.com/gizak/termui/doc.go
+++ b/Godeps/_workspace/src/github.com/gizak/termui/doc.go
@@ -1,4 +1,4 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/events.go b/Godeps/_workspace/src/github.com/gizak/termui/events.go
index 23a189b56..177bbb4b0 100644
--- a/Godeps/_workspace/src/github.com/gizak/termui/events.go
+++ b/Godeps/_workspace/src/github.com/gizak/termui/events.go
@@ -1,219 +1,316 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
-//
-// Portions of this file uses [termbox-go](https://github.com/nsf/termbox-go/blob/54b74d087b7c397c402d0e3b66d2ccb6eaf5c2b4/api_common.go)
-// by [authors](https://github.com/nsf/termbox-go/blob/master/AUTHORS)
-// under [license](https://github.com/nsf/termbox-go/blob/master/LICENSE)
package termui
-import "github.com/nsf/termbox-go"
+import (
+ "path"
+ "strconv"
+ "sync"
+ "time"
-/***********************************termbox-go**************************************/
-
-type (
- EventType uint8
- Modifier uint8
- Key uint16
+ "github.com/nsf/termbox-go"
)
-// This type represents a termbox event. The 'Mod', 'Key' and 'Ch' fields are
-// valid if 'Type' is EventKey. The 'Width' and 'Height' fields are valid if
-// 'Type' is EventResize. The 'Err' field is valid if 'Type' is EventError.
type Event struct {
- Type EventType // one of Event* constants
- Mod Modifier // one of Mod* constants or 0
- Key Key // one of Key* constants, invalid if 'Ch' is not 0
- Ch rune // a unicode character
- Width int // width of the screen
- Height int // height of the screen
- Err error // error in case if input failed
- MouseX int // x coord of mouse
- MouseY int // y coord of mouse
- N int // number of bytes written when getting a raw event
-}
-
-const (
- KeyF1 Key = 0xFFFF - iota
- KeyF2
- KeyF3
- KeyF4
- KeyF5
- KeyF6
- KeyF7
- KeyF8
- KeyF9
- KeyF10
- KeyF11
- KeyF12
- KeyInsert
- KeyDelete
- KeyHome
- KeyEnd
- KeyPgup
- KeyPgdn
- KeyArrowUp
- KeyArrowDown
- KeyArrowLeft
- KeyArrowRight
- key_min // see terminfo
- MouseLeft
- MouseMiddle
- MouseRight
-)
+ Type string
+ Path string
+ From string
+ To string
+ Data interface{}
+ Time int64
+}
-const (
- KeyCtrlTilde Key = 0x00
- KeyCtrl2 Key = 0x00
- KeyCtrlSpace Key = 0x00
- KeyCtrlA Key = 0x01
- KeyCtrlB Key = 0x02
- KeyCtrlC Key = 0x03
- KeyCtrlD Key = 0x04
- KeyCtrlE Key = 0x05
- KeyCtrlF Key = 0x06
- KeyCtrlG Key = 0x07
- KeyBackspace Key = 0x08
- KeyCtrlH Key = 0x08
- KeyTab Key = 0x09
- KeyCtrlI Key = 0x09
- KeyCtrlJ Key = 0x0A
- KeyCtrlK Key = 0x0B
- KeyCtrlL Key = 0x0C
- KeyEnter Key = 0x0D
- KeyCtrlM Key = 0x0D
- KeyCtrlN Key = 0x0E
- KeyCtrlO Key = 0x0F
- KeyCtrlP Key = 0x10
- KeyCtrlQ Key = 0x11
- KeyCtrlR Key = 0x12
- KeyCtrlS Key = 0x13
- KeyCtrlT Key = 0x14
- KeyCtrlU Key = 0x15
- KeyCtrlV Key = 0x16
- KeyCtrlW Key = 0x17
- KeyCtrlX Key = 0x18
- KeyCtrlY Key = 0x19
- KeyCtrlZ Key = 0x1A
- KeyEsc Key = 0x1B
- KeyCtrlLsqBracket Key = 0x1B
- KeyCtrl3 Key = 0x1B
- KeyCtrl4 Key = 0x1C
- KeyCtrlBackslash Key = 0x1C
- KeyCtrl5 Key = 0x1D
- KeyCtrlRsqBracket Key = 0x1D
- KeyCtrl6 Key = 0x1E
- KeyCtrl7 Key = 0x1F
- KeyCtrlSlash Key = 0x1F
- KeyCtrlUnderscore Key = 0x1F
- KeySpace Key = 0x20
- KeyBackspace2 Key = 0x7F
- KeyCtrl8 Key = 0x7F
-)
+var sysEvtChs []chan Event
-// Alt modifier constant, see Event.Mod field and SetInputMode function.
-const (
- ModAlt Modifier = 0x01
-)
+type EvtKbd struct {
+ KeyStr string
+}
-// Event type. See Event.Type field.
-const (
- EventKey EventType = iota
- EventResize
- EventMouse
- EventError
- EventInterrupt
- EventRaw
- EventNone
-)
+func evtKbd(e termbox.Event) EvtKbd {
+ ek := EvtKbd{}
-/**************************************end**************************************/
+ k := string(e.Ch)
+ pre := ""
+ mod := ""
-// convert termbox.Event to termui.Event
-func uiEvt(e termbox.Event) Event {
- event := Event{}
- event.Type = EventType(e.Type)
- event.Mod = Modifier(e.Mod)
- event.Key = Key(e.Key)
- event.Ch = e.Ch
- event.Width = e.Width
- event.Height = e.Height
- event.Err = e.Err
- event.MouseX = e.MouseX
- event.MouseY = e.MouseY
- event.N = e.N
+ if e.Mod == termbox.ModAlt {
+ mod = "M-"
+ }
+ if e.Ch == 0 {
+ if e.Key > 0xFFFF-12 {
+ k = "<f" + strconv.Itoa(0xFFFF-int(e.Key)+1) + ">"
+ } else if e.Key > 0xFFFF-25 {
+ ks := []string{"<insert>", "<delete>", "<home>", "<end>", "<previous>", "<next>", "<up>", "<down>", "<left>", "<right>"}
+ k = ks[0xFFFF-int(e.Key)-12]
+ }
- return event
+ if e.Key <= 0x7F {
+ pre = "C-"
+ k = string('a' - 1 + int(e.Key))
+ kmap := map[termbox.Key][2]string{
+ termbox.KeyCtrlSpace: {"C-", "<space>"},
+ termbox.KeyBackspace: {"", "<backspace>"},
+ termbox.KeyTab: {"", "<tab>"},
+ termbox.KeyEnter: {"", "<enter>"},
+ termbox.KeyEsc: {"", "<escape>"},
+ termbox.KeyCtrlBackslash: {"C-", "\\"},
+ termbox.KeyCtrlSlash: {"C-", "/"},
+ termbox.KeySpace: {"", "<space>"},
+ termbox.KeyCtrl8: {"C-", "8"},
+ }
+ if sk, ok := kmap[e.Key]; ok {
+ pre = sk[0]
+ k = sk[1]
+ }
+ }
+ }
+
+ ek.KeyStr = pre + mod + k
+ return ek
}
-var evtChs = make([]chan Event, 0)
+func crtTermboxEvt(e termbox.Event) Event {
+ systypemap := map[termbox.EventType]string{
+ termbox.EventKey: "keyboard",
+ termbox.EventResize: "window",
+ termbox.EventMouse: "mouse",
+ termbox.EventError: "error",
+ termbox.EventInterrupt: "interrupt",
+ }
+ ne := Event{From: "/sys", Time: time.Now().Unix()}
+ typ := e.Type
+ ne.Type = systypemap[typ]
+
+ switch typ {
+ case termbox.EventKey:
+ kbd := evtKbd(e)
+ ne.Path = "/sys/kbd/" + kbd.KeyStr
+ ne.Data = kbd
+ case termbox.EventResize:
+ wnd := EvtWnd{}
+ wnd.Width = e.Width
+ wnd.Height = e.Height
+ ne.Path = "/sys/wnd/resize"
+ ne.Data = wnd
+ case termbox.EventError:
+ err := EvtErr(e.Err)
+ ne.Path = "/sys/err"
+ ne.Data = err
+ case termbox.EventMouse:
+ m := EvtMouse{}
+ m.X = e.MouseX
+ m.Y = e.MouseY
+ ne.Path = "/sys/mouse"
+ ne.Data = m
+ }
+ return ne
+}
-// EventCh returns an output-only event channel.
-// This function can be called many times (multiplexer).
-func EventCh() <-chan Event {
- out := make(chan Event)
- evtChs = append(evtChs, out)
- return out
+type EvtWnd struct {
+ Width int
+ Height int
}
-// turn on event listener
-func evtListen() {
- go func() {
- for {
- e := termbox.PollEvent()
- // dispatch
- for _, c := range evtChs {
- go func(ch chan Event) {
- ch <- uiEvt(e)
- }(c)
- }
+type EvtMouse struct {
+ X int
+ Y int
+ Press string
+}
+
+type EvtErr error
+
+func hookTermboxEvt() {
+ for {
+ e := termbox.PollEvent()
+
+ for _, c := range sysEvtChs {
+ go func(ch chan Event) {
+ ch <- crtTermboxEvt(e)
+ }(c)
}
+ }
+}
+
+func NewSysEvtCh() chan Event {
+ ec := make(chan Event)
+ sysEvtChs = append(sysEvtChs, ec)
+ return ec
+}
+
+var DefaultEvtStream = NewEvtStream()
+
+type EvtStream struct {
+ sync.RWMutex
+ srcMap map[string]chan Event
+ stream chan Event
+ wg sync.WaitGroup
+ sigStopLoop chan Event
+ Handlers map[string]func(Event)
+ hook func(Event)
+}
+
+func NewEvtStream() *EvtStream {
+ return &EvtStream{
+ srcMap: make(map[string]chan Event),
+ stream: make(chan Event),
+ Handlers: make(map[string]func(Event)),
+ sigStopLoop: make(chan Event),
+ }
+}
+
+func (es *EvtStream) Init() {
+ es.Merge("internal", es.sigStopLoop)
+ go func() {
+ es.wg.Wait()
+ close(es.stream)
}()
}
-/*
-// EventHandlers is a handler sequence
-var EventHandlers []func(Event)
+func cleanPath(p string) string {
+ if p == "" {
+ return "/"
+ }
+ if p[0] != '/' {
+ p = "/" + p
+ }
+ return path.Clean(p)
+}
-var signalQuit = make(chan bool)
+func isPathMatch(pattern, path string) bool {
+ if len(pattern) == 0 {
+ return false
+ }
+ n := len(pattern)
+ return len(path) >= n && path[0:n] == pattern
+}
+
+func (es *EvtStream) Merge(name string, ec chan Event) {
+ es.Lock()
+ defer es.Unlock()
+
+ es.wg.Add(1)
+ es.srcMap[name] = ec
-// Quit sends quit signal to terminate termui
-func Quit() {
- signalQuit <- true
+ go func(a chan Event) {
+ for n := range a {
+ n.From = name
+ es.stream <- n
+ }
+ es.wg.Done()
+ }(ec)
}
-// Wait listening to signalQuit, block operation.
-func Wait() {
- <-signalQuit
+func (es *EvtStream) Handle(path string, handler func(Event)) {
+ es.Handlers[cleanPath(path)] = handler
}
-// RegEvtHandler register function into TSEventHandler sequence.
-func RegEvtHandler(fn func(Event)) {
- EventHandlers = append(EventHandlers, fn)
+func findMatch(mux map[string]func(Event), path string) string {
+ n := -1
+ pattern := ""
+ for m := range mux {
+ if !isPathMatch(m, path) {
+ continue
+ }
+ if len(m) > n {
+ pattern = m
+ n = len(m)
+ }
+ }
+ return pattern
+
}
-// EventLoop handles all events and
-// redirects every event to callbacks in EventHandlers
-func EventLoop() {
- evt := make(chan termbox.Event)
+func (es *EvtStream) match(path string) string {
+ return findMatch(es.Handlers, path)
+}
+
+func (es *EvtStream) Hook(f func(Event)) {
+ es.hook = f
+}
+func (es *EvtStream) Loop() {
+ for e := range es.stream {
+ switch e.Path {
+ case "/sig/stoploop":
+ return
+ }
+ go func(a Event) {
+ es.RLock()
+ defer es.RUnlock()
+ if pattern := es.match(a.Path); pattern != "" {
+ es.Handlers[pattern](a)
+ }
+ }(e)
+ if es.hook != nil {
+ es.hook(e)
+ }
+ }
+}
+
+func (es *EvtStream) StopLoop() {
go func() {
- for {
- evt <- termbox.PollEvent()
+ e := Event{
+ Path: "/sig/stoploop",
}
+ es.sigStopLoop <- e
}()
+}
- for {
- select {
- case c := <-signalQuit:
- defer func() { signalQuit <- c }()
- return
- case e := <-evt:
- for _, fn := range EventHandlers {
- fn(uiEvt(e))
+func Merge(name string, ec chan Event) {
+ DefaultEvtStream.Merge(name, ec)
+}
+
+func Handle(path string, handler func(Event)) {
+ DefaultEvtStream.Handle(path, handler)
+}
+
+func Loop() {
+ DefaultEvtStream.Loop()
+}
+
+func StopLoop() {
+ DefaultEvtStream.StopLoop()
+}
+
+type EvtTimer struct {
+ Duration time.Duration
+ Count uint64
+}
+
+func NewTimerCh(du time.Duration) chan Event {
+ t := make(chan Event)
+
+ go func(a chan Event) {
+ n := uint64(0)
+ for {
+ n++
+ time.Sleep(du)
+ e := Event{}
+ e.Type = "timer"
+ e.Path = "/timer/" + du.String()
+ e.Time = time.Now().Unix()
+ e.Data = EvtTimer{
+ Duration: du,
+ Count: n,
}
+ t <- e
+
}
- }
+ }(t)
+ return t
+}
+
+var DefualtHandler = func(e Event) {
+}
+
+var usrEvtCh = make(chan Event)
+
+func SendCustomEvt(path string, data interface{}) {
+ e := Event{}
+ e.Path = path
+ e.Data = data
+ e.Time = time.Now().Unix()
+ usrEvtCh <- e
}
-*/
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/events_test.go b/Godeps/_workspace/src/github.com/gizak/termui/events_test.go
deleted file mode 100644
index 1137b1d26..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/events_test.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
-// Use of this source code is governed by a MIT license that can
-// be found in the LICENSE file.
-//
-// Portions of this file uses [termbox-go](https://github.com/nsf/termbox-go/blob/54b74d087b7c397c402d0e3b66d2ccb6eaf5c2b4/api_common.go)
-// by [authors](https://github.com/nsf/termbox-go/blob/master/AUTHORS)
-// under [license](https://github.com/nsf/termbox-go/blob/master/LICENSE)
-
-package termui
-
-import (
- "errors"
- "testing"
-
- termbox "github.com/nsf/termbox-go"
- "github.com/stretchr/testify/assert"
-)
-
-type boxEvent termbox.Event
-
-func TestUiEvt(t *testing.T) {
- err := errors.New("This is a mock error")
- event := boxEvent{3, 5, 2, 'H', 200, 500, err, 50, 30, 2}
- expetced := Event{3, 5, 2, 'H', 200, 500, err, 50, 30, 2}
-
- // We need to do that ugly casting so that vet does not complain
- assert.Equal(t, uiEvt(termbox.Event(event)), expetced)
-}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/example/barchart.go b/Godeps/_workspace/src/github.com/gizak/termui/example/barchart.go
deleted file mode 100644
index 83947f580..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/example/barchart.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
-// Use of this source code is governed by a MIT license that can
-// be found in the LICENSE file.
-
-// +build ignore
-
-package main
-
-import "github.com/gizak/termui"
-
-func main() {
- err := termui.Init()
- if err != nil {
- panic(err)
- }
- defer termui.Close()
-
- termui.UseTheme("helloworld")
-
- bc := termui.NewBarChart()
- data := []int{3, 2, 5, 3, 9, 5, 3, 2, 5, 8, 3, 2, 4, 5, 3, 2, 5, 7, 5, 3, 2, 6, 7, 4, 6, 3, 6, 7, 8, 3, 6, 4, 5, 3, 2, 4, 6, 4, 8, 5, 9, 4, 3, 6, 5, 3, 6}
- bclabels := []string{"S0", "S1", "S2", "S3", "S4", "S5"}
- bc.Border.Label = "Bar Chart"
- bc.Data = data
- bc.Width = 26
- bc.Height = 10
- bc.DataLabels = bclabels
- bc.TextColor = termui.ColorGreen
- bc.BarColor = termui.ColorRed
- bc.NumColor = termui.ColorYellow
-
- termui.Render(bc)
-
- <-termui.EventCh()
-}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/example/barchart.png b/Godeps/_workspace/src/github.com/gizak/termui/example/barchart.png
deleted file mode 100644
index a37912f7f..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/example/barchart.png
+++ /dev/null
Binary files differ
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/example/dashboard.gif b/Godeps/_workspace/src/github.com/gizak/termui/example/dashboard.gif
deleted file mode 100644
index 8e1859c72..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/example/dashboard.gif
+++ /dev/null
Binary files differ
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/example/dashboard.go b/Godeps/_workspace/src/github.com/gizak/termui/example/dashboard.go
deleted file mode 100644
index c14bb4413..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/example/dashboard.go
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
-// Use of this source code is governed by a MIT license that can
-// be found in the LICENSE file.
-
-// +build ignore
-
-package main
-
-import ui "github.com/gizak/termui"
-import "math"
-
-import "time"
-
-func main() {
- err := ui.Init()
- if err != nil {
- panic(err)
- }
- defer ui.Close()
-
- p := ui.NewPar(":PRESS q TO QUIT DEMO")
- p.Height = 3
- p.Width = 50
- p.TextFgColor = ui.ColorWhite
- p.Border.Label = "Text Box"
- p.Border.FgColor = ui.ColorCyan
-
- strs := []string{"[0] gizak/termui", "[1] editbox.go", "[2] iterrupt.go", "[3] keyboard.go", "[4] output.go", "[5] random_out.go", "[6] dashboard.go", "[7] nsf/termbox-go"}
- list := ui.NewList()
- list.Items = strs
- list.ItemFgColor = ui.ColorYellow
- list.Border.Label = "List"
- list.Height = 7
- list.Width = 25
- list.Y = 4
-
- g := ui.NewGauge()
- g.Percent = 50
- g.Width = 50
- g.Height = 3
- g.Y = 11
- g.Border.Label = "Gauge"
- g.BarColor = ui.ColorRed
- g.Border.FgColor = ui.ColorWhite
- g.Border.LabelFgColor = ui.ColorCyan
-
- spark := ui.Sparkline{}
- spark.Height = 1
- spark.Title = "srv 0:"
- spdata := []int{4, 2, 1, 6, 3, 9, 1, 4, 2, 15, 14, 9, 8, 6, 10, 13, 15, 12, 10, 5, 3, 6, 1, 7, 10, 10, 14, 13, 6, 4, 2, 1, 6, 3, 9, 1, 4, 2, 15, 14, 9, 8, 6, 10, 13, 15, 12, 10, 5, 3, 6, 1, 7, 10, 10, 14, 13, 6, 4, 2, 1, 6, 3, 9, 1, 4, 2, 15, 14, 9, 8, 6, 10, 13, 15, 12, 10, 5, 3, 6, 1, 7, 10, 10, 14, 13, 6, 4, 2, 1, 6, 3, 9, 1, 4, 2, 15, 14, 9, 8, 6, 10, 13, 15, 12, 10, 5, 3, 6, 1, 7, 10, 10, 14, 13, 6}
- spark.Data = spdata
- spark.LineColor = ui.ColorCyan
- spark.TitleColor = ui.ColorWhite
-
- spark1 := ui.Sparkline{}
- spark1.Height = 1
- spark1.Title = "srv 1:"
- spark1.Data = spdata
- spark1.TitleColor = ui.ColorWhite
- spark1.LineColor = ui.ColorRed
-
- sp := ui.NewSparklines(spark, spark1)
- sp.Width = 25
- sp.Height = 7
- sp.Border.Label = "Sparkline"
- sp.Y = 4
- sp.X = 25
-
- sinps := (func() []float64 {
- n := 220
- ps := make([]float64, n)
- for i := range ps {
- ps[i] = 1 + math.Sin(float64(i)/5)
- }
- return ps
- })()
-
- lc := ui.NewLineChart()
- lc.Border.Label = "dot-mode Line Chart"
- lc.Data = sinps
- lc.Width = 50
- lc.Height = 11
- lc.X = 0
- lc.Y = 14
- lc.AxesColor = ui.ColorWhite
- lc.LineColor = ui.ColorRed | ui.AttrBold
- lc.Mode = "dot"
-
- bc := ui.NewBarChart()
- bcdata := []int{3, 2, 5, 3, 9, 5, 3, 2, 5, 8, 3, 2, 4, 5, 3, 2, 5, 7, 5, 3, 2, 6, 7, 4, 6, 3, 6, 7, 8, 3, 6, 4, 5, 3, 2, 4, 6, 4, 8, 5, 9, 4, 3, 6, 5, 3, 6}
- bclabels := []string{"S0", "S1", "S2", "S3", "S4", "S5"}
- bc.Border.Label = "Bar Chart"
- bc.Width = 26
- bc.Height = 10
- bc.X = 51
- bc.Y = 0
- bc.DataLabels = bclabels
- bc.BarColor = ui.ColorGreen
- bc.NumColor = ui.ColorBlack
-
- lc1 := ui.NewLineChart()
- lc1.Border.Label = "braille-mode Line Chart"
- lc1.Data = sinps
- lc1.Width = 26
- lc1.Height = 11
- lc1.X = 51
- lc1.Y = 14
- lc1.AxesColor = ui.ColorWhite
- lc1.LineColor = ui.ColorYellow | ui.AttrBold
-
- p1 := ui.NewPar("Hey!\nI am a borderless block!")
- p1.HasBorder = false
- p1.Width = 26
- p1.Height = 2
- p1.TextFgColor = ui.ColorMagenta
- p1.X = 52
- p1.Y = 11
-
- draw := func(t int) {
- g.Percent = t % 101
- list.Items = strs[t%9:]
- sp.Lines[0].Data = spdata[:30+t%50]
- sp.Lines[1].Data = spdata[:35+t%50]
- lc.Data = sinps[t/2:]
- lc1.Data = sinps[2*t:]
- bc.Data = bcdata[t/2%10:]
- ui.Render(p, list, g, sp, lc, bc, lc1, p1)
- }
-
- evt := ui.EventCh()
-
- i := 0
- for {
- select {
- case e := <-evt:
- if e.Type == ui.EventKey && e.Ch == 'q' {
- return
- }
- default:
- draw(i)
- i++
- if i == 102 {
- return
- }
- time.Sleep(time.Second / 2)
- }
- }
-}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/example/gauge.go b/Godeps/_workspace/src/github.com/gizak/termui/example/gauge.go
deleted file mode 100644
index b7033580f..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/example/gauge.go
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
-// Use of this source code is governed by a MIT license that can
-// be found in the LICENSE file.
-
-// +build ignore
-
-package main
-
-import "github.com/gizak/termui"
-
-func main() {
- err := termui.Init()
- if err != nil {
- panic(err)
- }
- defer termui.Close()
-
- termui.UseTheme("helloworld")
-
- g0 := termui.NewGauge()
- g0.Percent = 40
- g0.Width = 50
- g0.Height = 3
- g0.Border.Label = "Slim Gauge"
- g0.BarColor = termui.ColorRed
- g0.Border.FgColor = termui.ColorWhite
- g0.Border.LabelFgColor = termui.ColorCyan
-
- g2 := termui.NewGauge()
- g2.Percent = 60
- g2.Width = 50
- g2.Height = 3
- g2.PercentColor = termui.ColorBlue
- g2.Y = 3
- g2.Border.Label = "Slim Gauge"
- g2.BarColor = termui.ColorYellow
- g2.Border.FgColor = termui.ColorWhite
-
- g1 := termui.NewGauge()
- g1.Percent = 30
- g1.Width = 50
- g1.Height = 5
- g1.Y = 6
- g1.Border.Label = "Big Gauge"
- g1.PercentColor = termui.ColorYellow
- g1.BarColor = termui.ColorGreen
- g1.Border.FgColor = termui.ColorWhite
- g1.Border.LabelFgColor = termui.ColorMagenta
-
- g3 := termui.NewGauge()
- g3.Percent = 50
- g3.Width = 50
- g3.Height = 3
- g3.Y = 11
- g3.Border.Label = "Gauge with custom label"
- g3.Label = "{{percent}}% (100MBs free)"
- g3.LabelAlign = termui.AlignRight
-
- termui.Render(g0, g1, g2, g3)
-
- <-termui.EventCh()
-}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/example/gauge.png b/Godeps/_workspace/src/github.com/gizak/termui/example/gauge.png
deleted file mode 100644
index 5c20e6e8a..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/example/gauge.png
+++ /dev/null
Binary files differ
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/example/grid.gif b/Godeps/_workspace/src/github.com/gizak/termui/example/grid.gif
deleted file mode 100644
index 7490043de..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/example/grid.gif
+++ /dev/null
Binary files differ
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/example/grid.go b/Godeps/_workspace/src/github.com/gizak/termui/example/grid.go
deleted file mode 100644
index 49121411f..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/example/grid.go
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
-// Use of this source code is governed by a MIT license that can
-// be found in the LICENSE file.
-
-// +build ignore
-
-package main
-
-import ui "github.com/gizak/termui"
-import "math"
-import "time"
-
-func main() {
- err := ui.Init()
- if err != nil {
- panic(err)
- }
- defer ui.Close()
-
- sinps := (func() []float64 {
- n := 400
- ps := make([]float64, n)
- for i := range ps {
- ps[i] = 1 + math.Sin(float64(i)/5)
- }
- return ps
- })()
- sinpsint := (func() []int {
- ps := make([]int, len(sinps))
- for i, v := range sinps {
- ps[i] = int(100*v + 10)
- }
- return ps
- })()
-
- ui.UseTheme("helloworld")
-
- spark := ui.Sparkline{}
- spark.Height = 8
- spdata := sinpsint
- spark.Data = spdata[:100]
- spark.LineColor = ui.ColorCyan
- spark.TitleColor = ui.ColorWhite
-
- sp := ui.NewSparklines(spark)
- sp.Height = 11
- sp.Border.Label = "Sparkline"
-
- lc := ui.NewLineChart()
- lc.Border.Label = "braille-mode Line Chart"
- lc.Data = sinps
- lc.Height = 11
- lc.AxesColor = ui.ColorWhite
- lc.LineColor = ui.ColorYellow | ui.AttrBold
-
- gs := make([]*ui.Gauge, 3)
- for i := range gs {
- gs[i] = ui.NewGauge()
- gs[i].Height = 2
- gs[i].HasBorder = false
- gs[i].Percent = i * 10
- gs[i].PaddingBottom = 1
- gs[i].BarColor = ui.ColorRed
- }
-
- ls := ui.NewList()
- ls.HasBorder = false
- ls.Items = []string{
- "[1] Downloading File 1",
- "", // == \newline
- "[2] Downloading File 2",
- "",
- "[3] Uploading File 3",
- }
- ls.Height = 5
-
- par := ui.NewPar("<> This row has 3 columns\n<- Widgets can be stacked up like left side\n<- Stacked widgets are treated as a single widget")
- par.Height = 5
- par.Border.Label = "Demonstration"
-
- // build layout
- ui.Body.AddRows(
- ui.NewRow(
- ui.NewCol(6, 0, sp),
- ui.NewCol(6, 0, lc)),
- ui.NewRow(
- ui.NewCol(3, 0, ls),
- ui.NewCol(3, 0, gs[0], gs[1], gs[2]),
- ui.NewCol(6, 0, par)))
-
- // calculate layout
- ui.Body.Align()
-
- done := make(chan bool)
- redraw := make(chan bool)
-
- update := func() {
- for i := 0; i < 103; i++ {
- for _, g := range gs {
- g.Percent = (g.Percent + 3) % 100
- }
-
- sp.Lines[0].Data = spdata[:100+i]
- lc.Data = sinps[2*i:]
-
- time.Sleep(time.Second / 2)
- redraw <- true
- }
- done <- true
- }
-
- evt := ui.EventCh()
-
- ui.Render(ui.Body)
- go update()
-
- for {
- select {
- case e := <-evt:
- if e.Type == ui.EventKey && e.Ch == 'q' {
- return
- }
- if e.Type == ui.EventResize {
- ui.Body.Width = ui.TermWidth()
- ui.Body.Align()
- go func() { redraw <- true }()
- }
- case <-done:
- return
- case <-redraw:
- ui.Render(ui.Body)
- }
- }
-}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/example/linechart.go b/Godeps/_workspace/src/github.com/gizak/termui/example/linechart.go
deleted file mode 100644
index 1db543496..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/example/linechart.go
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
-// Use of this source code is governed by a MIT license that can
-// be found in the LICENSE file.
-
-// +build ignore
-
-package main
-
-import (
- "math"
-
- "github.com/gizak/termui"
-)
-
-func main() {
- err := termui.Init()
- if err != nil {
- panic(err)
- }
- defer termui.Close()
-
- termui.UseTheme("helloworld")
-
- sinps := (func() []float64 {
- n := 220
- ps := make([]float64, n)
- for i := range ps {
- ps[i] = 1 + math.Sin(float64(i)/5)
- }
- return ps
- })()
-
- lc0 := termui.NewLineChart()
- lc0.Border.Label = "braille-mode Line Chart"
- lc0.Data = sinps
- lc0.Width = 50
- lc0.Height = 12
- lc0.X = 0
- lc0.Y = 0
- lc0.AxesColor = termui.ColorWhite
- lc0.LineColor = termui.ColorGreen | termui.AttrBold
-
- lc1 := termui.NewLineChart()
- lc1.Border.Label = "dot-mode Line Chart"
- lc1.Mode = "dot"
- lc1.Data = sinps
- lc1.Width = 26
- lc1.Height = 12
- lc1.X = 51
- lc1.DotStyle = '+'
- lc1.AxesColor = termui.ColorWhite
- lc1.LineColor = termui.ColorYellow | termui.AttrBold
-
- lc2 := termui.NewLineChart()
- lc2.Border.Label = "dot-mode Line Chart"
- lc2.Mode = "dot"
- lc2.Data = sinps[4:]
- lc2.Width = 77
- lc2.Height = 16
- lc2.X = 0
- lc2.Y = 12
- lc2.AxesColor = termui.ColorWhite
- lc2.LineColor = termui.ColorCyan | termui.AttrBold
-
- termui.Render(lc0, lc1, lc2)
-
- <-termui.EventCh()
-}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/example/linechart.png b/Godeps/_workspace/src/github.com/gizak/termui/example/linechart.png
deleted file mode 100644
index 655ef435f..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/example/linechart.png
+++ /dev/null
Binary files differ
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/example/list.go b/Godeps/_workspace/src/github.com/gizak/termui/example/list.go
deleted file mode 100644
index d33a3616c..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/example/list.go
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
-// Use of this source code is governed by a MIT license that can
-// be found in the LICENSE file.
-
-// +build ignore
-
-package main
-
-import "github.com/gizak/termui"
-
-func main() {
- err := termui.Init()
- if err != nil {
- panic(err)
- }
- defer termui.Close()
-
- termui.UseTheme("helloworld")
-
- strs := []string{
- "[0] github.com/gizak/termui",
- "[1] 你好,世界",
- "[2] こんにちは世界",
- "[3] keyboard.go",
- "[4] output.go",
- "[5] random_out.go",
- "[6] dashboard.go",
- "[7] nsf/termbox-go"}
-
- ls := termui.NewList()
- ls.Items = strs
- ls.ItemFgColor = termui.ColorYellow
- ls.Border.Label = "List"
- ls.Height = 7
- ls.Width = 25
- ls.Y = 0
-
- termui.Render(ls)
-
- <-termui.EventCh()
-}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/example/list.png b/Godeps/_workspace/src/github.com/gizak/termui/example/list.png
deleted file mode 100644
index 8ca08c079..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/example/list.png
+++ /dev/null
Binary files differ
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/example/mbarchart.go b/Godeps/_workspace/src/github.com/gizak/termui/example/mbarchart.go
deleted file mode 100644
index a32a28e0a..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/example/mbarchart.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
-// Use of this source code is governed by a MIT license that can
-// be found in the LICENSE file.
-
-// +build ignore
-
-package main
-
-import "github.com/gizak/termui"
-
-func main() {
- err := termui.Init()
- if err != nil {
- panic(err)
- }
- defer termui.Close()
-
- termui.UseTheme("helloworld")
-
- bc := termui.NewMBarChart()
- math := []int{90, 85, 90, 80}
- english := []int{70, 85, 75, 60}
- science := []int{75, 60, 80, 85}
- compsci := []int{100, 100, 100, 100}
- bc.Data[0] = math
- bc.Data[1] = english
- bc.Data[2] = science
- bc.Data[3] = compsci
- studentsName := []string{"Ken", "Rob", "Dennis", "Linus"}
- bc.Border.Label = "Student's Marks X-Axis=Name Y-Axis=Marks[Math,English,Science,ComputerScience] in %"
- bc.Width = 100
- bc.Height = 50
- bc.Y = 10
- bc.BarWidth = 10
- bc.DataLabels = studentsName
- bc.ShowScale = true //Show y_axis scale value (min and max)
- bc.SetMax(400)
-
- bc.TextColor = termui.ColorGreen //this is color for label (x-axis)
- bc.BarColor[3] = termui.ColorGreen //BarColor for computerscience
- bc.BarColor[1] = termui.ColorYellow //Bar Color for english
- bc.NumColor[3] = termui.ColorRed // Num color for computerscience
- bc.NumColor[1] = termui.ColorRed // num color for english
-
- //Other colors are automatically populated, btw All the students seems do well in computerscience. :p
-
- termui.Render(bc)
-
- <-termui.EventCh()
-}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/example/mbarchart.png b/Godeps/_workspace/src/github.com/gizak/termui/example/mbarchart.png
deleted file mode 100644
index 9a4252616..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/example/mbarchart.png
+++ /dev/null
Binary files differ
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/example/par.go b/Godeps/_workspace/src/github.com/gizak/termui/example/par.go
deleted file mode 100644
index ffbc60aa8..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/example/par.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
-// Use of this source code is governed by a MIT license that can
-// be found in the LICENSE file.
-
-// +build ignore
-
-package main
-
-import "github.com/gizak/termui"
-
-func main() {
- err := termui.Init()
- if err != nil {
- panic(err)
- }
- defer termui.Close()
-
- termui.UseTheme("helloworld")
-
- par0 := termui.NewPar("Borderless Text")
- par0.Height = 1
- par0.Width = 20
- par0.Y = 1
- par0.HasBorder = false
-
- par1 := termui.NewPar("你好,世界。")
- par1.Height = 3
- par1.Width = 17
- par1.X = 20
- par1.Border.Label = "标签"
-
- par2 := termui.NewPar("Simple text\nwith label. It can be multilined with \\n or break automatically")
- par2.Height = 5
- par2.Width = 37
- par2.Y = 4
- par2.Border.Label = "Multiline"
- par2.Border.FgColor = termui.ColorYellow
-
- par3 := termui.NewPar("Long text with label and it is auto trimmed.")
- par3.Height = 3
- par3.Width = 37
- par3.Y = 9
- par3.Border.Label = "Auto Trim"
-
- termui.Render(par0, par1, par2, par3)
-
- <-termui.EventCh()
-}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/example/par.png b/Godeps/_workspace/src/github.com/gizak/termui/example/par.png
deleted file mode 100644
index a85e64415..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/example/par.png
+++ /dev/null
Binary files differ
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/example/sparklines.go b/Godeps/_workspace/src/github.com/gizak/termui/example/sparklines.go
deleted file mode 100644
index f04baf570..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/example/sparklines.go
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
-// Use of this source code is governed by a MIT license that can
-// be found in the LICENSE file.
-
-// +build ignore
-
-package main
-
-import "github.com/gizak/termui"
-
-func main() {
- err := termui.Init()
- if err != nil {
- panic(err)
- }
- defer termui.Close()
-
- termui.UseTheme("helloworld")
-
- data := []int{4, 2, 1, 6, 3, 9, 1, 4, 2, 15, 14, 9, 8, 6, 10, 13, 15, 12, 10, 5, 3, 6, 1, 7, 10, 10, 14, 13, 6}
- spl0 := termui.NewSparkline()
- spl0.Data = data[3:]
- spl0.Title = "Sparkline 0"
- spl0.LineColor = termui.ColorGreen
-
- // single
- spls0 := termui.NewSparklines(spl0)
- spls0.Height = 2
- spls0.Width = 20
- spls0.HasBorder = false
-
- spl1 := termui.NewSparkline()
- spl1.Data = data
- spl1.Title = "Sparkline 1"
- spl1.LineColor = termui.ColorRed
-
- spl2 := termui.NewSparkline()
- spl2.Data = data[5:]
- spl2.Title = "Sparkline 2"
- spl2.LineColor = termui.ColorMagenta
-
- // group
- spls1 := termui.NewSparklines(spl0, spl1, spl2)
- spls1.Height = 8
- spls1.Width = 20
- spls1.Y = 3
- spls1.Border.Label = "Group Sparklines"
-
- spl3 := termui.NewSparkline()
- spl3.Data = data
- spl3.Title = "Enlarged Sparkline"
- spl3.Height = 8
- spl3.LineColor = termui.ColorYellow
-
- spls2 := termui.NewSparklines(spl3)
- spls2.Height = 11
- spls2.Width = 30
- spls2.Border.FgColor = termui.ColorCyan
- spls2.X = 21
- spls2.Border.Label = "Tweeked Sparkline"
-
- termui.Render(spls0, spls1, spls2)
-
- <-termui.EventCh()
-}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/example/sparklines.png b/Godeps/_workspace/src/github.com/gizak/termui/example/sparklines.png
deleted file mode 100644
index 9dd7c82b1..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/example/sparklines.png
+++ /dev/null
Binary files differ
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/example/theme.go b/Godeps/_workspace/src/github.com/gizak/termui/example/theme.go
deleted file mode 100644
index 30c51a343..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/example/theme.go
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
-// Use of this source code is governed by a MIT license that can
-// be found in the LICENSE file.
-
-// +build ignore
-
-package main
-
-import ui "github.com/gizak/termui"
-import "math"
-
-import "time"
-
-func main() {
- err := ui.Init()
- if err != nil {
- panic(err)
- }
- defer ui.Close()
-
- ui.UseTheme("helloworld")
-
- p := ui.NewPar(":PRESS q TO QUIT DEMO")
- p.Height = 3
- p.Width = 50
- p.Border.Label = "Text Box"
-
- strs := []string{"[0] gizak/termui", "[1] editbox.go", "[2] iterrupt.go", "[3] keyboard.go", "[4] output.go", "[5] random_out.go", "[6] dashboard.go", "[7] nsf/termbox-go"}
- list := ui.NewList()
- list.Items = strs
- list.Border.Label = "List"
- list.Height = 7
- list.Width = 25
- list.Y = 4
-
- g := ui.NewGauge()
- g.Percent = 50
- g.Width = 50
- g.Height = 3
- g.Y = 11
- g.Border.Label = "Gauge"
-
- spark := ui.NewSparkline()
- spark.Title = "srv 0:"
- spdata := []int{4, 2, 1, 6, 3, 9, 1, 4, 2, 15, 14, 9, 8, 6, 10, 13, 15, 12, 10, 5, 3, 6, 1, 7, 10, 10, 14, 13, 6}
- spark.Data = spdata
-
- spark1 := ui.NewSparkline()
- spark1.Title = "srv 1:"
- spark1.Data = spdata
-
- sp := ui.NewSparklines(spark, spark1)
- sp.Width = 25
- sp.Height = 7
- sp.Border.Label = "Sparkline"
- sp.Y = 4
- sp.X = 25
-
- lc := ui.NewLineChart()
- sinps := (func() []float64 {
- n := 100
- ps := make([]float64, n)
- for i := range ps {
- ps[i] = 1 + math.Sin(float64(i)/4)
- }
- return ps
- })()
-
- lc.Border.Label = "Line Chart"
- lc.Data = sinps
- lc.Width = 50
- lc.Height = 11
- lc.X = 0
- lc.Y = 14
- lc.Mode = "dot"
-
- bc := ui.NewBarChart()
- bcdata := []int{3, 2, 5, 3, 9, 5, 3, 2, 5, 8, 3, 2, 4, 5, 3, 2, 5, 7, 5, 3, 2, 6, 7, 4, 6, 3, 6, 7, 8, 3, 6, 4, 5, 3, 2, 4, 6, 4, 8, 5, 9, 4, 3, 6, 5, 3, 6}
- bclabels := []string{"S0", "S1", "S2", "S3", "S4", "S5"}
- bc.Border.Label = "Bar Chart"
- bc.Width = 26
- bc.Height = 10
- bc.X = 51
- bc.Y = 0
- bc.DataLabels = bclabels
-
- lc1 := ui.NewLineChart()
- lc1.Border.Label = "Line Chart"
- rndwalk := (func() []float64 {
- n := 150
- d := make([]float64, n)
- for i := 1; i < n; i++ {
- if i < 20 {
- d[i] = d[i-1] + 0.01
- }
- if i > 20 {
- d[i] = d[i-1] - 0.05
- }
- }
- return d
- })()
- lc1.Data = rndwalk
- lc1.Width = 26
- lc1.Height = 11
- lc1.X = 51
- lc1.Y = 14
-
- p1 := ui.NewPar("Hey!\nI am a borderless block!")
- p1.HasBorder = false
- p1.Width = 26
- p1.Height = 2
- p1.X = 52
- p1.Y = 11
-
- draw := func(t int) {
- g.Percent = t % 101
- list.Items = strs[t%9:]
- sp.Lines[0].Data = spdata[t%10:]
- sp.Lines[1].Data = spdata[t/2%10:]
- lc.Data = sinps[t/2:]
- lc1.Data = rndwalk[t:]
- bc.Data = bcdata[t/2%10:]
- ui.Render(p, list, g, sp, lc, bc, lc1, p1)
- }
-
- evt := ui.EventCh()
- i := 0
- for {
- select {
- case e := <-evt:
- if e.Type == ui.EventKey && e.Ch == 'q' {
- return
- }
- default:
- draw(i)
- i++
- if i == 102 {
- return
- }
- time.Sleep(time.Second / 2)
- }
- }
-}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/example/themedefault.png b/Godeps/_workspace/src/github.com/gizak/termui/example/themedefault.png
deleted file mode 100644
index 23b574f96..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/example/themedefault.png
+++ /dev/null
Binary files differ
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/example/themehelloworld.png b/Godeps/_workspace/src/github.com/gizak/termui/example/themehelloworld.png
deleted file mode 100644
index eaf4d9303..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/example/themehelloworld.png
+++ /dev/null
Binary files differ
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/gauge.go b/Godeps/_workspace/src/github.com/gizak/termui/gauge.go
index 986f4f3dc..244d2995e 100644
--- a/Godeps/_workspace/src/github.com/gizak/termui/gauge.go
+++ b/Godeps/_workspace/src/github.com/gizak/termui/gauge.go
@@ -1,4 +1,4 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
@@ -21,33 +21,27 @@ import (
g.PercentColor = termui.ColorBlue
*/
-// Align is the position of the gauge's label.
-type Align int
-
-// All supported positions.
-const (
- AlignLeft Align = iota
- AlignCenter
- AlignRight
-)
+const ColorUndef Attribute = Attribute(^uint16(0))
type Gauge struct {
Block
- Percent int
- BarColor Attribute
- PercentColor Attribute
- Label string
- LabelAlign Align
+ Percent int
+ BarColor Attribute
+ PercentColor Attribute
+ PercentColorHighlighted Attribute
+ Label string
+ LabelAlign Align
}
// NewGauge return a new gauge with current theme.
func NewGauge() *Gauge {
g := &Gauge{
- Block: *NewBlock(),
- PercentColor: theme.GaugePercent,
- BarColor: theme.GaugeBar,
- Label: "{{percent}}%",
- LabelAlign: AlignCenter,
+ Block: *NewBlock(),
+ PercentColor: ThemeAttr("gauge.percent.fg"),
+ BarColor: ThemeAttr("gauge.bar.bg"),
+ Label: "{{percent}}%",
+ LabelAlign: AlignCenter,
+ PercentColorHighlighted: ColorUndef,
}
g.Width = 12
@@ -56,28 +50,26 @@ func NewGauge() *Gauge {
}
// Buffer implements Bufferer interface.
-func (g *Gauge) Buffer() []Point {
- ps := g.Block.Buffer()
+func (g *Gauge) Buffer() Buffer {
+ buf := g.Block.Buffer()
// plot bar
- w := g.Percent * g.innerWidth / 100
- for i := 0; i < g.innerHeight; i++ {
+ w := g.Percent * g.innerArea.Dx() / 100
+ for i := 0; i < g.innerArea.Dy(); i++ {
for j := 0; j < w; j++ {
- p := Point{}
- p.X = g.innerX + j
- p.Y = g.innerY + i
- p.Ch = ' '
- p.Bg = g.BarColor
- if p.Bg == ColorDefault {
- p.Bg |= AttrReverse
+ c := Cell{}
+ c.Ch = ' '
+ c.Bg = g.BarColor
+ if c.Bg == ColorDefault {
+ c.Bg |= AttrReverse
}
- ps = append(ps, p)
+ buf.Set(g.innerArea.Min.X+j, g.innerArea.Min.Y+i, c)
}
}
// plot percentage
s := strings.Replace(g.Label, "{{percent}}", strconv.Itoa(g.Percent), -1)
- pry := g.innerY + g.innerHeight/2
+ pry := g.innerArea.Min.Y + g.innerArea.Dy()/2
rs := str2runes(s)
var pos int
switch g.LabelAlign {
@@ -85,29 +77,33 @@ func (g *Gauge) Buffer() []Point {
pos = 0
case AlignCenter:
- pos = (g.innerWidth - strWidth(s)) / 2
+ pos = (g.innerArea.Dx() - strWidth(s)) / 2
case AlignRight:
- pos = g.innerWidth - strWidth(s)
+ pos = g.innerArea.Dx() - strWidth(s) - 1
}
+ pos += g.innerArea.Min.X
for i, v := range rs {
- p := Point{}
- p.X = 1 + pos + i
- p.Y = pry
- p.Ch = v
- p.Fg = g.PercentColor
- if w+g.innerX > pos+i {
- p.Bg = g.BarColor
- if p.Bg == ColorDefault {
- p.Bg |= AttrReverse
+ c := Cell{
+ Ch: v,
+ Fg: g.PercentColor,
+ }
+
+ if w+g.innerArea.Min.X > pos+i {
+ c.Bg = g.BarColor
+ if c.Bg == ColorDefault {
+ c.Bg |= AttrReverse
}
+ if g.PercentColorHighlighted != ColorUndef {
+ c.Fg = g.PercentColorHighlighted
+ }
} else {
- p.Bg = g.Block.BgColor
+ c.Bg = g.Block.Bg
}
- ps = append(ps, p)
+ buf.Set(1+pos+i, pry, c)
}
- return g.Block.chopOverflow(ps)
+ return buf
}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/grid.go b/Godeps/_workspace/src/github.com/gizak/termui/grid.go
index 5f6e85e76..364442e02 100644
--- a/Godeps/_workspace/src/github.com/gizak/termui/grid.go
+++ b/Godeps/_workspace/src/github.com/gizak/termui/grid.go
@@ -1,4 +1,4 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
@@ -160,8 +160,8 @@ func (r *Row) SetWidth(w int) {
// Buffer implements Bufferer interface,
// recursively merge all widgets buffer
-func (r *Row) Buffer() []Point {
- merged := []Point{}
+func (r *Row) Buffer() Buffer {
+ merged := NewBuffer()
if r.isRenderableLeaf() {
return r.Widget.Buffer()
@@ -169,13 +169,13 @@ func (r *Row) Buffer() []Point {
// for those are not leaves but have a renderable widget
if r.Widget != nil {
- merged = append(merged, r.Widget.Buffer()...)
+ merged.Merge(r.Widget.Buffer())
}
// collect buffer from children
if !r.isLeaf() {
for _, c := range r.Cols {
- merged = append(merged, c.Buffer()...)
+ merged.Merge(c.Buffer())
}
}
@@ -267,13 +267,13 @@ func (g *Grid) Align() {
}
// Buffer implments Bufferer interface.
-func (g Grid) Buffer() []Point {
- ps := []Point{}
+func (g Grid) Buffer() Buffer {
+ buf := NewBuffer()
+
for _, r := range g.Rows {
- ps = append(ps, r.Buffer()...)
+ buf.Merge(r.Buffer())
}
- return ps
+ return buf
}
-// Body corresponds to the entire terminal display region.
var Body *Grid
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/grid_test.go b/Godeps/_workspace/src/github.com/gizak/termui/grid_test.go
deleted file mode 100644
index cdafb2052..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/grid_test.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
-// Use of this source code is governed by a MIT license that can
-// be found in the LICENSE file.
-
-package termui
-
-import (
- "testing"
-
- "github.com/davecgh/go-spew/spew"
-)
-
-var r *Row
-
-func TestRowWidth(t *testing.T) {
- p0 := NewPar("p0")
- p0.Height = 1
- p1 := NewPar("p1")
- p1.Height = 1
- p2 := NewPar("p2")
- p2.Height = 1
- p3 := NewPar("p3")
- p3.Height = 1
-
- /* test against tree:
-
- r
- / \
- 0:w 1
- / \
- 10:w 11
- /
- 110:w
- /
- 1100:w
- */
- /*
- r = &row{
- Span: 12,
- Cols: []*row{
- &row{Widget: p0, Span: 6},
- &row{
- Span: 6,
- Cols: []*row{
- &row{Widget: p1, Span: 6},
- &row{
- Span: 6,
- Cols: []*row{
- &row{
- Span: 12,
- Widget: p2,
- Cols: []*row{
- &row{Span: 12, Widget: p3}}}}}}}}}
- */
-
- r = NewRow(
- NewCol(6, 0, p0),
- NewCol(6, 0,
- NewRow(
- NewCol(6, 0, p1),
- NewCol(6, 0, p2, p3))))
-
- r.assignWidth(100)
- if r.Width != 100 ||
- (r.Cols[0].Width) != 50 ||
- (r.Cols[1].Width) != 50 ||
- (r.Cols[1].Cols[0].Width) != 25 ||
- (r.Cols[1].Cols[1].Width) != 25 ||
- (r.Cols[1].Cols[1].Cols[0].Width) != 25 ||
- (r.Cols[1].Cols[1].Cols[0].Cols[0].Width) != 25 {
- t.Error("assignWidth fails")
- }
-}
-
-func TestRowHeight(t *testing.T) {
- spew.Dump()
-
- if (r.solveHeight()) != 2 ||
- (r.Cols[1].Cols[1].Height) != 2 ||
- (r.Cols[1].Cols[1].Cols[0].Height) != 2 ||
- (r.Cols[1].Cols[0].Height) != 1 {
- t.Error("solveHeight fails")
- }
-}
-
-func TestAssignXY(t *testing.T) {
- r.assignX(0)
- r.assignY(0)
- if (r.Cols[0].X) != 0 ||
- (r.Cols[1].Cols[0].X) != 50 ||
- (r.Cols[1].Cols[1].X) != 75 ||
- (r.Cols[1].Cols[1].Cols[0].X) != 75 ||
- (r.Cols[1].Cols[0].Y) != 0 ||
- (r.Cols[1].Cols[1].Cols[0].Y) != 0 ||
- (r.Cols[1].Cols[1].Cols[0].Cols[0].Y) != 1 {
- t.Error("assignXY fails")
- }
-}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/helper.go b/Godeps/_workspace/src/github.com/gizak/termui/helper.go
index 80d8a0278..6690e7fb0 100644
--- a/Godeps/_workspace/src/github.com/gizak/termui/helper.go
+++ b/Godeps/_workspace/src/github.com/gizak/termui/helper.go
@@ -1,10 +1,15 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
package termui
-import tm "github.com/nsf/termbox-go"
+import (
+ "regexp"
+ "strings"
+
+ tm "github.com/nsf/termbox-go"
+)
import rw "github.com/mattn/go-runewidth"
/* ---------------Port from termbox-go --------------------- */
@@ -12,6 +17,7 @@ import rw "github.com/mattn/go-runewidth"
// Attribute is printable cell's color and style.
type Attribute uint16
+// 8 basic clolrs
const (
ColorDefault Attribute = iota
ColorBlack
@@ -24,7 +30,10 @@ const (
ColorWhite
)
-const NumberofColors = 8 //Have a constant that defines number of colors
+//Have a constant that defines number of colors
+const NumberofColors = 8
+
+// Text style
const (
AttrBold Attribute = 1 << (iota + 9)
AttrUnderline
@@ -46,15 +55,39 @@ func str2runes(s string) []rune {
return []rune(s)
}
+// Here for backwards-compatibility.
func trimStr2Runes(s string, w int) []rune {
+ return TrimStr2Runes(s, w)
+}
+
+// TrimStr2Runes trims string to w[-1 rune], appends …, and returns the runes
+// of that string if string is grather then n. If string is small then w,
+// return the runes.
+func TrimStr2Runes(s string, w int) []rune {
if w <= 0 {
return []rune{}
}
+
sw := rw.StringWidth(s)
if sw > w {
return []rune(rw.Truncate(s, w, dot))
}
- return str2runes(s) //[]rune(rw.Truncate(s, w, ""))
+ return str2runes(s)
+}
+
+// TrimStrIfAppropriate trim string to "s[:-1] + …"
+// if string > width otherwise return string
+func TrimStrIfAppropriate(s string, w int) string {
+ if w <= 0 {
+ return ""
+ }
+
+ sw := rw.StringWidth(s)
+ if sw > w {
+ return rw.Truncate(s, w, dot)
+ }
+
+ return s
}
func strWidth(s string) int {
@@ -64,3 +97,118 @@ func strWidth(s string) int {
func charWidth(ch rune) int {
return rw.RuneWidth(ch)
}
+
+var whiteSpaceRegex = regexp.MustCompile(`\s`)
+
+// StringToAttribute converts text to a termui attribute. You may specifiy more
+// then one attribute like that: "BLACK, BOLD, ...". All whitespaces
+// are ignored.
+func StringToAttribute(text string) Attribute {
+ text = whiteSpaceRegex.ReplaceAllString(strings.ToLower(text), "")
+ attributes := strings.Split(text, ",")
+ result := Attribute(0)
+
+ for _, theAttribute := range attributes {
+ var match Attribute
+ switch theAttribute {
+ case "reset", "default":
+ match = ColorDefault
+
+ case "black":
+ match = ColorBlack
+
+ case "red":
+ match = ColorRed
+
+ case "green":
+ match = ColorGreen
+
+ case "yellow":
+ match = ColorYellow
+
+ case "blue":
+ match = ColorBlue
+
+ case "magenta":
+ match = ColorMagenta
+
+ case "cyan":
+ match = ColorCyan
+
+ case "white":
+ match = ColorWhite
+
+ case "bold":
+ match = AttrBold
+
+ case "underline":
+ match = AttrUnderline
+
+ case "reverse":
+ match = AttrReverse
+ }
+
+ result |= match
+ }
+
+ return result
+}
+
+// TextCells returns a coloured text cells []Cell
+func TextCells(s string, fg, bg Attribute) []Cell {
+ cs := make([]Cell, 0, len(s))
+
+ // sequence := MarkdownTextRendererFactory{}.TextRenderer(s).Render(fg, bg)
+ // runes := []rune(sequence.NormalizedText)
+ runes := str2runes(s)
+
+ for n := range runes {
+ // point, _ := sequence.PointAt(n, 0, 0)
+ // cs = append(cs, Cell{point.Ch, point.Fg, point.Bg})
+ cs = append(cs, Cell{runes[n], fg, bg})
+ }
+ return cs
+}
+
+// Width returns the actual screen space the cell takes (usually 1 or 2).
+func (c Cell) Width() int {
+ return charWidth(c.Ch)
+}
+
+// Copy return a copy of c
+func (c Cell) Copy() Cell {
+ return c
+}
+
+// TrimTxCells trims the overflowed text cells sequence.
+func TrimTxCells(cs []Cell, w int) []Cell {
+ if len(cs) <= w {
+ return cs
+ }
+ return cs[:w]
+}
+
+// DTrimTxCls trims the overflowed text cells sequence and append dots at the end.
+func DTrimTxCls(cs []Cell, w int) []Cell {
+ l := len(cs)
+ if l <= 0 {
+ return []Cell{}
+ }
+
+ rt := make([]Cell, 0, w)
+ csw := 0
+ for i := 0; i < l && csw <= w; i++ {
+ c := cs[i]
+ cw := c.Width()
+
+ if cw+csw < w {
+ rt = append(rt, c)
+ csw += cw
+ } else {
+ rt = append(rt, Cell{'…', c.Fg, c.Bg})
+ break
+ }
+ }
+
+ return rt
+}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/helper_test.go b/Godeps/_workspace/src/github.com/gizak/termui/helper_test.go
deleted file mode 100644
index 6d1a56130..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/helper_test.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
-// Use of this source code is governed by a MIT license that can
-// be found in the LICENSE file.
-
-package termui
-
-import (
- "testing"
-
- "github.com/davecgh/go-spew/spew"
-)
-
-func TestStr2Rune(t *testing.T) {
- s := "你好,世界."
- rs := str2runes(s)
- if len(rs) != 6 {
- t.Error()
- }
-}
-
-func TestWidth(t *testing.T) {
- s0 := "つのだ☆HIRO"
- s1 := "11111111111"
- spew.Dump(s0)
- spew.Dump(s1)
- // above not align for setting East Asian Ambiguous to wide!!
-
- if strWidth(s0) != strWidth(s1) {
- t.Error("str len failed")
- }
-
- len1 := []rune{'a', '2', '&', '「', 'オ', '。'} //will false: 'ᆵ', 'ᄚ', 'ᄒ'
- for _, v := range len1 {
- if charWidth(v) != 1 {
- t.Error("len1 failed")
- }
- }
-
- len2 := []rune{'漢', '字', '한', '자', '你', '好', 'だ', '。', '%', 's', 'E', 'ョ', '、', 'ヲ'}
- for _, v := range len2 {
- if charWidth(v) != 2 {
- t.Error("len2 failed")
- }
- }
-}
-
-func TestTrim(t *testing.T) {
- s := "つのだ☆HIRO"
- if string(trimStr2Runes(s, 10)) != "つのだ☆HI"+dot {
- t.Error("trim failed")
- }
- if string(trimStr2Runes(s, 11)) != "つのだ☆HIRO" {
- t.Error("avoid tail trim failed")
- }
- if string(trimStr2Runes(s, 15)) != "つのだ☆HIRO" {
- t.Error("avoid trim failed")
- }
-}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/chart.go b/Godeps/_workspace/src/github.com/gizak/termui/linechart.go
index d6fb8bc7d..f2829148e 100644
--- a/Godeps/_workspace/src/github.com/gizak/termui/chart.go
+++ b/Godeps/_workspace/src/github.com/gizak/termui/linechart.go
@@ -1,4 +1,4 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
@@ -74,8 +74,8 @@ type LineChart struct {
// NewLineChart returns a new LineChart with current theme.
func NewLineChart() *LineChart {
lc := &LineChart{Block: *NewBlock()}
- lc.AxesColor = theme.LineChartAxes
- lc.LineColor = theme.LineChartLine
+ lc.AxesColor = ThemeAttr("linechart.axes.fg")
+ lc.LineColor = ThemeAttr("linechart.line.fg")
lc.Mode = "braille"
lc.DotStyle = '•'
lc.axisXLebelGap = 2
@@ -87,8 +87,8 @@ func NewLineChart() *LineChart {
// one cell contains two data points
// so the capicity is 2x as dot-mode
-func (lc *LineChart) renderBraille() []Point {
- ps := []Point{}
+func (lc *LineChart) renderBraille() Buffer {
+ buf := NewBuffer()
// return: b -> which cell should the point be in
// m -> in the cell, divided into 4 equal height levels, which subcell?
@@ -104,44 +104,48 @@ func (lc *LineChart) renderBraille() []Point {
b1, m1 := getPos(lc.Data[2*i+1])
if b0 == b1 {
- p := Point{}
- p.Ch = braillePatterns[[2]int{m0, m1}]
- p.Bg = lc.BgColor
- p.Fg = lc.LineColor
- p.Y = lc.innerY + lc.innerHeight - 3 - b0
- p.X = lc.innerX + lc.labelYSpace + 1 + i
- ps = append(ps, p)
+ c := Cell{
+ Ch: braillePatterns[[2]int{m0, m1}],
+ Bg: lc.Bg,
+ Fg: lc.LineColor,
+ }
+ y := lc.innerArea.Min.Y + lc.innerArea.Dy() - 3 - b0
+ x := lc.innerArea.Min.X + lc.labelYSpace + 1 + i
+ buf.Set(x, y, c)
} else {
- p0 := newPointWithAttrs(lSingleBraille[m0],
- lc.innerX+lc.labelYSpace+1+i,
- lc.innerY+lc.innerHeight-3-b0,
- lc.LineColor,
- lc.BgColor)
- p1 := newPointWithAttrs(rSingleBraille[m1],
- lc.innerX+lc.labelYSpace+1+i,
- lc.innerY+lc.innerHeight-3-b1,
- lc.LineColor,
- lc.BgColor)
- ps = append(ps, p0, p1)
+ c0 := Cell{Ch: lSingleBraille[m0],
+ Fg: lc.LineColor,
+ Bg: lc.Bg}
+ x0 := lc.innerArea.Min.X + lc.labelYSpace + 1 + i
+ y0 := lc.innerArea.Min.Y + lc.innerArea.Dy() - 3 - b0
+ buf.Set(x0, y0, c0)
+
+ c1 := Cell{Ch: rSingleBraille[m1],
+ Fg: lc.LineColor,
+ Bg: lc.Bg}
+ x1 := lc.innerArea.Min.X + lc.labelYSpace + 1 + i
+ y1 := lc.innerArea.Min.Y + lc.innerArea.Dy() - 3 - b1
+ buf.Set(x1, y1, c1)
}
}
- return ps
+ return buf
}
-func (lc *LineChart) renderDot() []Point {
- ps := []Point{}
+func (lc *LineChart) renderDot() Buffer {
+ buf := NewBuffer()
for i := 0; i < len(lc.Data) && i < lc.axisXWidth; i++ {
- p := Point{}
- p.Ch = lc.DotStyle
- p.Fg = lc.LineColor
- p.Bg = lc.BgColor
- p.X = lc.innerX + lc.labelYSpace + 1 + i
- p.Y = lc.innerY + lc.innerHeight - 3 - int((lc.Data[i]-lc.bottomValue)/lc.scale+0.5)
- ps = append(ps, p)
+ c := Cell{
+ Ch: lc.DotStyle,
+ Fg: lc.LineColor,
+ Bg: lc.Bg,
+ }
+ x := lc.innerArea.Min.X + lc.labelYSpace + 1 + i
+ y := lc.innerArea.Min.Y + lc.innerArea.Dy() - 3 - int((lc.Data[i]-lc.bottomValue)/lc.scale+0.5)
+ buf.Set(x, y, c)
}
- return ps
+ return buf
}
func (lc *LineChart) calcLabelX() {
@@ -220,9 +224,9 @@ func (lc *LineChart) calcLayout() {
lc.maxY = lc.Data[0]
// valid visible range
- vrange := lc.innerWidth
+ vrange := lc.innerArea.Dx()
if lc.Mode == "braille" {
- vrange = 2 * lc.innerWidth
+ vrange = 2 * lc.innerArea.Dx()
}
if vrange > len(lc.Data) {
vrange = len(lc.Data)
@@ -247,40 +251,30 @@ func (lc *LineChart) calcLayout() {
lc.topValue = lc.maxY + 0.2*span
}
- lc.axisYHeight = lc.innerHeight - 2
+ lc.axisYHeight = lc.innerArea.Dy() - 2
lc.calcLabelY()
- lc.axisXWidth = lc.innerWidth - 1 - lc.labelYSpace
+ lc.axisXWidth = lc.innerArea.Dx() - 1 - lc.labelYSpace
lc.calcLabelX()
- lc.drawingX = lc.innerX + 1 + lc.labelYSpace
- lc.drawingY = lc.innerY
+ lc.drawingX = lc.innerArea.Min.X + 1 + lc.labelYSpace
+ lc.drawingY = lc.innerArea.Min.Y
}
-func (lc *LineChart) plotAxes() []Point {
- origY := lc.innerY + lc.innerHeight - 2
- origX := lc.innerX + lc.labelYSpace
+func (lc *LineChart) plotAxes() Buffer {
+ buf := NewBuffer()
+
+ origY := lc.innerArea.Min.Y + lc.innerArea.Dy() - 2
+ origX := lc.innerArea.Min.X + lc.labelYSpace
- ps := []Point{newPointWithAttrs(ORIGIN, origX, origY, lc.AxesColor, lc.BgColor)}
+ buf.Set(origX, origY, Cell{Ch: ORIGIN, Fg: lc.AxesColor, Bg: lc.Bg})
for x := origX + 1; x < origX+lc.axisXWidth; x++ {
- p := Point{}
- p.X = x
- p.Y = origY
- p.Bg = lc.BgColor
- p.Fg = lc.AxesColor
- p.Ch = HDASH
- ps = append(ps, p)
+ buf.Set(x, origY, Cell{Ch: HDASH, Fg: lc.AxesColor, Bg: lc.Bg})
}
for dy := 1; dy <= lc.axisYHeight; dy++ {
- p := Point{}
- p.X = origX
- p.Y = origY - dy
- p.Bg = lc.BgColor
- p.Fg = lc.AxesColor
- p.Ch = VDASH
- ps = append(ps, p)
+ buf.Set(origX, origY-dy, Cell{Ch: VDASH, Fg: lc.AxesColor, Bg: lc.Bg})
}
// x label
@@ -290,13 +284,14 @@ func (lc *LineChart) plotAxes() []Point {
break
}
for j, r := range rs {
- p := Point{}
- p.Ch = r
- p.Fg = lc.AxesColor
- p.Bg = lc.BgColor
- p.X = origX + oft + j
- p.Y = lc.innerY + lc.innerHeight - 1
- ps = append(ps, p)
+ c := Cell{
+ Ch: r,
+ Fg: lc.AxesColor,
+ Bg: lc.Bg,
+ }
+ x := origX + oft + j
+ y := lc.innerArea.Min.Y + lc.innerArea.Dy() - 1
+ buf.Set(x, y, c)
}
oft += len(rs) + lc.axisXLebelGap
}
@@ -304,33 +299,31 @@ func (lc *LineChart) plotAxes() []Point {
// y labels
for i, rs := range lc.labelY {
for j, r := range rs {
- p := Point{}
- p.Ch = r
- p.Fg = lc.AxesColor
- p.Bg = lc.BgColor
- p.X = lc.innerX + j
- p.Y = origY - i*(lc.axisYLebelGap+1)
- ps = append(ps, p)
+ buf.Set(
+ lc.innerArea.Min.X+j,
+ origY-i*(lc.axisYLebelGap+1),
+ Cell{Ch: r, Fg: lc.AxesColor, Bg: lc.Bg})
}
}
- return ps
+ return buf
}
// Buffer implements Bufferer interface.
-func (lc *LineChart) Buffer() []Point {
- ps := lc.Block.Buffer()
+func (lc *LineChart) Buffer() Buffer {
+ buf := lc.Block.Buffer()
+
if lc.Data == nil || len(lc.Data) == 0 {
- return ps
+ return buf
}
lc.calcLayout()
- ps = append(ps, lc.plotAxes()...)
+ buf.Merge(lc.plotAxes())
if lc.Mode == "dot" {
- ps = append(ps, lc.renderDot()...)
+ buf.Merge(lc.renderDot())
} else {
- ps = append(ps, lc.renderBraille()...)
+ buf.Merge(lc.renderBraille())
}
- return lc.Block.chopOverflow(ps)
+ return buf
}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/chart_others.go b/Godeps/_workspace/src/github.com/gizak/termui/linechart_others.go
index 8911873b6..7e2e66b3e 100644
--- a/Godeps/_workspace/src/github.com/gizak/termui/chart_others.go
+++ b/Godeps/_workspace/src/github.com/gizak/termui/linechart_others.go
@@ -1,4 +1,4 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/chart_windows.go b/Godeps/_workspace/src/github.com/gizak/termui/linechart_windows.go
index 9f9a5e96c..1478b5ce3 100644
--- a/Godeps/_workspace/src/github.com/gizak/termui/chart_windows.go
+++ b/Godeps/_workspace/src/github.com/gizak/termui/linechart_windows.go
@@ -1,4 +1,4 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/list.go b/Godeps/_workspace/src/github.com/gizak/termui/list.go
index 0640932f2..670015fd3 100644
--- a/Godeps/_workspace/src/github.com/gizak/termui/list.go
+++ b/Godeps/_workspace/src/github.com/gizak/termui/list.go
@@ -1,4 +1,4 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
@@ -41,64 +41,49 @@ type List struct {
func NewList() *List {
l := &List{Block: *NewBlock()}
l.Overflow = "hidden"
- l.ItemFgColor = theme.ListItemFg
- l.ItemBgColor = theme.ListItemBg
+ l.ItemFgColor = ThemeAttr("list.item.fg")
+ l.ItemBgColor = ThemeAttr("list.item.bg")
return l
}
// Buffer implements Bufferer interface.
-func (l *List) Buffer() []Point {
- ps := l.Block.Buffer()
+func (l *List) Buffer() Buffer {
+ buf := l.Block.Buffer()
+
switch l.Overflow {
case "wrap":
- rs := str2runes(strings.Join(l.Items, "\n"))
+ cs := DefaultTxBuilder.Build(strings.Join(l.Items, "\n"), l.ItemFgColor, l.ItemBgColor)
i, j, k := 0, 0, 0
- for i < l.innerHeight && k < len(rs) {
- w := charWidth(rs[k])
- if rs[k] == '\n' || j+w > l.innerWidth {
+ for i < l.innerArea.Dy() && k < len(cs) {
+ w := cs[k].Width()
+ if cs[k].Ch == '\n' || j+w > l.innerArea.Dx() {
i++
j = 0
- if rs[k] == '\n' {
+ if cs[k].Ch == '\n' {
k++
}
continue
}
- pi := Point{}
- pi.X = l.innerX + j
- pi.Y = l.innerY + i
-
- pi.Ch = rs[k]
- pi.Bg = l.ItemBgColor
- pi.Fg = l.ItemFgColor
+ buf.Set(l.innerArea.Min.X+j, l.innerArea.Min.Y+i, cs[k])
- ps = append(ps, pi)
k++
j++
}
case "hidden":
trimItems := l.Items
- if len(trimItems) > l.innerHeight {
- trimItems = trimItems[:l.innerHeight]
+ if len(trimItems) > l.innerArea.Dy() {
+ trimItems = trimItems[:l.innerArea.Dy()]
}
for i, v := range trimItems {
- rs := trimStr2Runes(v, l.innerWidth)
-
+ cs := DTrimTxCls(DefaultTxBuilder.Build(v, l.ItemFgColor, l.ItemBgColor), l.innerArea.Dx())
j := 0
- for _, vv := range rs {
- w := charWidth(vv)
- p := Point{}
- p.X = l.innerX + j
- p.Y = l.innerY + i
-
- p.Ch = vv
- p.Bg = l.ItemBgColor
- p.Fg = l.ItemFgColor
-
- ps = append(ps, p)
+ for _, vv := range cs {
+ w := vv.Width()
+ buf.Set(l.innerArea.Min.X+j, l.innerArea.Min.Y+i, vv)
j += w
}
}
}
- return l.Block.chopOverflow(ps)
+ return buf
}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/mbar.go b/Godeps/_workspace/src/github.com/gizak/termui/mbarchart.go
index 9d18c2cb4..231de277f 100644
--- a/Godeps/_workspace/src/github.com/gizak/termui/mbar.go
+++ b/Godeps/_workspace/src/github.com/gizak/termui/mbarchart.go
@@ -1,4 +1,4 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
@@ -48,16 +48,16 @@ type MBarChart struct {
// NewBarChart returns a new *BarChart with current theme.
func NewMBarChart() *MBarChart {
bc := &MBarChart{Block: *NewBlock()}
- bc.BarColor[0] = theme.MBarChartBar
- bc.NumColor[0] = theme.MBarChartNum
- bc.TextColor = theme.MBarChartText
+ bc.BarColor[0] = ThemeAttr("mbarchart.bar.bg")
+ bc.NumColor[0] = ThemeAttr("mbarchart.num.fg")
+ bc.TextColor = ThemeAttr("mbarchart.text.fg")
bc.BarGap = 1
bc.BarWidth = 3
return bc
}
func (bc *MBarChart) layout() {
- bc.numBar = bc.innerWidth / (bc.BarGap + bc.BarWidth)
+ bc.numBar = bc.innerArea.Dx() / (bc.BarGap + bc.BarWidth)
bc.labels = make([][]rune, bc.numBar)
DataLen := 0
LabelLen := len(bc.DataLabels)
@@ -129,9 +129,9 @@ func (bc *MBarChart) layout() {
if bc.ShowScale {
s := fmt.Sprintf("%d", bc.max)
bc.maxScale = trimStr2Runes(s, len(s))
- bc.scale = float64(bc.max) / float64(bc.innerHeight-2)
+ bc.scale = float64(bc.max) / float64(bc.innerArea.Dy()-2)
} else {
- bc.scale = float64(bc.max) / float64(bc.innerHeight-1)
+ bc.scale = float64(bc.max) / float64(bc.innerArea.Dy()-1)
}
}
@@ -144,8 +144,8 @@ func (bc *MBarChart) SetMax(max int) {
}
// Buffer implements Bufferer interface.
-func (bc *MBarChart) Buffer() []Point {
- ps := bc.Block.Buffer()
+func (bc *MBarChart) Buffer() Buffer {
+ buf := bc.Block.Buffer()
bc.layout()
var oftX int
@@ -157,15 +157,17 @@ func (bc *MBarChart) Buffer() []Point {
// plot bars
for j := 0; j < bc.BarWidth; j++ {
for k := 0; k < h; k++ {
- p := Point{}
- p.Ch = ' '
- p.Bg = bc.BarColor[i1]
+ c := Cell{
+ Ch: ' ',
+ Bg: bc.BarColor[i1],
+ }
if bc.BarColor[i1] == ColorDefault { // when color is default, space char treated as transparent!
- p.Bg |= AttrReverse
+ c.Bg |= AttrReverse
}
- p.X = bc.innerX + i*(bc.BarWidth+bc.BarGap) + j
- p.Y = bc.innerY + bc.innerHeight - 2 - k - ph
- ps = append(ps, p)
+ x := bc.innerArea.Min.X + i*(bc.BarWidth+bc.BarGap) + j
+ y := bc.innerArea.Min.Y + bc.innerArea.Dy() - 2 - k - ph
+ buf.Set(x, y, c)
+
}
}
ph += h
@@ -173,13 +175,14 @@ func (bc *MBarChart) Buffer() []Point {
// plot text
for j, k := 0, 0; j < len(bc.labels[i]); j++ {
w := charWidth(bc.labels[i][j])
- p := Point{}
- p.Ch = bc.labels[i][j]
- p.Bg = bc.BgColor
- p.Fg = bc.TextColor
- p.Y = bc.innerY + bc.innerHeight - 1
- p.X = bc.innerX + oftX + ((bc.BarWidth - len(bc.labels[i])) / 2) + k
- ps = append(ps, p)
+ c := Cell{
+ Ch: bc.labels[i][j],
+ Bg: bc.Bg,
+ Fg: bc.TextColor,
+ }
+ y := bc.innerArea.Min.Y + bc.innerArea.Dy() - 1
+ x := bc.innerArea.Max.X + oftX + ((bc.BarWidth - len(bc.labels[i])) / 2) + k
+ buf.Set(x, y, c)
k += w
}
// plot num
@@ -187,19 +190,20 @@ func (bc *MBarChart) Buffer() []Point {
for i1 := 0; i1 < bc.numStack; i1++ {
h := int(float64(bc.Data[i1][i]) / bc.scale)
for j := 0; j < len(bc.dataNum[i1][i]) && h > 0; j++ {
- p := Point{}
- p.Ch = bc.dataNum[i1][i][j]
- p.Fg = bc.NumColor[i1]
- p.Bg = bc.BarColor[i1]
+ c := Cell{
+ Ch: bc.dataNum[i1][i][j],
+ Fg: bc.NumColor[i1],
+ Bg: bc.BarColor[i1],
+ }
if bc.BarColor[i1] == ColorDefault { // the same as above
- p.Bg |= AttrReverse
+ c.Bg |= AttrReverse
}
if h == 0 {
- p.Bg = bc.BgColor
+ c.Bg = bc.Bg
}
- p.X = bc.innerX + oftX + (bc.BarWidth-len(bc.dataNum[i1][i]))/2 + j
- p.Y = bc.innerY + bc.innerHeight - 2 - ph
- ps = append(ps, p)
+ x := bc.innerArea.Min.X + oftX + (bc.BarWidth-len(bc.dataNum[i1][i]))/2 + j
+ y := bc.innerArea.Min.Y + bc.innerArea.Dy() - 2 - ph
+ buf.Set(x, y, c)
}
ph += h
}
@@ -208,26 +212,31 @@ func (bc *MBarChart) Buffer() []Point {
if bc.ShowScale {
//Currently bar graph only supprts data range from 0 to MAX
//Plot 0
- p := Point{}
- p.Ch = '0'
- p.Bg = bc.BgColor
- p.Fg = bc.TextColor
- p.Y = bc.innerY + bc.innerHeight - 2
- p.X = bc.X
- ps = append(ps, p)
+ c := Cell{
+ Ch: '0',
+ Bg: bc.Bg,
+ Fg: bc.TextColor,
+ }
+
+ y := bc.innerArea.Min.Y + bc.innerArea.Dy() - 2
+ x := bc.X
+ buf.Set(x, y, c)
//Plot the maximum sacle value
for i := 0; i < len(bc.maxScale); i++ {
- p := Point{}
- p.Ch = bc.maxScale[i]
- p.Bg = bc.BgColor
- p.Fg = bc.TextColor
- p.Y = bc.innerY
- p.X = bc.X + i
- ps = append(ps, p)
+ c := Cell{
+ Ch: bc.maxScale[i],
+ Bg: bc.Bg,
+ Fg: bc.TextColor,
+ }
+
+ y := bc.innerArea.Min.Y
+ x := bc.X + i
+
+ buf.Set(x, y, c)
}
}
- return bc.Block.chopOverflow(ps)
+ return buf
}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/p.go b/Godeps/_workspace/src/github.com/gizak/termui/p.go
deleted file mode 100644
index e327d7489..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/p.go
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
-// Use of this source code is governed by a MIT license that can
-// be found in the LICENSE file.
-
-package termui
-
-// Par displays a paragraph.
-/*
- par := termui.NewPar("Simple Text")
- par.Height = 3
- par.Width = 17
- par.Border.Label = "Label"
-*/
-type Par struct {
- Block
- Text string
- TextFgColor Attribute
- TextBgColor Attribute
-}
-
-// NewPar returns a new *Par with given text as its content.
-func NewPar(s string) *Par {
- return &Par{
- Block: *NewBlock(),
- Text: s,
- TextFgColor: theme.ParTextFg,
- TextBgColor: theme.ParTextBg}
-}
-
-// Buffer implements Bufferer interface.
-func (p *Par) Buffer() []Point {
- ps := p.Block.Buffer()
-
- rs := str2runes(p.Text)
- i, j, k := 0, 0, 0
- for i < p.innerHeight && k < len(rs) {
- // the width of char is about to print
- w := charWidth(rs[k])
-
- if rs[k] == '\n' || j+w > p.innerWidth {
- i++
- j = 0 // set x = 0
- if rs[k] == '\n' {
- k++
- }
-
- if i >= p.innerHeight {
- ps = append(ps, newPointWithAttrs('…',
- p.innerX+p.innerWidth-1,
- p.innerY+p.innerHeight-1,
- p.TextFgColor, p.TextBgColor))
- break
- }
-
- continue
- }
- pi := Point{}
- pi.X = p.innerX + j
- pi.Y = p.innerY + i
-
- pi.Ch = rs[k]
- pi.Bg = p.TextBgColor
- pi.Fg = p.TextFgColor
-
- ps = append(ps, pi)
-
- k++
- j += w
- }
- return p.Block.chopOverflow(ps)
-}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/par.go b/Godeps/_workspace/src/github.com/gizak/termui/par.go
new file mode 100644
index 000000000..c01bd0020
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gizak/termui/par.go
@@ -0,0 +1,64 @@
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Use of this source code is governed by a MIT license that can
+// be found in the LICENSE file.
+
+package termui
+
+// Par displays a paragraph.
+/*
+ par := termui.NewPar("Simple Text")
+ par.Height = 3
+ par.Width = 17
+ par.Border.Label = "Label"
+*/
+type Par struct {
+ Block
+ Text string
+ TextFgColor Attribute
+ TextBgColor Attribute
+}
+
+// NewPar returns a new *Par with given text as its content.
+func NewPar(s string) *Par {
+ return &Par{
+ Block: *NewBlock(),
+ Text: s,
+ TextFgColor: ThemeAttr("par.text.fg"),
+ TextBgColor: ThemeAttr("par.text.bg"),
+ }
+}
+
+// Buffer implements Bufferer interface.
+func (p *Par) Buffer() Buffer {
+ buf := p.Block.Buffer()
+
+ fg, bg := p.TextFgColor, p.TextBgColor
+ cs := DefaultTxBuilder.Build(p.Text, fg, bg)
+
+ y, x, n := 0, 0, 0
+ for y < p.innerArea.Dy() && n < len(cs) {
+ w := cs[n].Width()
+ if cs[n].Ch == '\n' || x+w > p.innerArea.Dx() {
+ y++
+ x = 0 // set x = 0
+ if cs[n].Ch == '\n' {
+ n++
+ }
+
+ if y >= p.innerArea.Dy() {
+ buf.Set(p.innerArea.Min.X+p.innerArea.Dx()-1,
+ p.innerArea.Min.Y+p.innerArea.Dy()-1,
+ Cell{Ch: '…', Fg: p.TextFgColor, Bg: p.TextBgColor})
+ break
+ }
+ continue
+ }
+
+ buf.Set(p.innerArea.Min.X+x, p.innerArea.Min.Y+y, cs[n])
+
+ n++
+ x += w
+ }
+
+ return buf
+}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/point.go b/Godeps/_workspace/src/github.com/gizak/termui/point.go
deleted file mode 100644
index c381af9a4..000000000
--- a/Godeps/_workspace/src/github.com/gizak/termui/point.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
-// Use of this source code is governed by a MIT license that can
-// be found in the LICENSE file.
-
-package termui
-
-// Point stands for a single cell in terminal.
-type Point struct {
- Ch rune
- Bg Attribute
- Fg Attribute
- X int
- Y int
-}
-
-func newPoint(c rune, x, y int) (p Point) {
- p.Ch = c
- p.X = x
- p.Y = y
- return
-}
-
-func newPointWithAttrs(c rune, x, y int, fg, bg Attribute) Point {
- p := newPoint(c, x, y)
- p.Bg = bg
- p.Fg = fg
- return p
-}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/pos.go b/Godeps/_workspace/src/github.com/gizak/termui/pos.go
new file mode 100644
index 000000000..2046dce5a
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gizak/termui/pos.go
@@ -0,0 +1,78 @@
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Use of this source code is governed by a MIT license that can
+// be found in the LICENSE file.
+
+package termui
+
+import "image"
+
+// Align is the position of the gauge's label.
+type Align uint
+
+// All supported positions.
+const (
+ AlignNone Align = 0
+ AlignLeft Align = 1 << iota
+ AlignRight
+ AlignBottom
+ AlignTop
+ AlignCenterVertical
+ AlignCenterHorizontal
+ AlignCenter = AlignCenterVertical | AlignCenterHorizontal
+)
+
+func AlignArea(parent, child image.Rectangle, a Align) image.Rectangle {
+ w, h := child.Dx(), child.Dy()
+
+ // parent center
+ pcx, pcy := parent.Min.X+parent.Dx()/2, parent.Min.Y+parent.Dy()/2
+ // child center
+ ccx, ccy := child.Min.X+child.Dx()/2, child.Min.Y+child.Dy()/2
+
+ if a&AlignLeft == AlignLeft {
+ child.Min.X = parent.Min.X
+ child.Max.X = child.Min.X + w
+ }
+
+ if a&AlignRight == AlignRight {
+ child.Max.X = parent.Max.X
+ child.Min.X = child.Max.X - w
+ }
+
+ if a&AlignBottom == AlignBottom {
+ child.Max.Y = parent.Max.Y
+ child.Min.Y = child.Max.Y - h
+ }
+
+ if a&AlignTop == AlignRight {
+ child.Min.Y = parent.Min.Y
+ child.Max.Y = child.Min.Y + h
+ }
+
+ if a&AlignCenterHorizontal == AlignCenterHorizontal {
+ child.Min.X += pcx - ccx
+ child.Max.X = child.Min.X + w
+ }
+
+ if a&AlignCenterVertical == AlignCenterVertical {
+ child.Min.Y += pcy - ccy
+ child.Max.Y = child.Min.Y + h
+ }
+
+ return child
+}
+
+func MoveArea(a image.Rectangle, dx, dy int) image.Rectangle {
+ a.Min.X += dx
+ a.Max.X += dx
+ a.Min.Y += dy
+ a.Max.Y += dy
+ return a
+}
+
+var termWidth int
+var termHeight int
+
+func TermRect() image.Rectangle {
+ return image.Rect(0, 0, termWidth, termHeight)
+}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/render.go b/Godeps/_workspace/src/github.com/gizak/termui/render.go
index d697d0aea..36544f063 100644
--- a/Godeps/_workspace/src/github.com/gizak/termui/render.go
+++ b/Godeps/_workspace/src/github.com/gizak/termui/render.go
@@ -1,29 +1,62 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
package termui
-import tm "github.com/nsf/termbox-go"
+import (
+ "image"
+ "sync"
+ "time"
+
+ tm "github.com/nsf/termbox-go"
+)
// Bufferer should be implemented by all renderable components.
type Bufferer interface {
- Buffer() []Point
+ Buffer() Buffer
}
// Init initializes termui library. This function should be called before any others.
// After initialization, the library must be finalized by 'Close' function.
func Init() error {
+ if err := tm.Init(); err != nil {
+ return err
+ }
+
+ sysEvtChs = make([]chan Event, 0)
+ go hookTermboxEvt()
+
+ renderJobs = make(chan []Bufferer)
+ //renderLock = new(sync.RWMutex)
+
Body = NewGrid()
Body.X = 0
Body.Y = 0
- Body.BgColor = theme.BodyBg
- defer func() {
- w, _ := tm.Size()
- Body.Width = w
- evtListen()
+ Body.BgColor = ThemeAttr("bg")
+ Body.Width = TermWidth()
+
+ DefaultEvtStream.Init()
+ DefaultEvtStream.Merge("termbox", NewSysEvtCh())
+ DefaultEvtStream.Merge("timer", NewTimerCh(time.Second))
+ DefaultEvtStream.Merge("custom", usrEvtCh)
+
+ DefaultEvtStream.Handle("/", DefualtHandler)
+ DefaultEvtStream.Handle("/sys/wnd/resize", func(e Event) {
+ w := e.Data.(EvtWnd)
+ Body.Width = w.Width
+ })
+
+ DefaultWgtMgr = NewWgtMgr()
+ DefaultEvtStream.Hook(DefaultWgtMgr.WgtHandlersHook())
+
+ go func() {
+ for bs := range renderJobs {
+ render(bs...)
+ }
}()
- return tm.Init()
+
+ return nil
}
// Close finalizes termui library,
@@ -32,29 +65,71 @@ func Close() {
tm.Close()
}
+var renderLock sync.Mutex
+
+func termSync() {
+ renderLock.Lock()
+ tm.Sync()
+ termWidth, termHeight = tm.Size()
+ renderLock.Unlock()
+}
+
// TermWidth returns the current terminal's width.
func TermWidth() int {
- tm.Sync()
- w, _ := tm.Size()
- return w
+ termSync()
+ return termWidth
}
// TermHeight returns the current terminal's height.
func TermHeight() int {
- tm.Sync()
- _, h := tm.Size()
- return h
+ termSync()
+ return termHeight
}
// Render renders all Bufferer in the given order from left to right,
// right could overlap on left ones.
-func Render(rs ...Bufferer) {
- tm.Clear(tm.ColorDefault, toTmAttr(theme.BodyBg))
- for _, r := range rs {
- buf := r.Buffer()
- for _, v := range buf {
- tm.SetCell(v.X, v.Y, v.Ch, toTmAttr(v.Fg), toTmAttr(v.Bg))
+func render(bs ...Bufferer) {
+
+ for _, b := range bs {
+
+ buf := b.Buffer()
+ // set cels in buf
+ for p, c := range buf.CellMap {
+ if p.In(buf.Area) {
+
+ tm.SetCell(p.X, p.Y, c.Ch, toTmAttr(c.Fg), toTmAttr(c.Bg))
+
+ }
}
+
}
+
+ renderLock.Lock()
+ // render
tm.Flush()
+ renderLock.Unlock()
+}
+
+func Clear() {
+ tm.Clear(tm.ColorDefault, toTmAttr(ThemeAttr("bg")))
+}
+
+func clearArea(r image.Rectangle, bg Attribute) {
+ for i := r.Min.X; i < r.Max.X; i++ {
+ for j := r.Min.Y; j < r.Max.Y; j++ {
+ tm.SetCell(i, j, ' ', tm.ColorDefault, toTmAttr(bg))
+ }
+ }
+}
+
+func ClearArea(r image.Rectangle, bg Attribute) {
+ clearArea(r, bg)
+ tm.Flush()
+}
+
+var renderJobs chan []Bufferer
+
+func Render(bs ...Bufferer) {
+ //go func() { renderJobs <- bs }()
+ renderJobs <- bs
}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/sparkline.go b/Godeps/_workspace/src/github.com/gizak/termui/sparkline.go
index c63a5857f..312ad9563 100644
--- a/Godeps/_workspace/src/github.com/gizak/termui/sparkline.go
+++ b/Godeps/_workspace/src/github.com/gizak/termui/sparkline.go
@@ -1,12 +1,10 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
package termui
-import "math"
-
-// Sparkline is like: ▅▆▂▂▅▇▂▂▃▆▆▆▅▃
+// Sparkline is like: ▅▆▂▂▅▇▂▂▃▆▆▆▅▃. The data points should be non-negative integers.
/*
data := []int{4, 2, 1, 6, 3, 9, 1, 4, 2, 15, 14, 9, 8, 6, 10, 13, 15, 12, 10, 5, 3, 6, 1}
spl := termui.NewSparkline()
@@ -49,8 +47,8 @@ func (s *Sparklines) Add(sl Sparkline) {
func NewSparkline() Sparkline {
return Sparkline{
Height: 1,
- TitleColor: theme.SparklineTitle,
- LineColor: theme.SparklineLine}
+ TitleColor: ThemeAttr("sparkline.title.fg"),
+ LineColor: ThemeAttr("sparkline.line.fg")}
}
// NewSparklines return a new *Spaklines with given Sparkline(s), you can always add a new Sparkline later.
@@ -67,13 +65,13 @@ func (sl *Sparklines) update() {
sl.Lines[i].displayHeight = v.Height + 1
}
}
- sl.displayWidth = sl.innerWidth
+ sl.displayWidth = sl.innerArea.Dx()
// get how many lines gotta display
h := 0
sl.displayLines = 0
for _, v := range sl.Lines {
- if h+v.displayHeight <= sl.innerHeight {
+ if h+v.displayHeight <= sl.innerArea.Dy() {
sl.displayLines++
} else {
break
@@ -84,20 +82,24 @@ func (sl *Sparklines) update() {
for i := 0; i < sl.displayLines; i++ {
data := sl.Lines[i].Data
- max := math.MinInt32
+ max := 0
for _, v := range data {
if max < v {
max = v
}
}
sl.Lines[i].max = max
- sl.Lines[i].scale = float32(8*sl.Lines[i].Height) / float32(max)
+ if max != 0 {
+ sl.Lines[i].scale = float32(8*sl.Lines[i].Height) / float32(max)
+ } else { // when all negative
+ sl.Lines[i].scale = 0
+ }
}
}
// Buffer implements Bufferer interface.
-func (sl *Sparklines) Buffer() []Point {
- ps := sl.Block.Buffer()
+func (sl *Sparklines) Buffer() Buffer {
+ buf := sl.Block.Buffer()
sl.update()
oftY := 0
@@ -105,52 +107,61 @@ func (sl *Sparklines) Buffer() []Point {
l := sl.Lines[i]
data := l.Data
- if len(data) > sl.innerWidth {
- data = data[len(data)-sl.innerWidth:]
+ if len(data) > sl.innerArea.Dx() {
+ data = data[len(data)-sl.innerArea.Dx():]
}
if l.Title != "" {
- rs := trimStr2Runes(l.Title, sl.innerWidth)
+ rs := trimStr2Runes(l.Title, sl.innerArea.Dx())
oftX := 0
for _, v := range rs {
w := charWidth(v)
- p := Point{}
- p.Ch = v
- p.Fg = l.TitleColor
- p.Bg = sl.BgColor
- p.X = sl.innerX + oftX
- p.Y = sl.innerY + oftY
- ps = append(ps, p)
+ c := Cell{
+ Ch: v,
+ Fg: l.TitleColor,
+ Bg: sl.Bg,
+ }
+ x := sl.innerArea.Min.X + oftX
+ y := sl.innerArea.Min.Y + oftY
+ buf.Set(x, y, c)
oftX += w
}
}
for j, v := range data {
+ // display height of the data point, zero when data is negative
h := int(float32(v)*l.scale + 0.5)
+ if v < 0 {
+ h = 0
+ }
+
barCnt := h / 8
barMod := h % 8
for jj := 0; jj < barCnt; jj++ {
- p := Point{}
- p.X = sl.innerX + j
- p.Y = sl.innerY + oftY + l.Height - jj
- p.Ch = ' ' // => sparks[7]
- p.Bg = l.LineColor
+ c := Cell{
+ Ch: ' ', // => sparks[7]
+ Bg: l.LineColor,
+ }
+ x := sl.innerArea.Min.X + j
+ y := sl.innerArea.Min.Y + oftY + l.Height - jj
+
//p.Bg = sl.BgColor
- ps = append(ps, p)
+ buf.Set(x, y, c)
}
if barMod != 0 {
- p := Point{}
- p.X = sl.innerX + j
- p.Y = sl.innerY + oftY + l.Height - barCnt
- p.Ch = sparks[barMod-1]
- p.Fg = l.LineColor
- p.Bg = sl.BgColor
- ps = append(ps, p)
+ c := Cell{
+ Ch: sparks[barMod-1],
+ Fg: l.LineColor,
+ Bg: sl.Bg,
+ }
+ x := sl.innerArea.Min.X + j
+ y := sl.innerArea.Min.Y + oftY + l.Height - barCnt
+ buf.Set(x, y, c)
}
}
oftY += l.displayHeight
}
- return sl.Block.chopOverflow(ps)
+ return buf
}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/test/runtest.go b/Godeps/_workspace/src/github.com/gizak/termui/test/runtest.go
new file mode 100644
index 000000000..99794c4db
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gizak/termui/test/runtest.go
@@ -0,0 +1,66 @@
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Use of this source code is governed by a MIT license that can
+// be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "os"
+
+ "github.com/gizak/termui"
+ "github.com/gizak/termui/debug"
+)
+
+func main() {
+ // run as client
+ if len(os.Args) > 1 {
+ fmt.Print(debug.ConnectAndListen())
+ return
+ }
+
+ // run as server
+ go func() { panic(debug.ListenAndServe()) }()
+
+ if err := termui.Init(); err != nil {
+ panic(err)
+ }
+ defer termui.Close()
+
+ //termui.UseTheme("helloworld")
+ b := termui.NewBlock()
+ b.Width = 20
+ b.Height = 20
+ b.Float = termui.AlignCenter
+ b.BorderLabel = "[HELLO](fg-red,bg-white) [WORLD](fg-blue,bg-green)"
+
+ termui.Render(b)
+
+ termui.Handle("/sys", func(e termui.Event) {
+ k, ok := e.Data.(termui.EvtKbd)
+ debug.Logf("->%v\n", e)
+ if ok && k.KeyStr == "q" {
+ termui.StopLoop()
+ }
+ })
+
+ termui.Handle(("/usr"), func(e termui.Event) {
+ debug.Logf("->%v\n", e)
+ })
+
+ termui.Handle("/timer/1s", func(e termui.Event) {
+ t := e.Data.(termui.EvtTimer)
+ termui.SendCustomEvt("/usr/t", t.Count)
+
+ if t.Count%2 == 0 {
+ b.BorderLabel = "[HELLO](fg-red,bg-green) [WORLD](fg-blue,bg-white)"
+ } else {
+ b.BorderLabel = "[HELLO](fg-blue,bg-white) [WORLD](fg-red,bg-green)"
+ }
+
+ termui.Render(b)
+
+ })
+
+ termui.Loop()
+}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/textbuilder.go b/Godeps/_workspace/src/github.com/gizak/termui/textbuilder.go
new file mode 100644
index 000000000..6ff6d21f3
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gizak/termui/textbuilder.go
@@ -0,0 +1,215 @@
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Use of this source code is governed by a MIT license that can
+// be found in the LICENSE file.
+
+package termui
+
+import (
+ "regexp"
+ "strings"
+)
+
+// TextBuilder is a minial interface to produce text []Cell using sepcific syntax (markdown).
+type TextBuilder interface {
+ Build(s string, fg, bg Attribute) []Cell
+}
+
+// DefaultTxBuilder is set to be MarkdownTxBuilder.
+var DefaultTxBuilder = NewMarkdownTxBuilder()
+
+// MarkdownTxBuilder implements TextBuilder interface, using markdown syntax.
+type MarkdownTxBuilder struct {
+ baseFg Attribute
+ baseBg Attribute
+ plainTx []rune
+ markers []marker
+}
+
+type marker struct {
+ st int
+ ed int
+ fg Attribute
+ bg Attribute
+}
+
+var colorMap = map[string]Attribute{
+ "red": ColorRed,
+ "blue": ColorBlue,
+ "black": ColorBlack,
+ "cyan": ColorCyan,
+ "yellow": ColorYellow,
+ "white": ColorWhite,
+ "default": ColorDefault,
+ "green": ColorGreen,
+ "magenta": ColorMagenta,
+}
+
+var attrMap = map[string]Attribute{
+ "bold": AttrBold,
+ "underline": AttrUnderline,
+ "reverse": AttrReverse,
+}
+
+func rmSpc(s string) string {
+ reg := regexp.MustCompile(`\s+`)
+ return reg.ReplaceAllString(s, "")
+}
+
+// readAttr translates strings like `fg-red,fg-bold,bg-white` to fg and bg Attribute
+func (mtb MarkdownTxBuilder) readAttr(s string) (Attribute, Attribute) {
+ fg := mtb.baseFg
+ bg := mtb.baseBg
+
+ updateAttr := func(a Attribute, attrs []string) Attribute {
+ for _, s := range attrs {
+ // replace the color
+ if c, ok := colorMap[s]; ok {
+ a &= 0xFF00 // erase clr 0 ~ 8 bits
+ a |= c // set clr
+ }
+ // add attrs
+ if c, ok := attrMap[s]; ok {
+ a |= c
+ }
+ }
+ return a
+ }
+
+ ss := strings.Split(s, ",")
+ fgs := []string{}
+ bgs := []string{}
+ for _, v := range ss {
+ subs := strings.Split(v, "-")
+ if len(subs) > 1 {
+ if subs[0] == "fg" {
+ fgs = append(fgs, subs[1])
+ }
+ if subs[0] == "bg" {
+ bgs = append(bgs, subs[1])
+ }
+ }
+ }
+
+ fg = updateAttr(fg, fgs)
+ bg = updateAttr(bg, bgs)
+ return fg, bg
+}
+
+func (mtb *MarkdownTxBuilder) reset() {
+ mtb.plainTx = []rune{}
+ mtb.markers = []marker{}
+}
+
+// parse streams and parses text into normalized text and render sequence.
+func (mtb *MarkdownTxBuilder) parse(str string) {
+ rs := str2runes(str)
+ normTx := []rune{}
+ square := []rune{}
+ brackt := []rune{}
+ accSquare := false
+ accBrackt := false
+ cntSquare := 0
+
+ reset := func() {
+ square = []rune{}
+ brackt = []rune{}
+ accSquare = false
+ accBrackt = false
+ cntSquare = 0
+ }
+ // pipe stacks into normTx and clear
+ rollback := func() {
+ normTx = append(normTx, square...)
+ normTx = append(normTx, brackt...)
+ reset()
+ }
+ // chop first and last
+ chop := func(s []rune) []rune {
+ return s[1 : len(s)-1]
+ }
+
+ for i, r := range rs {
+ switch {
+ // stacking brackt
+ case accBrackt:
+ brackt = append(brackt, r)
+ if ')' == r {
+ fg, bg := mtb.readAttr(string(chop(brackt)))
+ st := len(normTx)
+ ed := len(normTx) + len(square) - 2
+ mtb.markers = append(mtb.markers, marker{st, ed, fg, bg})
+ normTx = append(normTx, chop(square)...)
+ reset()
+ } else if i+1 == len(rs) {
+ rollback()
+ }
+ // stacking square
+ case accSquare:
+ switch {
+ // squares closed and followed by a '('
+ case cntSquare == 0 && '(' == r:
+ accBrackt = true
+ brackt = append(brackt, '(')
+ // squares closed but not followed by a '('
+ case cntSquare == 0:
+ rollback()
+ if '[' == r {
+ accSquare = true
+ cntSquare = 1
+ brackt = append(brackt, '[')
+ } else {
+ normTx = append(normTx, r)
+ }
+ // hit the end
+ case i+1 == len(rs):
+ square = append(square, r)
+ rollback()
+ case '[' == r:
+ cntSquare++
+ square = append(square, '[')
+ case ']' == r:
+ cntSquare--
+ square = append(square, ']')
+ // normal char
+ default:
+ square = append(square, r)
+ }
+ // stacking normTx
+ default:
+ if '[' == r {
+ accSquare = true
+ cntSquare = 1
+ square = append(square, '[')
+ } else {
+ normTx = append(normTx, r)
+ }
+ }
+ }
+
+ mtb.plainTx = normTx
+}
+
+// Build implements TextBuilder interface.
+func (mtb MarkdownTxBuilder) Build(s string, fg, bg Attribute) []Cell {
+ mtb.baseFg = fg
+ mtb.baseBg = bg
+ mtb.reset()
+ mtb.parse(s)
+ cs := make([]Cell, len(mtb.plainTx))
+ for i := range cs {
+ cs[i] = Cell{Ch: mtb.plainTx[i], Fg: fg, Bg: bg}
+ }
+ for _, mrk := range mtb.markers {
+ for i := mrk.st; i < mrk.ed; i++ {
+ cs[i].Fg = mrk.fg
+ cs[i].Bg = mrk.bg
+ }
+ }
+
+ return cs
+}
+
+// NewMarkdownTxBuilder returns a TextBuilder employing markdown syntax.
+func NewMarkdownTxBuilder() TextBuilder {
+ return MarkdownTxBuilder{}
+}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/theme.go b/Godeps/_workspace/src/github.com/gizak/termui/theme.go
index c8ad94756..c3ccda559 100644
--- a/Godeps/_workspace/src/github.com/gizak/termui/theme.go
+++ b/Godeps/_workspace/src/github.com/gizak/termui/theme.go
@@ -1,9 +1,12 @@
-// Copyright 2015 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
package termui
+import "strings"
+
+/*
// A ColorScheme represents the current look-and-feel of the dashboard.
type ColorScheme struct {
BodyBg Attribute
@@ -29,6 +32,7 @@ type ColorScheme struct {
MBarChartBar Attribute
MBarChartText Attribute
MBarChartNum Attribute
+ TabActiveBg Attribute
}
// default color scheme depends on the user's terminal setting.
@@ -58,6 +62,7 @@ var themeHelloWorld = ColorScheme{
MBarChartBar: ColorRed,
MBarChartNum: ColorWhite,
MBarChartText: ColorCyan,
+ TabActiveBg: ColorMagenta,
}
var theme = themeDefault // global dep
@@ -82,3 +87,54 @@ func UseTheme(th string) {
theme = themeDefault
}
}
+*/
+
+var ColorMap = map[string]Attribute{
+ "fg": ColorWhite,
+ "bg": ColorDefault,
+ "border.fg": ColorWhite,
+ "label.fg": ColorGreen,
+ "par.fg": ColorYellow,
+ "par.label.bg": ColorWhite,
+}
+
+func ThemeAttr(name string) Attribute {
+ return lookUpAttr(ColorMap, name)
+}
+
+func lookUpAttr(clrmap map[string]Attribute, name string) Attribute {
+
+ a, ok := clrmap[name]
+ if ok {
+ return a
+ }
+
+ ns := strings.Split(name, ".")
+ for i := range ns {
+ nn := strings.Join(ns[i:len(ns)], ".")
+ a, ok = ColorMap[nn]
+ if ok {
+ break
+ }
+ }
+
+ return a
+}
+
+// 0<=r,g,b <= 5
+func ColorRGB(r, g, b int) Attribute {
+ within := func(n int) int {
+ if n < 0 {
+ return 0
+ }
+
+ if n > 5 {
+ return 5
+ }
+
+ return n
+ }
+
+ r, b, g = within(r), within(b), within(g)
+ return Attribute(0x0f + 36*r + 6*g + b)
+}
diff --git a/Godeps/_workspace/src/github.com/gizak/termui/widget.go b/Godeps/_workspace/src/github.com/gizak/termui/widget.go
new file mode 100644
index 000000000..35cf143a3
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gizak/termui/widget.go
@@ -0,0 +1,94 @@
+// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Use of this source code is governed by a MIT license that can
+// be found in the LICENSE file.
+
+package termui
+
+import (
+ "fmt"
+ "sync"
+)
+
+// event mixins
+type WgtMgr map[string]WgtInfo
+
+type WgtInfo struct {
+ Handlers map[string]func(Event)
+ WgtRef Widget
+ Id string
+}
+
+type Widget interface {
+ Id() string
+}
+
+func NewWgtInfo(wgt Widget) WgtInfo {
+ return WgtInfo{
+ Handlers: make(map[string]func(Event)),
+ WgtRef: wgt,
+ Id: wgt.Id(),
+ }
+}
+
+func NewWgtMgr() WgtMgr {
+ wm := WgtMgr(make(map[string]WgtInfo))
+ return wm
+
+}
+
+func (wm WgtMgr) AddWgt(wgt Widget) {
+ wm[wgt.Id()] = NewWgtInfo(wgt)
+}
+
+func (wm WgtMgr) RmWgt(wgt Widget) {
+ wm.RmWgtById(wgt.Id())
+}
+
+func (wm WgtMgr) RmWgtById(id string) {
+ delete(wm, id)
+}
+
+func (wm WgtMgr) AddWgtHandler(id, path string, h func(Event)) {
+ if w, ok := wm[id]; ok {
+ w.Handlers[path] = h
+ }
+}
+
+func (wm WgtMgr) RmWgtHandler(id, path string) {
+ if w, ok := wm[id]; ok {
+ delete(w.Handlers, path)
+ }
+}
+
+var counter struct {
+ sync.RWMutex
+ count int
+}
+
+func GenId() string {
+ counter.Lock()
+ defer counter.Unlock()
+
+ counter.count += 1
+ return fmt.Sprintf("%d", counter.count)
+}
+
+func (wm WgtMgr) WgtHandlersHook() func(Event) {
+ return func(e Event) {
+ for _, v := range wm {
+ if k := findMatch(v.Handlers, e.Path); k != "" {
+ v.Handlers[k](e)
+ }
+ }
+ }
+}
+
+var DefaultWgtMgr WgtMgr
+
+func (b *Block) Handle(path string, handler func(Event)) {
+ if _, ok := DefaultWgtMgr[b.Id()]; !ok {
+ DefaultWgtMgr.AddWgt(b)
+ }
+
+ DefaultWgtMgr.AddWgtHandler(b.Id(), path, handler)
+}