sampler-fork/component/layout.go

288 lines
7.9 KiB
Go
Raw Normal View History

2019-02-24 04:49:09 +00:00
package component
2019-01-31 00:02:38 +00:00
import (
2019-02-24 04:49:09 +00:00
"github.com/sqshq/sampler/component/runchart"
"github.com/sqshq/sampler/config"
2019-02-11 02:51:55 +00:00
"github.com/sqshq/sampler/console"
ui "github.com/sqshq/termui"
"image"
2019-03-01 03:44:01 +00:00
"math"
2019-01-31 00:02:38 +00:00
)
type Layout struct {
2019-02-11 02:51:55 +00:00
ui.Block
Components []Component
ChangeModeEvents chan Mode
2019-02-25 00:08:36 +00:00
statusbar *StatusBar
menu *Menu
2019-02-25 00:08:36 +00:00
mode Mode
selection int
2019-01-31 00:02:38 +00:00
}
2019-02-11 02:51:55 +00:00
type Mode rune
const (
ModeDefault Mode = 0
2019-03-03 01:04:02 +00:00
ModePause Mode = 1
ModeComponentSelect Mode = 2
ModeMenuOptionSelect Mode = 3
ModeComponentMove Mode = 4
ModeComponentResize Mode = 5
ModeChartPinpoint Mode = 6
2019-02-11 02:51:55 +00:00
)
2019-01-31 00:02:38 +00:00
const (
2019-02-26 04:36:23 +00:00
columnsCount = 80
2019-03-01 03:44:01 +00:00
rowsCount = 40
2019-03-02 21:38:36 +00:00
minDimension = 3
2019-02-25 00:37:57 +00:00
statusbarHeight = 1
2019-01-31 00:02:38 +00:00
)
2019-02-25 00:08:36 +00:00
func NewLayout(width, height int, statusline *StatusBar, menu *Menu) *Layout {
2019-01-31 00:02:38 +00:00
2019-02-11 02:51:55 +00:00
block := *ui.NewBlock()
2019-01-31 00:02:38 +00:00
block.SetRect(0, 0, width, height)
2019-02-25 00:37:57 +00:00
statusline.SetRect(0, height-statusbarHeight, width, height)
2019-01-31 00:02:38 +00:00
return &Layout{
Block: block,
Components: make([]Component, 0),
2019-02-25 00:08:36 +00:00
statusbar: statusline,
menu: menu,
mode: ModeDefault,
selection: 0,
ChangeModeEvents: make(chan Mode, 10),
2019-01-31 00:02:38 +00:00
}
}
func (l *Layout) AddComponent(Type config.ComponentType, drawable ui.Drawable, title string, position config.Position, size config.Size, refreshRateMs int) {
l.Components = append(l.Components, Component{Type, drawable, title, position, size, refreshRateMs})
}
func (l *Layout) GetComponents(Type config.ComponentType) []ui.Drawable {
2019-02-11 02:51:55 +00:00
var components []ui.Drawable
for _, component := range l.Components {
if component.Type == Type {
components = append(components, component.Drawable)
}
}
return components
2019-01-31 00:02:38 +00:00
}
func (l *Layout) changeMode(m Mode) {
l.mode = m
l.ChangeModeEvents <- m
}
2019-02-11 02:51:55 +00:00
func (l *Layout) HandleConsoleEvent(e string) {
switch e {
2019-03-03 01:04:02 +00:00
case console.KeyPause:
if l.mode == ModePause {
l.changeMode(ModeDefault)
} else {
if l.getSelectedComponent().Type == config.TypeRunChart {
chart := l.getSelectedComponent().Drawable.(*runchart.RunChart)
chart.DisableSelection()
}
l.menu.idle()
l.changeMode(ModePause)
}
2019-02-11 02:51:55 +00:00
case console.KeyEnter:
switch l.mode {
case ModeComponentSelect:
l.menu.choose()
l.changeMode(ModeMenuOptionSelect)
2019-02-11 02:51:55 +00:00
case ModeMenuOptionSelect:
option := l.menu.getSelectedOption()
switch option {
case MenuOptionMove:
l.changeMode(ModeComponentMove)
2019-02-11 02:51:55 +00:00
l.menu.moveOrResize()
case MenuOptionResize:
l.changeMode(ModeComponentResize)
2019-02-11 02:51:55 +00:00
l.menu.moveOrResize()
case MenuOptionPinpoint:
l.changeMode(ModeChartPinpoint)
2019-02-11 02:51:55 +00:00
l.menu.idle()
2019-02-15 04:34:45 +00:00
chart := l.getSelectedComponent().Drawable.(*runchart.RunChart)
2019-02-11 02:51:55 +00:00
chart.MoveSelection(0)
2019-02-11 04:06:48 +00:00
case MenuOptionResume:
l.changeMode(ModeDefault)
2019-02-11 02:51:55 +00:00
l.menu.idle()
}
case ModeComponentMove:
fallthrough
case ModeComponentResize:
l.menu.idle()
l.changeMode(ModeDefault)
2019-02-11 02:51:55 +00:00
}
case console.KeyEsc:
switch l.mode {
case ModeChartPinpoint:
2019-02-15 04:34:45 +00:00
chart := l.getSelectedComponent().Drawable.(*runchart.RunChart)
2019-02-11 02:51:55 +00:00
chart.DisableSelection()
fallthrough
case ModeComponentSelect:
fallthrough
case ModeMenuOptionSelect:
l.menu.idle()
l.changeMode(ModeDefault)
2019-02-11 02:51:55 +00:00
}
case console.KeyLeft:
switch l.mode {
case ModeDefault:
l.changeMode(ModeComponentSelect)
2019-02-11 02:51:55 +00:00
l.menu.highlight(l.getComponent(l.selection))
case ModeChartPinpoint:
2019-02-15 04:34:45 +00:00
chart := l.getSelectedComponent().Drawable.(*runchart.RunChart)
2019-02-11 02:51:55 +00:00
chart.MoveSelection(-1)
case ModeComponentSelect:
l.moveSelection(e)
2019-02-11 02:51:55 +00:00
l.menu.highlight(l.getComponent(l.selection))
case ModeComponentMove:
l.getSelectedComponent().Move(-1, 0)
case ModeComponentResize:
l.getSelectedComponent().Resize(-1, 0)
}
case console.KeyRight:
switch l.mode {
case ModeDefault:
l.changeMode(ModeComponentSelect)
2019-02-11 02:51:55 +00:00
l.menu.highlight(l.getComponent(l.selection))
case ModeChartPinpoint:
2019-02-15 04:34:45 +00:00
chart := l.getSelectedComponent().Drawable.(*runchart.RunChart)
2019-02-11 02:51:55 +00:00
chart.MoveSelection(1)
case ModeComponentSelect:
l.moveSelection(e)
2019-02-11 02:51:55 +00:00
l.menu.highlight(l.getComponent(l.selection))
case ModeComponentMove:
l.getSelectedComponent().Move(1, 0)
case ModeComponentResize:
l.getSelectedComponent().Resize(1, 0)
}
case console.KeyUp:
switch l.mode {
2019-02-16 03:46:03 +00:00
case ModeDefault:
l.changeMode(ModeComponentSelect)
2019-02-16 03:46:03 +00:00
l.menu.highlight(l.getComponent(l.selection))
case ModeComponentSelect:
l.moveSelection(e)
2019-02-16 03:46:03 +00:00
l.menu.highlight(l.getComponent(l.selection))
2019-02-11 02:51:55 +00:00
case ModeMenuOptionSelect:
l.menu.up()
case ModeComponentMove:
l.getSelectedComponent().Move(0, -1)
case ModeComponentResize:
l.getSelectedComponent().Resize(0, -1)
}
case console.KeyDown:
switch l.mode {
2019-02-16 03:46:03 +00:00
case ModeDefault:
l.changeMode(ModeComponentSelect)
2019-02-16 03:46:03 +00:00
l.menu.highlight(l.getComponent(l.selection))
case ModeComponentSelect:
l.moveSelection(e)
2019-02-16 03:46:03 +00:00
l.menu.highlight(l.getComponent(l.selection))
2019-02-11 02:51:55 +00:00
case ModeMenuOptionSelect:
l.menu.down()
case ModeComponentMove:
l.getSelectedComponent().Move(0, 1)
case ModeComponentResize:
l.getSelectedComponent().Resize(0, 1)
}
}
}
2019-02-11 02:51:55 +00:00
func (l *Layout) ChangeDimensions(width, height int) {
l.SetRect(0, 0, width, height)
2019-01-31 00:02:38 +00:00
}
func (l *Layout) getComponent(i int) Component {
return l.Components[i]
}
func (l *Layout) getSelectedComponent() *Component {
return &l.Components[l.selection]
}
func (l *Layout) moveSelection(direction string) {
previouslySelected := *l.getSelectedComponent()
newlySelectedIndex := l.selection
for i, current := range l.Components {
if current == previouslySelected {
continue
}
if newlySelectedIndex < 0 {
newlySelectedIndex = i
}
var previouslySelectedCornerPoint image.Point
var newlySelectedCornerPoint image.Point
var currentCornerPoint image.Point
switch direction {
case console.KeyLeft:
previouslySelectedCornerPoint = getRectLeftAgeCenter(previouslySelected.Drawable.GetRect())
newlySelectedCornerPoint = getRectRightAgeCenter(l.getComponent(newlySelectedIndex).Drawable.GetRect())
currentCornerPoint = getRectRightAgeCenter(current.Drawable.GetRect())
case console.KeyRight:
previouslySelectedCornerPoint = getRectRightAgeCenter(previouslySelected.Drawable.GetRect())
newlySelectedCornerPoint = getRectLeftAgeCenter(l.getComponent(newlySelectedIndex).Drawable.GetRect())
currentCornerPoint = getRectLeftAgeCenter(current.Drawable.GetRect())
case console.KeyUp:
previouslySelectedCornerPoint = getRectTopAgeCenter(previouslySelected.Drawable.GetRect())
newlySelectedCornerPoint = getRectBottomAgeCenter(l.getComponent(newlySelectedIndex).Drawable.GetRect())
currentCornerPoint = getRectBottomAgeCenter(current.Drawable.GetRect())
case console.KeyDown:
previouslySelectedCornerPoint = getRectBottomAgeCenter(previouslySelected.Drawable.GetRect())
newlySelectedCornerPoint = getRectTopAgeCenter(l.getComponent(newlySelectedIndex).Drawable.GetRect())
currentCornerPoint = getRectTopAgeCenter(current.Drawable.GetRect())
}
if getDistance(previouslySelectedCornerPoint, currentCornerPoint) < getDistance(previouslySelectedCornerPoint, newlySelectedCornerPoint) {
newlySelectedIndex = i
}
}
l.selection = newlySelectedIndex
}
2019-02-11 02:51:55 +00:00
func (l *Layout) Draw(buffer *ui.Buffer) {
2019-01-31 00:02:38 +00:00
2019-03-01 03:44:01 +00:00
columnWidth := float64(l.GetRect().Dx()) / float64(columnsCount)
rowHeight := float64(l.GetRect().Dy()-statusbarHeight) / float64(rowsCount)
2019-01-31 00:02:38 +00:00
for _, component := range l.Components {
2019-01-31 00:02:38 +00:00
2019-03-01 03:44:01 +00:00
x1 := math.Floor(float64(component.Position.X) * columnWidth)
y1 := math.Floor(float64(component.Position.Y) * rowHeight)
x2 := x1 + math.Floor(float64(component.Size.X))*columnWidth
y2 := y1 + math.Floor(float64(component.Size.Y))*rowHeight
2019-01-31 00:02:38 +00:00
2019-03-02 21:38:36 +00:00
if x2-x1 < minDimension {
x2 = x1 + minDimension
}
if y2-y1 < minDimension {
y2 = y1 + minDimension
}
2019-01-31 01:41:51 +00:00
component.Drawable.SetRect(int(x1), int(y1), int(x2), int(y2))
2019-02-03 03:30:45 +00:00
component.Drawable.Draw(buffer)
2019-01-31 00:02:38 +00:00
}
2019-02-11 02:51:55 +00:00
2019-02-25 00:37:57 +00:00
l.statusbar.SetRect(
0, l.GetRect().Dy()-statusbarHeight,
l.GetRect().Dx(), l.GetRect().Dy())
2019-02-25 00:08:36 +00:00
l.statusbar.Draw(buffer)
2019-03-03 01:04:02 +00:00
l.menu.Draw(buffer)
2019-01-31 00:02:38 +00:00
}