Moved the grid control into the UI package.
This commit is contained in:
parent
96f3271cd6
commit
4a831f7730
4
main.go
4
main.go
|
|
@ -17,7 +17,9 @@ func main() {
|
||||||
statusLayout.Append(&ui.StatusBar{"Another", "Component"})
|
statusLayout.Append(&ui.StatusBar{"Another", "Component"})
|
||||||
statusLayout.Append(&ui.StatusBar{"Third", "Test"})
|
statusLayout.Append(&ui.StatusBar{"Third", "Test"})
|
||||||
|
|
||||||
clientArea := &ui.RelativeLayout{ South: statusLayout }
|
grid := ui.NewGrid(&ui.TestModel{})
|
||||||
|
|
||||||
|
clientArea := &ui.RelativeLayout{ Client: grid, South: statusLayout }
|
||||||
|
|
||||||
uiManager.SetRootComponent(clientArea)
|
uiManager.SetRootComponent(clientArea)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,13 @@ func (dc *DrawContext) DrawRune(x, y int, ch rune) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draws a rune at a local point X, Y with specific foreground and background attributes
|
||||||
|
func (dc *DrawContext) DrawRuneWithAttrs(x, y int, ch rune, fa, ba Attribute) {
|
||||||
|
if rx, ry, isWithinContext := dc.localPointToRealPoint(x, y); isWithinContext {
|
||||||
|
dc.driver.SetCell(rx, ry, ch, fa, ba)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Converts a local point to a real point. If the point is within the context, also returns true
|
// Converts a local point to a real point. If the point is within the context, also returns true
|
||||||
func (dc *DrawContext) localPointToRealPoint(x, y int) (int, int, bool) {
|
func (dc *DrawContext) localPointToRealPoint(x, y int) (int, int, bool) {
|
||||||
rx, ry := x + dc.X, y + dc.Y
|
rx, ry := x + dc.X, y + dc.Y
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,13 @@ const (
|
||||||
type EventType int
|
type EventType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
EventNone EventType = iota
|
||||||
|
|
||||||
|
// Event when the window is resized
|
||||||
|
EventResize
|
||||||
|
|
||||||
// Event indicating a key press. The event parameter is the key scancode?
|
// Event indicating a key press. The event parameter is the key scancode?
|
||||||
EventKeyPress EventType = iota
|
EventKeyPress
|
||||||
)
|
)
|
||||||
|
|
||||||
// Data from an event callback.
|
// Data from an event callback.
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
/**
|
/**
|
||||||
* The grid component. This is used for displaying the model.
|
* The grid component. This is used for displaying the model.
|
||||||
*/
|
*/
|
||||||
package main
|
package ui
|
||||||
|
|
||||||
import "github.com/nsf/termbox-go"
|
|
||||||
import "strconv"
|
import "strconv"
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -76,8 +75,8 @@ func NewGrid(model GridModel) *Grid {
|
||||||
/**
|
/**
|
||||||
* Returns the requested dimensions of a grid (as required by UiComponent)
|
* Returns the requested dimensions of a grid (as required by UiComponent)
|
||||||
*/
|
*/
|
||||||
func (grid *Grid) RequestDims() (int, int) {
|
func (grid *Grid) Remeasure(w, h int) (int, int) {
|
||||||
return -1, -1
|
return w, h
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -122,31 +121,31 @@ func (grid *Grid) reposition() {
|
||||||
|
|
||||||
|
|
||||||
// Gets the cell value and attributes of a particular cell
|
// Gets the cell value and attributes of a particular cell
|
||||||
func (grid *Grid) getCellData(cellX, cellY int) (text string, fg, bg termbox.Attribute) {
|
func (grid *Grid) getCellData(cellX, cellY int) (text string, fg, bg Attribute) {
|
||||||
// The fixed cells
|
// The fixed cells
|
||||||
modelCellX := cellX - 1 + grid.viewCellX
|
modelCellX := cellX - 1 + grid.viewCellX
|
||||||
modelCellY := cellY - 1 + grid.viewCellY
|
modelCellY := cellY - 1 + grid.viewCellY
|
||||||
modelMaxX, modelMaxY := grid.model.GetDimensions()
|
modelMaxX, modelMaxY := grid.model.GetDimensions()
|
||||||
|
|
||||||
if (cellX == 0) && (cellY == 0) {
|
if (cellX == 0) && (cellY == 0) {
|
||||||
return strconv.Itoa(grid.cellsWide), termbox.AttrBold, termbox.AttrBold
|
return strconv.Itoa(grid.cellsWide), AttrBold, AttrBold
|
||||||
} else if (cellX == 0) {
|
} else if (cellX == 0) {
|
||||||
if (modelCellY == grid.selCellY) {
|
if (modelCellY == grid.selCellY) {
|
||||||
return strconv.Itoa(modelCellY), termbox.AttrBold | termbox.AttrReverse, termbox.AttrBold | termbox.AttrReverse
|
return strconv.Itoa(modelCellY), AttrBold | AttrReverse, AttrBold | AttrReverse
|
||||||
} else {
|
} else {
|
||||||
return strconv.Itoa(modelCellY), termbox.AttrBold, termbox.AttrBold
|
return strconv.Itoa(modelCellY), AttrBold, AttrBold
|
||||||
}
|
}
|
||||||
} else if (cellY == 0) {
|
} else if (cellY == 0) {
|
||||||
if (modelCellX == grid.selCellX) {
|
if (modelCellX == grid.selCellX) {
|
||||||
return strconv.Itoa(modelCellX), termbox.AttrBold | termbox.AttrReverse, termbox.AttrBold | termbox.AttrReverse
|
return strconv.Itoa(modelCellX), AttrBold | AttrReverse, AttrBold | AttrReverse
|
||||||
} else {
|
} else {
|
||||||
return strconv.Itoa(modelCellX), termbox.AttrBold, termbox.AttrBold
|
return strconv.Itoa(modelCellX), AttrBold, AttrBold
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// The data from the model
|
// The data from the model
|
||||||
if (modelCellX >= 0) && (modelCellY >= 0) && (modelCellX < modelMaxX) && (modelCellY < modelMaxY) {
|
if (modelCellX >= 0) && (modelCellY >= 0) && (modelCellX < modelMaxX) && (modelCellY < modelMaxY) {
|
||||||
if (modelCellX == grid.selCellX) && (modelCellY == grid.selCellY) {
|
if (modelCellX == grid.selCellX) && (modelCellY == grid.selCellY) {
|
||||||
return grid.model.GetCellValue(modelCellX, modelCellY), termbox.AttrReverse, termbox.AttrReverse
|
return grid.model.GetCellValue(modelCellX, modelCellY), AttrReverse, AttrReverse
|
||||||
} else {
|
} else {
|
||||||
return grid.model.GetCellValue(modelCellX, modelCellY), 0, 0
|
return grid.model.GetCellValue(modelCellX, modelCellY), 0, 0
|
||||||
}
|
}
|
||||||
|
|
@ -202,7 +201,7 @@ func (grid *Grid) getCellDimensions(cellX, cellY int) (width, height int) {
|
||||||
* Renders a cell which contains text. The clip rectangle defines the size of the cell, as well as the left offset
|
* Renders a cell which contains text. The clip rectangle defines the size of the cell, as well as the left offset
|
||||||
* of the cell. The sx and sy determine the screen position of the cell top-left.
|
* of the cell. The sx and sy determine the screen position of the cell top-left.
|
||||||
*/
|
*/
|
||||||
func (grid *Grid) renderCell(cellClipRect gridRect, sx int, sy int, text string, fg, bg termbox.Attribute) {
|
func (grid *Grid) renderCell(ctx *DrawContext, cellClipRect gridRect, sx int, sy int, text string, fg, bg Attribute) {
|
||||||
for x := cellClipRect.x1; x <= cellClipRect.x2; x++ {
|
for x := cellClipRect.x1; x <= cellClipRect.x2; x++ {
|
||||||
for y := cellClipRect.y1; y <= cellClipRect.y2; y++ {
|
for y := cellClipRect.y1; y <= cellClipRect.y2; y++ {
|
||||||
currRune := ' '
|
currRune := ' '
|
||||||
|
|
@ -213,7 +212,10 @@ func (grid *Grid) renderCell(cellClipRect gridRect, sx int, sy int, text string,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
termbox.SetCell(int(x - cellClipRect.x1) + sx, int(y - cellClipRect.y1) + sy, currRune, fg, bg)
|
//termbox.SetCell(int(x - cellClipRect.x1) + sx, int(y - cellClipRect.y1) + sy, currRune, fg, bg)
|
||||||
|
|
||||||
|
// TODO: This might be better if this wasn't so low-level
|
||||||
|
ctx.DrawRuneWithAttrs(int(x - cellClipRect.x1) + sx, int(y - cellClipRect.y1) + sy, currRune, fg, bg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -222,7 +224,7 @@ func (grid *Grid) renderCell(cellClipRect gridRect, sx int, sy int, text string,
|
||||||
// Renders a column. The viewport determines the maximum position of the rendered cell. CellX and CellY are the
|
// Renders a column. The viewport determines the maximum position of the rendered cell. CellX and CellY are the
|
||||||
// cell indicies to render, cellOffset are the LOCAL offset of the cell.
|
// cell indicies to render, cellOffset are the LOCAL offset of the cell.
|
||||||
// This function will return the new X position (gridRect.x1 + colWidth)
|
// This function will return the new X position (gridRect.x1 + colWidth)
|
||||||
func (grid *Grid) renderColumn(screenViewPort gridRect, cellX int, cellY int, cellOffsetX int, cellOffsetY int) (gridPoint, int) {
|
func (grid *Grid) renderColumn(ctx *DrawContext, screenViewPort gridRect, cellX int, cellY int, cellOffsetX int, cellOffsetY int) (gridPoint, int) {
|
||||||
|
|
||||||
// The top-left position of the column
|
// The top-left position of the column
|
||||||
screenX := int(screenViewPort.x1)
|
screenX := int(screenViewPort.x1)
|
||||||
|
|
@ -251,7 +253,7 @@ func (grid *Grid) renderColumn(screenViewPort gridRect, cellX int, cellY int, ce
|
||||||
|
|
||||||
cellText, cellFg, cellBg := grid.getCellData(cellX, cellY)
|
cellText, cellFg, cellBg := grid.getCellData(cellX, cellY)
|
||||||
|
|
||||||
grid.renderCell(newGridRect(cellOffsetX, cellOffsetY, colWidth - cellOffsetX, rowHeight),
|
grid.renderCell(ctx, newGridRect(cellOffsetX, cellOffsetY, colWidth - cellOffsetX, rowHeight),
|
||||||
screenX, screenY, cellText, cellFg, cellBg) // termbox.AttrReverse, termbox.AttrReverse
|
screenX, screenY, cellText, cellFg, cellBg) // termbox.AttrReverse, termbox.AttrReverse
|
||||||
|
|
||||||
cellY++
|
cellY++
|
||||||
|
|
@ -266,13 +268,13 @@ func (grid *Grid) renderColumn(screenViewPort gridRect, cellX int, cellY int, ce
|
||||||
|
|
||||||
// Renders the grid. Returns the number of cells in the X and Y direction were rendered.
|
// Renders the grid. Returns the number of cells in the X and Y direction were rendered.
|
||||||
//
|
//
|
||||||
func (grid *Grid) renderGrid(screenViewPort gridRect, cellX int, cellY int, cellOffsetX int, cellOffsetY int) (int, int) {
|
func (grid *Grid) renderGrid(ctx *DrawContext, screenViewPort gridRect, cellX int, cellY int, cellOffsetX int, cellOffsetY int) (int, int) {
|
||||||
|
|
||||||
var cellsHigh = 0
|
var cellsHigh = 0
|
||||||
var cellsWide = 0
|
var cellsWide = 0
|
||||||
|
|
||||||
for screenViewPort.x1 < screenViewPort.x2 {
|
for screenViewPort.x1 < screenViewPort.x2 {
|
||||||
screenViewPort.x1, cellsHigh = grid.renderColumn(screenViewPort, cellX, cellY, cellOffsetX, cellOffsetY)
|
screenViewPort.x1, cellsHigh = grid.renderColumn(ctx, screenViewPort, cellX, cellY, cellOffsetX, cellOffsetY)
|
||||||
cellX = cellX + 1
|
cellX = cellX + 1
|
||||||
cellsWide++
|
cellsWide++
|
||||||
cellOffsetX = 0
|
cellOffsetX = 0
|
||||||
|
|
@ -316,9 +318,9 @@ func (grid *Grid) pointToCell(x int, y int) (cellX int, cellY int, posX int, pos
|
||||||
/**
|
/**
|
||||||
* Redraws the grid.
|
* Redraws the grid.
|
||||||
*/
|
*/
|
||||||
func (grid *Grid) Redraw(x int, y int, w int, h int) {
|
func (grid *Grid) Redraw(ctx *DrawContext) {
|
||||||
viewportRect := newGridRect(x, y, x + w, y + h)
|
viewportRect := newGridRect(0, 0, ctx.W, ctx.H)
|
||||||
grid.cellsWide, grid.cellsHigh = grid.renderGrid(viewportRect, 0, 0, 0, 0)
|
grid.cellsWide, grid.cellsHigh = grid.renderGrid(ctx, viewportRect, 0, 0, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
|
|
@ -98,9 +98,18 @@ func (ui *Ui) redrawInternal(width, height int) {
|
||||||
|
|
||||||
// Enter the UI loop
|
// Enter the UI loop
|
||||||
func (ui *Ui) Loop() {
|
func (ui *Ui) Loop() {
|
||||||
//for {
|
for {
|
||||||
ui.Redraw()
|
ui.Redraw()
|
||||||
ui.driver.WaitForEvent()
|
event := ui.driver.WaitForEvent()
|
||||||
|
|
||||||
|
// TODO: If the event is a key-press, do something.
|
||||||
|
if event.Type == EventKeyPress {
|
||||||
|
return
|
||||||
|
} else if event.Type == EventResize {
|
||||||
|
|
||||||
|
// HACK: Find another way to refresh the size of the screen to prevent a full redraw.
|
||||||
|
ui.driver.Sync()
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if event.Type == termbox.EventResize {
|
if event.Type == termbox.EventResize {
|
||||||
|
|
@ -125,7 +134,7 @@ func (ui *Ui) Loop() {
|
||||||
//return UiEvent{EventKeyPress, 0}
|
//return UiEvent{EventKeyPress, 0}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
//}
|
}
|
||||||
|
|
||||||
// XXX: Workaround for bug in compiler
|
// XXX: Workaround for bug in compiler
|
||||||
}
|
}
|
||||||
|
|
@ -38,6 +38,14 @@ func (td *TermboxDriver) Sync() {
|
||||||
|
|
||||||
// Wait for an event
|
// Wait for an event
|
||||||
func (td *TermboxDriver) WaitForEvent() Event {
|
func (td *TermboxDriver) WaitForEvent() Event {
|
||||||
termbox.PollEvent()
|
tev := termbox.PollEvent()
|
||||||
return Event{}
|
|
||||||
|
switch tev.Type {
|
||||||
|
case termbox.EventResize:
|
||||||
|
return Event{EventResize, 0}
|
||||||
|
case termbox.EventKey:
|
||||||
|
return Event{EventKeyPress, 0}
|
||||||
|
default:
|
||||||
|
return Event{EventNone, 0}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue