func startUI(update chan *network.RoomUpdate, activity chan string, cmd chan<- network.GameMsg, character string) { err := ui.Init() if err != nil { panic(err) } defer ui.Close() //ui.UseTheme("helloworld") height := ui.TermHeight() descPar := ui.NewPar("") descPar.Height = ((height - 3) / 2) - 5 //descPar.Width = 50 descPar.TextFgColor = ui.ColorWhite descPar.Border.Label = "" descPar.Border.FgColor = ui.ColorCyan exitPar := ui.NewPar("") exitPar.Height = 5 exitPar.TextFgColor = ui.ColorWhite exitPar.Border.Label = "Exits" exitPar.Border.FgColor = ui.ColorCyan entityList := ui.NewList() entityList.ItemFgColor = ui.ColorYellow entityList.Border.Label = "Entities" entityList.Height = (height - 3) / 2 entityList.Y = 0 activityList := ui.NewList() activityList.ItemFgColor = ui.ColorWhite activityList.Border.Label = "Activity" activityList.Height = (height - 3) / 2 activityList.Y = 0 cmdPar := ui.NewPar("") cmdPar.Height = 3 //cmdPar.Width = 50 cmdPar.TextFgColor = ui.ColorWhite cmdPar.Border.Label = "Enter Command" cmdPar.Border.FgColor = ui.ColorCyan // build ui.Body.AddRows( ui.NewRow( ui.NewCol(4, 0, entityList), ui.NewCol(8, 0, descPar, exitPar)), ui.NewRow( ui.NewCol(12, 0, activityList)), ui.NewRow( ui.NewCol(12, 0, cmdPar))) ui.Body.Align() ui.Render(ui.Body) evt := ui.EventCh() redraw := make(chan bool) done := make(chan bool) clearActivity := false var prevCmds []string prevCmd := 0 for { select { // Get an event from the keyboard, mouse, screen resize, etc case e := <-evt: switch e.Type { case ui.EventKey: switch e.Ch { case 0: // e.Key is valid if e.Ch is 0 switch e.Key { case ui.KeyBackspace2: fallthrough case ui.KeyBackspace: len := len(cmdPar.Text) if len > 0 { cmdPar.Text = cmdPar.Text[:len-1] go func() { redraw <- true }() } case ui.KeySpace: cmdPar.Text += " " go func() { redraw <- true }() case ui.KeyEsc: fallthrough case ui.KeyCtrlC: return case ui.KeyEnter: msg, err := parseCmd(cmdPar.Text) if err != nil { //TODO: alert the user somehow break } // Set a flag so we know to clear the activity list on the next update if msg.CmdReq.Cmd == "go" { // go command will produce a room update or an error msg // both with set this back to false, the room update after clearing the list clearActivity = true } cmd <- msg prevCmds = append(prevCmds, cmdPar.Text) prevCmd = len(prevCmds) cmdPar.Text = "" go func() { redraw <- true }() case ui.KeyArrowUp: if prevCmd > 0 { prevCmd-- cmdPar.Text = prevCmds[prevCmd] go func() { redraw <- true }() } case ui.KeyArrowDown: if prevCmd < (len(prevCmds) - 1) { prevCmd++ cmdPar.Text = prevCmds[prevCmd] go func() { redraw <- true }() } else if prevCmd == (len(prevCmds) - 1) { prevCmd++ cmdPar.Text = "" go func() { redraw <- true }() } //default: // cmdPar.Text += strconv.Itoa(int(e.Key)) // go func() { redraw <- true }() } default: cmdPar.Text += string(e.Ch) go func() { redraw <- true }() } case ui.EventResize: height := ui.TermHeight() descPar.Height = ((height - 3) / 2) - 5 entityList.Height = (height - 3) / 2 activityList.Height = (height - 3) / 2 if len(activityList.Items) > (activityList.Height - 2) { //Slice the top off activityList.Items = activityList.Items[len(activityList.Items)-(activityList.Height-2) : len(activityList.Items)] } ui.Body.Width = ui.TermWidth() ui.Body.Align() go func() { redraw <- true }() } // We got a room update from the server case u := <-update: var entities []string for _, pc := range u.Pcs { entities = append(entities, pc+" (PC)") } entities = append(entities, u.Npcs...) entityList.Items = entities if clearActivity { activityList.Items = nil clearActivity = false } if u.Message != "" { addActivity(activityList, u.Message) } exitStr := "" if u.North { exitStr += " ^ North\n" } else { exitStr += " \n" } if u.West { exitStr += "West < " } else { exitStr += " " } if u.East { exitStr += " > East \n" } else { exitStr += " \n" } if u.South { exitStr += " v South" } exitPar.Text = exitStr descPar.Text = u.Desc descPar.Border.Label = u.Name go func() { redraw <- true }() // Local write request to activity dialog case a := <-activity: clearActivity = false addActivity(activityList, a) go func() { redraw <- true }() // Request to redraw case <-redraw: ui.Render(ui.Body) // We are done case <-done: return } } }
func createUi(state *render.RenderState) { err := ui.Init() if err != nil { panic(err) } defer ui.Close() ui.UseTheme("helloworld") bc := ui.NewBarChart() data := []int{} bclabels := []string{} bc.Border.Label = "SumoCLI" bc.Data = data //bc.Width = 26 bc.Height = ui.TermHeight() - 10 bc.DataLabels = bclabels bc.TextColor = ui.ColorGreen bc.BarColor = ui.ColorRed bc.NumColor = ui.ColorYellow // build layout ui.Body.AddRows( ui.NewRow( ui.NewCol(12, 0, bc))) // calculate layout ui.Body.Align() done := make(chan bool) redraw := make(chan bool) update := func() error { //fmt.Println("updating") bars := render.Columns(*state.Messages) columns := render.ColumnNames(bars) query, ok := (*state.Meta)["_queryString"] if ok && query.(string) != bc.Border.Label { bc.Border.Label = query.(string) } dataCol := render.NumericColumn(columns) data := []int{} labels := []string{} extractor := render.LabelExtractor(columns) for _, msg := range *state.Messages { labels = append(labels, extractor(msg)) // go is the worst floatVal, _ := strconv.ParseFloat(fmt.Sprint(msg[dataCol]), 64) rowData := int(floatVal) data = append(data, rowData) } bc.Data = data var numCols int if len(data) > 0 { numCols = len(data) } else { numCols = 1 } newBarWidth := (ui.TermWidth() - 10) / numCols if int(newBarWidth) != int(bc.BarWidth) { bc.BarWidth = newBarWidth } if len(labels) != len(bc.DataLabels) { bc.DataLabels = labels } redraw <- true return nil } state.Flush = update 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) } } }