Consolidate UI packages

pull/80/head
Miguel Mota 3 years ago
parent e89c5e65f0
commit 394d35473d

@ -1,7 +1,7 @@
package main package main
import ( import (
"github.com/miguelmota/cointop/cointop/cmd" cmd "github.com/miguelmota/cointop/cmd/commands"
) )
func main() { func main() {

@ -2,7 +2,7 @@ package cmd
import ( import (
"github.com/miguelmota/cointop/cointop" "github.com/miguelmota/cointop/cointop"
"github.com/miguelmota/cointop/cointop/common/filecache" "github.com/miguelmota/cointop/pkg/filecache"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )

@ -2,7 +2,7 @@ package cmd
import ( import (
"github.com/miguelmota/cointop/cointop" "github.com/miguelmota/cointop/cointop"
"github.com/miguelmota/cointop/cointop/common/filecache" "github.com/miguelmota/cointop/pkg/filecache"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )

@ -6,7 +6,7 @@ import (
"fmt" "fmt"
"time" "time"
cssh "github.com/miguelmota/cointop/cointop/ssh" cssh "github.com/miguelmota/cointop/pkg/ssh"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )

@ -0,0 +1,18 @@
package cointop
// SetActiveView sets the active view
func (ct *Cointop) SetActiveView(v string) error {
ct.g.SetViewOnTop(v)
ct.g.SetCurrentView(v)
if v == ct.Views.SearchField.Name() {
ct.Views.SearchField.SetCursor(1, 0)
ct.Views.SearchField.Update("/")
} else if v == ct.Views.Table.Name() {
ct.g.SetViewOnTop(ct.Views.Statusbar.Name())
}
if v == ct.Views.PortfolioUpdateMenu.Name() {
ct.g.SetViewOnTop(ct.Views.Input.Name())
ct.g.SetCurrentView(ct.Views.Input.Name())
}
return nil
}

@ -6,18 +6,18 @@ import (
"sync" "sync"
"time" "time"
"github.com/miguelmota/cointop/cointop/common/gizak/termui" "github.com/miguelmota/cointop/pkg/chartplot"
"github.com/miguelmota/cointop/cointop/common/timeutil" "github.com/miguelmota/cointop/pkg/timeutil"
"github.com/miguelmota/cointop/pkg/ui"
) )
// ChartView is structure for chart view // ChartView is structure for chart view
type ChartView struct { type ChartView = ui.View
*View
}
// NewChartView returns a new chart view // NewChartView returns a new chart view
func NewChartView() *ChartView { func NewChartView() *ChartView {
return &ChartView{NewView("chart")} var view *ChartView = ui.NewView("chart")
return view
} }
var chartLock sync.Mutex var chartLock sync.Mutex
@ -58,10 +58,6 @@ func ChartRangesMap() map[string]time.Duration {
// UpdateChart updates the chart view // UpdateChart updates the chart view
func (ct *Cointop) UpdateChart() error { func (ct *Cointop) UpdateChart() error {
ct.debuglog("UpdateChart()") ct.debuglog("UpdateChart()")
if ct.Views.Chart.Backing() == nil {
return nil
}
chartLock.Lock() chartLock.Lock()
defer chartLock.Unlock() defer chartLock.Unlock()
@ -83,21 +79,15 @@ func (ct *Cointop) UpdateChart() error {
var s string var s string
for j := range ct.State.chartPoints[i] { for j := range ct.State.chartPoints[i] {
p := ct.State.chartPoints[i][j] p := ct.State.chartPoints[i][j]
s = fmt.Sprintf("%s%c", s, p.Ch) s = fmt.Sprintf("%s%c", s, p)
} }
body = fmt.Sprintf("%s%s\n", body, s) body = fmt.Sprintf("%s%s\n", body, s)
} }
} }
ct.Update(func() error { ct.UpdateUI(func() error {
if ct.Views.Chart.Backing() == nil { return ct.Views.Chart.Update(ct.colorscheme.Chart(body))
return nil
}
ct.Views.Chart.Backing().Clear()
fmt.Fprint(ct.Views.Chart.Backing(), ct.colorscheme.Chart(body))
return nil
}) })
return nil return nil
@ -114,12 +104,8 @@ func (ct *Cointop) ChartPoints(symbol string, name string) error {
// TODO: not do this (SoC) // TODO: not do this (SoC)
go ct.UpdateMarketbar() go ct.UpdateMarketbar()
chart := termui.NewLineChart() chart := chartplot.NewChartPlot()
chart.Height = ct.State.chartHeight chart.SetHeight(ct.State.chartHeight)
chart.Border = false
// NOTE: empty list means don't show x-axis labels
chart.DataLabels = []string{""}
rangeseconds := ct.chartRangesMap[ct.State.selectedChartRange] rangeseconds := ct.chartRangesMap[ct.State.selectedChartRange]
if ct.State.selectedChartRange == "YTD" { if ct.State.selectedChartRange == "YTD" {
@ -165,8 +151,6 @@ func (ct *Cointop) ChartPoints(symbol string, name string) error {
return nil return nil
} }
// NOTE: edit `termui.LineChart.shortenFloatVal(float64)` to not
// use exponential notation.
for i := range graphData.Price { for i := range graphData.Price {
price := graphData.Price[i][1] price := graphData.Price[i][1]
data = append(data, price) data = append(data, price)
@ -181,32 +165,8 @@ func (ct *Cointop) ChartPoints(symbol string, name string) error {
} }
} }
chart.Data = data chart.SetData(data)
termui.Body = termui.NewGrid() ct.State.chartPoints = chart.GetChartPoints(maxX)
termui.Body.Width = maxX
termui.Body.AddRows(
termui.NewRow(
termui.NewCol(12, 0, chart),
),
)
var points [][]termui.Cell
// calculate layout
termui.Body.Align()
w := termui.Body.Width
h := chart.Height
row := termui.Body.Rows[0]
b := row.Buffer()
for i := 0; i < h; i = i + 1 {
var rowpoints []termui.Cell
for j := 0; j < w; j = j + 1 {
p := b.At(j, i)
rowpoints = append(rowpoints, p)
}
points = append(points, rowpoints)
}
ct.State.chartPoints = points
return nil return nil
} }
@ -221,12 +181,8 @@ func (ct *Cointop) PortfolioChart() error {
// TODO: not do this (SoC) // TODO: not do this (SoC)
go ct.UpdateMarketbar() go ct.UpdateMarketbar()
chart := termui.NewLineChart() chart := chartplot.NewChartPlot()
chart.Height = ct.State.chartHeight chart.SetHeight(ct.State.chartHeight)
chart.Border = false
// NOTE: empty list means don't show x-axis labels
chart.DataLabels = []string{""}
rangeseconds := ct.chartRangesMap[ct.State.selectedChartRange] rangeseconds := ct.chartRangesMap[ct.State.selectedChartRange]
if ct.State.selectedChartRange == "YTD" { if ct.State.selectedChartRange == "YTD" {
@ -298,32 +254,8 @@ func (ct *Cointop) PortfolioChart() error {
} }
} }
chart.Data = data chart.SetData(data)
termui.Body = termui.NewGrid() ct.State.chartPoints = chart.GetChartPoints(maxX)
termui.Body.Width = maxX
termui.Body.AddRows(
termui.NewRow(
termui.NewCol(12, 0, chart),
),
)
var points [][]termui.Cell
// calculate layout
termui.Body.Align()
w := termui.Body.Width
h := chart.Height
row := termui.Body.Rows[0]
b := row.Buffer()
for i := 0; i < h; i = i + 1 {
var rowpoints []termui.Cell
for j := 0; j < w; j = j + 1 {
p := b.At(j, i)
rowpoints = append(rowpoints, p)
}
points = append(points, rowpoints)
}
ct.State.chartPoints = points
return nil return nil
} }
@ -434,15 +366,9 @@ func (ct *Cointop) ToggleCoinChart() error {
// ShowChartLoader shows chart loading indicator // ShowChartLoader shows chart loading indicator
func (ct *Cointop) ShowChartLoader() error { func (ct *Cointop) ShowChartLoader() error {
ct.debuglog("ShowChartLoader()") ct.debuglog("ShowChartLoader()")
ct.Update(func() error { ct.UpdateUI(func() error {
if ct.Views.Chart.Backing() == nil {
return nil
}
content := "\n\nLoading..." content := "\n\nLoading..."
ct.Views.Chart.Backing().Clear() return ct.Views.Chart.Update(ct.colorscheme.Chart(content))
fmt.Fprint(ct.Views.Chart.Backing(), ct.colorscheme.Chart(content))
return nil
}) })
return nil return nil

@ -9,12 +9,12 @@ import (
"sync" "sync"
"time" "time"
"github.com/miguelmota/cointop/cointop/common/api" "github.com/miguelmota/cointop/pkg/api"
"github.com/miguelmota/cointop/cointop/common/api/types" "github.com/miguelmota/cointop/pkg/api/types"
"github.com/miguelmota/cointop/cointop/common/filecache" "github.com/miguelmota/cointop/pkg/filecache"
"github.com/miguelmota/cointop/cointop/common/gizak/termui" "github.com/miguelmota/cointop/pkg/pathutil"
"github.com/miguelmota/cointop/cointop/common/pathutil" "github.com/miguelmota/cointop/pkg/table"
"github.com/miguelmota/cointop/cointop/common/table" "github.com/miguelmota/cointop/pkg/ui"
"github.com/miguelmota/gocui" "github.com/miguelmota/gocui"
"github.com/patrickmn/go-cache" "github.com/patrickmn/go-cache"
) )
@ -44,7 +44,7 @@ type State struct {
allCoinsSlugMap sync.Map allCoinsSlugMap sync.Map
cacheDir string cacheDir string
coins []*Coin coins []*Coin
chartPoints [][]termui.Cell chartPoints [][]rune
currencyConversion string currencyConversion string
convertMenuVisible bool convertMenuVisible bool
defaultView string defaultView string
@ -79,6 +79,7 @@ type State struct {
// Cointop cointop // Cointop cointop
type Cointop struct { type Cointop struct {
g *gocui.Gui g *gocui.Gui
ui *ui.UI
ActionsMap map[string]bool ActionsMap map[string]bool
apiKeys *APIKeys apiKeys *APIKeys
cache *cache.Cache cache *cache.Cache
@ -406,26 +407,27 @@ func NewCointop(config *Config) (*Cointop, error) {
// Run runs cointop // Run runs cointop
func (ct *Cointop) Run() error { func (ct *Cointop) Run() error {
ct.debuglog("run()") ct.debuglog("run()")
g, err := gocui.NewGui(gocui.Output256) ui, err := ui.NewUI()
if err != nil { if err != nil {
return fmt.Errorf("new gocui: %v", err) return err
} }
g.FgColor = ct.colorscheme.BaseFg() ui.SetFgColor(ct.colorscheme.BaseFg())
g.BgColor = ct.colorscheme.BaseBg() ui.SetBgColor(ct.colorscheme.BaseBg())
ct.g = g ct.ui = ui
defer g.Close() ct.g = ui.GetGocui()
defer ui.Close()
g.InputEsc = true ui.SetInputEsc(true)
g.Mouse = true ui.SetMouse(true)
g.Highlight = true ui.SetHighlight(true)
g.SetManagerFunc(ct.layout) ui.SetManagerFunc(ct.layout)
if err := ct.Keybindings(g); err != nil { if err := ct.Keybindings(ct.g); err != nil {
return fmt.Errorf("keybindings: %v", err) return fmt.Errorf("keybindings: %v", err)
} }
ct.State.running = true ct.State.running = true
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit { if err := ui.MainLoop(); err != nil && err != gocui.ErrQuit {
return fmt.Errorf("main loop: %v", err) return fmt.Errorf("main loop: %v", err)
} }

@ -229,18 +229,6 @@ func (c *Colorscheme) TableRowFavoriteSprintf() ISprintf {
return c.toSprintf("table_row_favorite") return c.toSprintf("table_row_favorite")
} }
// SetViewColor ...
func (c *Colorscheme) SetViewColor(view *gocui.View, name string) {
view.FgColor = c.gocuiFgColor(name)
view.BgColor = c.gocuiBgColor(name)
}
// SetViewActiveColor ...
func (c *Colorscheme) SetViewActiveColor(view *gocui.View, name string) {
view.SelFgColor = c.gocuiFgColor(name)
view.SelBgColor = c.gocuiBgColor(name)
}
func (c *Colorscheme) toSprintf(name string) ISprintf { func (c *Colorscheme) toSprintf(name string) ISprintf {
if cached, ok := c.cache[name]; ok { if cached, ok := c.cache[name]; ok {
return cached return cached

@ -10,7 +10,7 @@ import (
"time" "time"
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
"github.com/miguelmota/cointop/cointop/common/pathutil" "github.com/miguelmota/cointop/pkg/pathutil"
) )
var fileperm = os.FileMode(0644) var fileperm = os.FileMode(0644)

@ -6,8 +6,9 @@ import (
"sort" "sort"
"strings" "strings"
color "github.com/miguelmota/cointop/cointop/common/color" color "github.com/miguelmota/cointop/pkg/color"
"github.com/miguelmota/cointop/cointop/common/pad" "github.com/miguelmota/cointop/pkg/pad"
"github.com/miguelmota/cointop/pkg/ui"
) )
// FiatCurrencyNames is a mpa of currency symbols to names. // FiatCurrencyNames is a mpa of currency symbols to names.
@ -105,13 +106,12 @@ var CurrencySymbolMap = map[string]string{
var alphanumericcharacters = []rune{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'} var alphanumericcharacters = []rune{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}
// ConvertMenuView is structure for convert menu view // ConvertMenuView is structure for convert menu view
type ConvertMenuView struct { type ConvertMenuView = ui.View
*View
}
// NewConvertMenuView returns a new convert menu view // NewConvertMenuView returns a new convert menu view
func NewConvertMenuView() *ConvertMenuView { func NewConvertMenuView() *ConvertMenuView {
return &ConvertMenuView{NewView("convertmenu")} var view *ConvertMenuView = ui.NewView("convertmenu")
return view
} }
// IsSupportedCurrencyConversion returns true if it's a supported currency conversion // IsSupportedCurrencyConversion returns true if it's a supported currency conversion
@ -158,7 +158,7 @@ func (ct *Cointop) SortedSupportedCurrencyConversions() []string {
} }
// UpdateConvertMenu updates the convert menu // UpdateConvertMenu updates the convert menu
func (ct *Cointop) UpdateConvertMenu() { func (ct *Cointop) UpdateConvertMenu() error {
ct.debuglog("updateConvertMenu()") ct.debuglog("updateConvertMenu()")
header := ct.colorscheme.MenuHeader(fmt.Sprintf(" Currency Conversion %s\n\n", pad.Left("[q] close menu ", ct.maxTableWidth-20, " "))) header := ct.colorscheme.MenuHeader(fmt.Sprintf(" Currency Conversion %s\n\n", pad.Left("[q] close menu ", ct.maxTableWidth-20, " ")))
helpline := " Press the corresponding key to select currency for conversion\n\n" helpline := " Press the corresponding key to select currency for conversion\n\n"
@ -204,16 +204,12 @@ func (ct *Cointop) UpdateConvertMenu() {
} }
content := fmt.Sprintf("%s%s%s", header, helpline, body) content := fmt.Sprintf("%s%s%s", header, helpline, body)
ct.Update(func() error { ct.UpdateUI(func() error {
if ct.Views.ConvertMenu.Backing() == nil { ct.Views.ConvertMenu.SetFrame(true)
return nil return ct.Views.ConvertMenu.Update(content)
}
ct.Views.ConvertMenu.Backing().Clear()
ct.Views.ConvertMenu.Backing().Frame = true
fmt.Fprintln(ct.Views.ConvertMenu.Backing(), content)
return nil
}) })
return nil
} }
// SetCurrencyConverstion sets the currency conversion // SetCurrencyConverstion sets the currency conversion
@ -274,16 +270,11 @@ func (ct *Cointop) ShowConvertMenu() error {
func (ct *Cointop) HideConvertMenu() error { func (ct *Cointop) HideConvertMenu() error {
ct.debuglog("hideConvertMenu()") ct.debuglog("hideConvertMenu()")
ct.State.convertMenuVisible = false ct.State.convertMenuVisible = false
ct.SetViewOnBottom(ct.Views.ConvertMenu.Name()) ct.ui.SetViewOnBottom(ct.Views.ConvertMenu)
ct.SetActiveView(ct.Views.Table.Name()) ct.SetActiveView(ct.Views.Table.Name())
ct.Update(func() error { ct.UpdateUI(func() error {
if ct.Views.ConvertMenu.Backing() == nil { ct.Views.ConvertMenu.SetFrame(false)
return nil return ct.Views.ConvertMenu.Update("")
}
ct.Views.ConvertMenu.Backing().Clear()
ct.Views.ConvertMenu.Backing().Frame = false
fmt.Fprintln(ct.Views.ConvertMenu.Backing(), "")
return nil return nil
}) })
return nil return nil

@ -3,7 +3,7 @@ package cointop
import ( import (
"fmt" "fmt"
"github.com/miguelmota/cointop/cointop/common/api" "github.com/miguelmota/cointop/pkg/api"
) )
// DominanceConfig is the config options for the dominance command // DominanceConfig is the config options for the dominance command

@ -4,17 +4,17 @@ import (
"fmt" "fmt"
"sort" "sort"
"github.com/miguelmota/cointop/cointop/common/pad" "github.com/miguelmota/cointop/pkg/pad"
"github.com/miguelmota/cointop/pkg/ui"
) )
// HelpView is structure for help view // HelpView is structure for help view
type HelpView struct { type HelpView = ui.View
*View
}
// NewHelpView returns a new help view // NewHelpView returns a new help view
func NewHelpView() *HelpView { func NewHelpView() *HelpView {
return &HelpView{NewView("help")} var view *HelpView = ui.NewView("help")
return view
} }
// UpdateHelp updates the help views // UpdateHelp updates the help views
@ -60,15 +60,9 @@ func (ct *Cointop) UpdateHelp() {
infoLine := "See git.io/cointop for more info.\n Press ESC to return." infoLine := "See git.io/cointop for more info.\n Press ESC to return."
content := fmt.Sprintf("%s %s\n %s\n\n %s\n\n%s\n %s", header, versionLine, licenseLine, instructionsLine, body, infoLine) content := fmt.Sprintf("%s %s\n %s\n\n %s\n\n%s\n %s", header, versionLine, licenseLine, instructionsLine, body, infoLine)
ct.Update(func() error { ct.UpdateUI(func() error {
if ct.Views.Help.Backing() == nil { ct.Views.Help.SetFrame(true)
return nil return ct.Views.Help.Update(content)
}
ct.Views.Help.Backing().Clear()
ct.Views.Help.Backing().Frame = true
fmt.Fprintln(ct.Views.Help.Backing(), content)
return nil
}) })
} }
@ -85,17 +79,11 @@ func (ct *Cointop) ShowHelp() error {
func (ct *Cointop) HideHelp() error { func (ct *Cointop) HideHelp() error {
ct.debuglog("hideHelp()") ct.debuglog("hideHelp()")
ct.State.helpVisible = false ct.State.helpVisible = false
ct.SetViewOnBottom(ct.Views.Help.Name()) ct.ui.SetViewOnBottom(ct.Views.Help)
ct.SetActiveView(ct.Views.Table.Name()) ct.SetActiveView(ct.Views.Table.Name())
ct.Update(func() error { ct.UpdateUI(func() error {
if ct.Views.Help.Backing() == nil { ct.Views.Help.SetFrame(false)
return nil return ct.Views.Help.Update("")
}
ct.Views.Help.Backing().Clear()
ct.Views.Help.Backing().Frame = false
fmt.Fprintln(ct.Views.Help.Backing(), "")
return nil
}) })
return nil return nil
} }

@ -3,8 +3,6 @@ package cointop
import ( import (
"fmt" "fmt"
"strings" "strings"
"github.com/miguelmota/gocui"
) )
// TODO: break up into small functions // TODO: break up into small functions
@ -12,7 +10,7 @@ import (
var lastWidth int var lastWidth int
// layout sets initial layout // layout sets initial layout
func (ct *Cointop) layout(g *gocui.Gui) error { func (ct *Cointop) layout() error {
ct.debuglog("layout()") ct.debuglog("layout()")
maxY := ct.height() maxY := ct.height()
maxX := ct.ClampedWidth() maxX := ct.ClampedWidth()
@ -43,13 +41,10 @@ func (ct *Cointop) layout(g *gocui.Gui) error {
} }
if !ct.State.hideMarketbar { if !ct.State.hideMarketbar {
if v, err := g.SetView(ct.Views.Marketbar.Name(), 0, topOffset, maxX, 2); err != nil { if err := ct.ui.SetView(ct.Views.Marketbar, 0, topOffset, maxX, 2); err != nil {
if err != gocui.ErrUnknownView { ct.Views.Marketbar.SetFrame(false)
return err ct.Views.Marketbar.SetFgColor(ct.colorscheme.gocuiFgColor(ct.Views.Marketbar.Name()))
} ct.Views.Marketbar.SetBgColor(ct.colorscheme.gocuiBgColor(ct.Views.Marketbar.Name()))
ct.Views.Marketbar.SetBacking(v)
ct.Views.Marketbar.Backing().Frame = false
ct.colorscheme.SetViewColor(ct.Views.Marketbar.Backing(), "marketbar")
go func() { go func() {
ct.UpdateMarketbar() ct.UpdateMarketbar()
_, found := ct.cache.Get(ct.Views.Marketbar.Name()) _, found := ct.cache.Get(ct.Views.Marketbar.Name())
@ -61,7 +56,7 @@ func (ct *Cointop) layout(g *gocui.Gui) error {
} }
} else { } else {
if ct.Views.Marketbar.Backing() != nil { if ct.Views.Marketbar.Backing() != nil {
if err := g.DeleteView(ct.Views.Marketbar.Name()); err != nil { if err := ct.g.DeleteView(ct.Views.Marketbar.Name()); err != nil {
return err return err
} }
ct.Views.Marketbar.SetBacking(nil) ct.Views.Marketbar.SetBacking(nil)
@ -71,14 +66,11 @@ func (ct *Cointop) layout(g *gocui.Gui) error {
topOffset = topOffset + marketbarHeight topOffset = topOffset + marketbarHeight
if !ct.State.hideChart { if !ct.State.hideChart {
if v, err := g.SetView(ct.Views.Chart.Name(), 0, topOffset, maxX, topOffset+chartHeight+marketbarHeight); err != nil { if err := ct.ui.SetView(ct.Views.Chart, 0, topOffset, maxX, topOffset+chartHeight+marketbarHeight); err != nil {
if err != gocui.ErrUnknownView { ct.Views.Chart.Clear()
return err ct.Views.Chart.SetFrame(false)
} ct.Views.Chart.SetFgColor(ct.colorscheme.gocuiFgColor(ct.Views.Chart.Name()))
v.Clear() ct.Views.Chart.SetBgColor(ct.colorscheme.gocuiBgColor(ct.Views.Chart.Name()))
ct.Views.Chart.SetBacking(v)
ct.Views.Chart.Backing().Frame = false
ct.colorscheme.SetViewColor(ct.Views.Chart.Backing(), "chart")
go func() { go func() {
ct.UpdateChart() ct.UpdateChart()
cachekey := strings.ToLower(fmt.Sprintf("%s_%s", "globaldata", strings.Replace(ct.State.selectedChartRange, " ", "", -1))) cachekey := strings.ToLower(fmt.Sprintf("%s_%s", "globaldata", strings.Replace(ct.State.selectedChartRange, " ", "", -1)))
@ -91,7 +83,7 @@ func (ct *Cointop) layout(g *gocui.Gui) error {
} }
} else { } else {
if ct.Views.Chart.Backing() != nil { if ct.Views.Chart.Backing() != nil {
if err := g.DeleteView(ct.Views.Chart.Name()); err != nil { if err := ct.g.DeleteView(ct.Views.Chart.Name()); err != nil {
return err return err
} }
ct.Views.Chart.SetBacking(nil) ct.Views.Chart.SetBacking(nil)
@ -99,25 +91,19 @@ func (ct *Cointop) layout(g *gocui.Gui) error {
} }
topOffset = topOffset + chartHeight topOffset = topOffset + chartHeight
if v, err := g.SetView(ct.Views.TableHeader.Name(), 0, topOffset, ct.maxTableWidth, topOffset+2); err != nil { if err := ct.ui.SetView(ct.Views.TableHeader, 0, topOffset, ct.maxTableWidth, topOffset+2); err != nil {
if err != gocui.ErrUnknownView { ct.Views.TableHeader.SetFrame(false)
return err ct.Views.TableHeader.SetFgColor(ct.colorscheme.gocuiFgColor(ct.Views.TableHeader.Name()))
} ct.Views.TableHeader.SetBgColor(ct.colorscheme.gocuiBgColor(ct.Views.TableHeader.Name()))
ct.Views.TableHeader.SetBacking(v)
ct.Views.TableHeader.Backing().Frame = false
ct.colorscheme.SetViewColor(ct.Views.TableHeader.Backing(), "table_header")
go ct.UpdateTableHeader() go ct.UpdateTableHeader()
} }
topOffset = topOffset + headerHeight topOffset = topOffset + headerHeight
if v, err := g.SetView(ct.Views.Table.Name(), 0, topOffset, ct.maxTableWidth, maxY-statusbarHeight); err != nil { if err := ct.ui.SetView(ct.Views.Table, 0, topOffset, ct.maxTableWidth, maxY-statusbarHeight); err != nil {
if err != gocui.ErrUnknownView { ct.Views.Table.SetFrame(false)
return err ct.Views.Table.SetHighlight(true)
} ct.Views.Table.SetSelFgColor(ct.colorscheme.gocuiFgColor("table_row_active"))
ct.Views.Table.SetBacking(v) ct.Views.Table.SetSelBgColor(ct.colorscheme.gocuiBgColor("table_row_active"))
ct.Views.Table.Backing().Frame = false
ct.Views.Table.Backing().Highlight = true
ct.colorscheme.SetViewActiveColor(ct.Views.Table.Backing(), "table_row_active")
_, found := ct.cache.Get("allCoinsSlugMap") _, found := ct.cache.Get("allCoinsSlugMap")
if found { if found {
ct.cache.Delete("allCoinsSlugMap") ct.cache.Delete("allCoinsSlugMap")
@ -129,80 +115,61 @@ func (ct *Cointop) layout(g *gocui.Gui) error {
} }
if !ct.State.hideStatusbar { if !ct.State.hideStatusbar {
if v, err := g.SetView(ct.Views.Statusbar.Name(), 0, maxY-statusbarHeight-1, ct.maxTableWidth, maxY); err != nil { if err := ct.ui.SetView(ct.Views.Statusbar, 0, maxY-statusbarHeight-1, ct.maxTableWidth, maxY); err != nil {
if err != gocui.ErrUnknownView { ct.Views.Statusbar.SetFrame(false)
return err ct.Views.Statusbar.SetFgColor(ct.colorscheme.gocuiFgColor(ct.Views.Statusbar.Name()))
} ct.Views.Statusbar.SetBgColor(ct.colorscheme.gocuiBgColor(ct.Views.Statusbar.Name()))
ct.Views.Statusbar.SetBacking(v)
ct.Views.Statusbar.Backing().Frame = false
ct.colorscheme.SetViewColor(ct.Views.Statusbar.Backing(), "statusbar")
go ct.UpdateStatusbar("") go ct.UpdateStatusbar("")
} }
} else { } else {
if ct.Views.Statusbar.Backing() != nil { if ct.Views.Statusbar.Backing() != nil {
if err := g.DeleteView(ct.Views.Statusbar.Name()); err != nil { if err := ct.g.DeleteView(ct.Views.Statusbar.Name()); err != nil {
return err return err
} }
ct.Views.Statusbar.SetBacking(nil) ct.Views.Statusbar.SetBacking(nil)
} }
} }
if v, err := g.SetView(ct.Views.SearchField.Name(), 0, maxY-2, ct.maxTableWidth, maxY); err != nil { if err := ct.ui.SetView(ct.Views.SearchField, 0, maxY-2, ct.maxTableWidth, maxY); err != nil {
if err != gocui.ErrUnknownView { ct.Views.SearchField.SetEditable(true)
return err ct.Views.SearchField.SetWrap(true)
} ct.Views.SearchField.SetFrame(false)
ct.Views.SearchField.SetBacking(v) ct.Views.SearchField.SetFgColor(ct.colorscheme.gocuiFgColor("searchbar"))
ct.Views.SearchField.Backing().Editable = true ct.Views.SearchField.SetBgColor(ct.colorscheme.gocuiBgColor("searchbar"))
ct.Views.SearchField.Backing().Wrap = true
ct.Views.SearchField.Backing().Frame = false
ct.colorscheme.SetViewColor(ct.Views.SearchField.Backing(), "searchbar")
} }
if v, err := g.SetView(ct.Views.Help.Name(), 1, 1, ct.maxTableWidth-1, maxY-1); err != nil { if err := ct.ui.SetView(ct.Views.Help, 1, 1, ct.maxTableWidth-1, maxY-1); err != nil {
if err != gocui.ErrUnknownView { ct.Views.Help.SetFrame(false)
return err ct.Views.Help.SetFgColor(ct.colorscheme.gocuiFgColor("menu"))
} ct.Views.Help.SetBgColor(ct.colorscheme.gocuiBgColor("menu"))
ct.Views.Help.SetBacking(v)
ct.Views.Help.Backing().Frame = false
ct.colorscheme.SetViewColor(ct.Views.Help.Backing(), "menu")
} }
if v, err := g.SetView(ct.Views.PortfolioUpdateMenu.Name(), 1, 1, ct.maxTableWidth-1, maxY-1); err != nil { if err := ct.ui.SetView(ct.Views.PortfolioUpdateMenu, 1, 1, ct.maxTableWidth-1, maxY-1); err != nil {
if err != gocui.ErrUnknownView { ct.Views.PortfolioUpdateMenu.SetFrame(false)
return err ct.Views.PortfolioUpdateMenu.SetFgColor(ct.colorscheme.gocuiFgColor("menu"))
} ct.Views.PortfolioUpdateMenu.SetBgColor(ct.colorscheme.gocuiBgColor("menu"))
ct.Views.PortfolioUpdateMenu.SetBacking(v)
ct.Views.PortfolioUpdateMenu.Backing().Frame = false
ct.colorscheme.SetViewColor(ct.Views.PortfolioUpdateMenu.Backing(), "menu")
} }
if v, err := g.SetView(ct.Views.Input.Name(), 3, 6, 30, 8); err != nil { if err := ct.ui.SetView(ct.Views.Input, 3, 6, 30, 8); err != nil {
if err != gocui.ErrUnknownView { ct.Views.Input.SetFrame(true)
return err ct.Views.Input.SetEditable(true)
} ct.Views.Input.SetWrap(true)
ct.Views.Input.SetBacking(v) ct.Views.Input.SetFgColor(ct.colorscheme.gocuiFgColor("menu"))
ct.Views.Input.Backing().Frame = true ct.Views.Input.SetBgColor(ct.colorscheme.gocuiBgColor("menu"))
ct.Views.Input.Backing().Editable = true
ct.Views.Input.Backing().Wrap = true
ct.colorscheme.SetViewColor(ct.Views.Input.Backing(), "menu")
} }
if v, err := g.SetView(ct.Views.ConvertMenu.Name(), 1, 1, ct.maxTableWidth-1, maxY-1); err != nil { if err := ct.ui.SetView(ct.Views.ConvertMenu, 1, 1, ct.maxTableWidth-1, maxY-1); err != nil {
if err != gocui.ErrUnknownView { ct.Views.ConvertMenu.SetFrame(false)
return err ct.Views.ConvertMenu.SetFgColor(ct.colorscheme.gocuiFgColor("menu"))
} ct.Views.ConvertMenu.SetBgColor(ct.colorscheme.gocuiBgColor("menu"))
ct.Views.ConvertMenu.SetBacking(v)
ct.Views.ConvertMenu.Backing().Frame = false
ct.colorscheme.SetViewColor(ct.Views.ConvertMenu.Backing(), "menu")
// run only once on init. // run only once on init.
// this bit of code should be at the bottom // this bit of code should be at the bottom
ct.g = g ct.ui.SetViewOnBottom(ct.Views.SearchField) // hide
g.SetViewOnBottom(ct.Views.SearchField.Name()) // hide ct.ui.SetViewOnBottom(ct.Views.Help) // hide
g.SetViewOnBottom(ct.Views.Help.Name()) // hide ct.ui.SetViewOnBottom(ct.Views.ConvertMenu) // hide
g.SetViewOnBottom(ct.Views.ConvertMenu.Name()) // hide ct.ui.SetViewOnBottom(ct.Views.PortfolioUpdateMenu) // hide
g.SetViewOnBottom(ct.Views.PortfolioUpdateMenu.Name()) // hide ct.ui.SetViewOnBottom(ct.Views.Input) // hide
g.SetViewOnBottom(ct.Views.Input.Name()) // hide
ct.SetActiveView(ct.Views.Table.Name()) ct.SetActiveView(ct.Views.Table.Name())
ct.intervalFetchData() ct.intervalFetchData()
} }

@ -4,7 +4,7 @@ import (
"sync" "sync"
"time" "time"
types "github.com/miguelmota/cointop/cointop/common/api/types" types "github.com/miguelmota/cointop/pkg/api/types"
) )
var coinslock sync.Mutex var coinslock sync.Mutex

@ -5,29 +5,25 @@ import (
"math" "math"
"time" "time"
types "github.com/miguelmota/cointop/cointop/common/api/types" types "github.com/miguelmota/cointop/pkg/api/types"
"github.com/miguelmota/cointop/cointop/common/color" "github.com/miguelmota/cointop/pkg/color"
"github.com/miguelmota/cointop/cointop/common/humanize" "github.com/miguelmota/cointop/pkg/humanize"
"github.com/miguelmota/cointop/cointop/common/pad" "github.com/miguelmota/cointop/pkg/pad"
"github.com/miguelmota/cointop/pkg/ui"
) )
// MarketbarView is structure for marketbar view // MarketbarView is structure for marketbar view
type MarketbarView struct { type MarketbarView = ui.View
*View
}
// NewMarketbarView returns a new marketbar view // NewMarketbarView returns a new marketbar view
func NewMarketbarView() *MarketbarView { func NewMarketbarView() *MarketbarView {
return &MarketbarView{NewView("marketbar")} var view *MarketbarView = ui.NewView("marketbar")
return view
} }
// UpdateMarketbar updates the market bar view // UpdateMarketbar updates the market bar view
func (ct *Cointop) UpdateMarketbar() error { func (ct *Cointop) UpdateMarketbar() error {
ct.debuglog("updateMarketbar()") ct.debuglog("updateMarketbar()")
if ct.Views.Marketbar.Backing() == nil {
return nil
}
maxX := ct.width() maxX := ct.width()
logo := "cointop" logo := "cointop"
if ct.colorschemeName == "cointop" { if ct.colorschemeName == "cointop" {
@ -147,14 +143,8 @@ func (ct *Cointop) UpdateMarketbar() error {
content = pad.Right(content, maxX, " ") content = pad.Right(content, maxX, " ")
content = ct.colorscheme.Marketbar(content) content = ct.colorscheme.Marketbar(content)
ct.Update(func() error { ct.UpdateUI(func() error {
if ct.Views.Marketbar.Backing() == nil { return ct.Views.Marketbar.Update(content)
return nil
}
ct.Views.Marketbar.Backing().Clear()
fmt.Fprintln(ct.Views.Marketbar.Backing(), content)
return nil
}) })
return nil return nil

@ -41,21 +41,16 @@ func (ct *Cointop) SetPage(page int) int {
// CursorDown moves the cursor one row down // CursorDown moves the cursor one row down
func (ct *Cointop) CursorDown() error { func (ct *Cointop) CursorDown() error {
ct.debuglog("cursorDown()") ct.debuglog("cursorDown()")
if ct.Views.Table.Backing() == nil {
return nil
}
// NOTE: return if already at the bottom // NOTE: return if already at the bottom
if ct.IsLastRow() { if ct.IsLastRow() {
return nil return nil
} }
cx, cy := ct.Views.Table.Backing().Cursor() cx, cy := ct.Views.Table.Cursor()
if err := ct.Views.Table.SetCursor(cx, cy+1); err != nil {
if err := ct.Views.Table.Backing().SetCursor(cx, cy+1); err != nil { ox, oy := ct.Views.Table.Origin()
ox, oy := ct.Views.Table.Backing().Origin()
// set origin scrolls // set origin scrolls
if err := ct.Views.Table.Backing().SetOrigin(ox, oy+1); err != nil { if err := ct.Views.Table.SetOrigin(ox, oy+1); err != nil {
return err return err
} }
} }
@ -66,21 +61,17 @@ func (ct *Cointop) CursorDown() error {
// CursorUp moves the cursor one row up // CursorUp moves the cursor one row up
func (ct *Cointop) CursorUp() error { func (ct *Cointop) CursorUp() error {
ct.debuglog("cursorUp()") ct.debuglog("cursorUp()")
if ct.Views.Table.Backing() == nil {
return nil
}
// NOTE: return if already at the top // NOTE: return if already at the top
if ct.IsFirstRow() { if ct.IsFirstRow() {
return nil return nil
} }
ox, oy := ct.Views.Table.Backing().Origin() ox, oy := ct.Views.Table.Origin()
cx, cy := ct.Views.Table.Backing().Cursor() cx, cy := ct.Views.Table.Cursor()
if err := ct.Views.Table.Backing().SetCursor(cx, cy-1); err != nil && oy > 0 { if err := ct.Views.Table.SetCursor(cx, cy-1); err != nil && oy > 0 {
// set origin scrolls // set origin scrolls
if err := ct.Views.Table.Backing().SetOrigin(ox, oy-1); err != nil { if err := ct.Views.Table.SetOrigin(ox, oy-1); err != nil {
return err return err
} }
} }
@ -91,18 +82,14 @@ func (ct *Cointop) CursorUp() error {
// PageDown moves the cursor one page down // PageDown moves the cursor one page down
func (ct *Cointop) PageDown() error { func (ct *Cointop) PageDown() error {
ct.debuglog("pageDown()") ct.debuglog("pageDown()")
if ct.Views.Table.Backing() == nil {
return nil
}
// NOTE: return if already at the bottom // NOTE: return if already at the bottom
if ct.IsLastRow() { if ct.IsLastRow() {
return nil return nil
} }
ox, oy := ct.Views.Table.Backing().Origin() // this is prev origin position ox, oy := ct.Views.Table.Origin() // this is prev origin position
cx, _ := ct.Views.Table.Backing().Cursor() // relative cursor position cx := ct.Views.Table.CursorX() // relative cursor position
_, sy := ct.Views.Table.Backing().Size() // rows in visible view sy := ct.Views.Table.Height() // rows in visible view
k := oy + sy k := oy + sy
l := len(ct.State.coins) l := len(ct.State.coins)
// end of table // end of table
@ -115,12 +102,13 @@ func (ct *Cointop) PageDown() error {
sy = l sy = l
} }
if err := ct.Views.Table.Backing().SetOrigin(ox, k); err != nil { if err := ct.Views.Table.SetOrigin(ox, k); err != nil {
return err return err
} }
// move cursor to last line if can't scroll further // move cursor to last line if can't scroll further
if k == oy { if k == oy {
if err := ct.Views.Table.Backing().SetCursor(cx, sy-1); err != nil { if err := ct.Views.Table.SetCursor(cx, sy-1); err != nil {
return err return err
} }
} }
@ -131,28 +119,24 @@ func (ct *Cointop) PageDown() error {
// PageUp moves the cursor one page up // PageUp moves the cursor one page up
func (ct *Cointop) PageUp() error { func (ct *Cointop) PageUp() error {
ct.debuglog("pageUp()") ct.debuglog("pageUp()")
if ct.Views.Table.Backing() == nil {
return nil
}
// NOTE: return if already at the top // NOTE: return if already at the top
if ct.IsFirstRow() { if ct.IsFirstRow() {
return nil return nil
} }
ox, oy := ct.Views.Table.Backing().Origin() ox, oy := ct.Views.Table.Origin()
cx, _ := ct.Views.Table.Backing().Cursor() // relative cursor position cx := ct.Views.Table.CursorX() // relative cursor position
_, sy := ct.Views.Table.Backing().Size() // rows in visible view sy := ct.Views.Table.Height() // rows in visible view
k := oy - sy k := oy - sy
if k < 0 { if k < 0 {
k = 0 k = 0
} }
if err := ct.Views.Table.Backing().SetOrigin(ox, k); err != nil { if err := ct.Views.Table.SetOrigin(ox, k); err != nil {
return err return err
} }
// move cursor to first line if can't scroll further // move cursor to first line if can't scroll further
if k == oy { if k == oy {
if err := ct.Views.Table.Backing().SetCursor(cx, 0); err != nil { if err := ct.Views.Table.SetCursor(cx, 0); err != nil {
return err return err
} }
} }
@ -163,21 +147,17 @@ func (ct *Cointop) PageUp() error {
// NavigateFirstLine moves the cursor to the first row of the table // NavigateFirstLine moves the cursor to the first row of the table
func (ct *Cointop) NavigateFirstLine() error { func (ct *Cointop) NavigateFirstLine() error {
ct.debuglog("navigateFirstLine()") ct.debuglog("navigateFirstLine()")
if ct.Views.Table.Backing() == nil {
return nil
}
// NOTE: return if already at the top // NOTE: return if already at the top
if ct.IsFirstRow() { if ct.IsFirstRow() {
return nil return nil
} }
ox, _ := ct.Views.Table.Backing().Origin() ox := ct.Views.Table.OriginX()
cx, _ := ct.Views.Table.Backing().Cursor() cx := ct.Views.Table.CursorX()
if err := ct.Views.Table.Backing().SetOrigin(ox, 0); err != nil { if err := ct.Views.Table.SetOrigin(ox, 0); err != nil {
return err return err
} }
if err := ct.Views.Table.Backing().SetCursor(cx, 0); err != nil { if err := ct.Views.Table.SetCursor(cx, 0); err != nil {
return err return err
} }
@ -188,24 +168,20 @@ func (ct *Cointop) NavigateFirstLine() error {
// NavigateLastLine moves the cursor to the last row of the table // NavigateLastLine moves the cursor to the last row of the table
func (ct *Cointop) NavigateLastLine() error { func (ct *Cointop) NavigateLastLine() error {
ct.debuglog("navigateLastLine()") ct.debuglog("navigateLastLine()")
if ct.Views.Table.Backing() == nil {
return nil
}
// NOTE: return if already at the bottom // NOTE: return if already at the bottom
if ct.IsLastRow() { if ct.IsLastRow() {
return nil return nil
} }
ox, _ := ct.Views.Table.Backing().Origin() ox := ct.Views.Table.OriginX()
cx, _ := ct.Views.Table.Backing().Cursor() cx := ct.Views.Table.CursorX()
_, sy := ct.Views.Table.Backing().Size() sy := ct.Views.Table.Height()
l := len(ct.State.coins) l := len(ct.State.coins)
k := l - sy k := l - sy
if err := ct.Views.Table.Backing().SetOrigin(ox, k); err != nil { if err := ct.Views.Table.SetOrigin(ox, k); err != nil {
return err return err
} }
if err := ct.Views.Table.Backing().SetCursor(cx, sy-1); err != nil { if err := ct.Views.Table.SetCursor(cx, sy-1); err != nil {
return err return err
} }
@ -216,17 +192,13 @@ func (ct *Cointop) NavigateLastLine() error {
// NavigatePageFirstLine moves the cursor to the visible first row of the table // NavigatePageFirstLine moves the cursor to the visible first row of the table
func (ct *Cointop) NavigatePageFirstLine() error { func (ct *Cointop) NavigatePageFirstLine() error {
ct.debuglog("navigatePageFirstLine()") ct.debuglog("navigatePageFirstLine()")
if ct.Views.Table.Backing() == nil {
return nil
}
// NOTE: return if already at the correct line // NOTE: return if already at the correct line
if ct.IsPageFirstLine() { if ct.IsPageFirstLine() {
return nil return nil
} }
cx, _ := ct.Views.Table.Backing().Cursor() cx := ct.Views.Table.CursorX()
if err := ct.Views.Table.Backing().SetCursor(cx, 0); err != nil { if err := ct.Views.Table.SetCursor(cx, 0); err != nil {
return err return err
} }
ct.RowChanged() ct.RowChanged()
@ -236,18 +208,14 @@ func (ct *Cointop) NavigatePageFirstLine() error {
// NavigatePageMiddleLine moves the cursor to the visible middle row of the table // NavigatePageMiddleLine moves the cursor to the visible middle row of the table
func (ct *Cointop) NavigatePageMiddleLine() error { func (ct *Cointop) NavigatePageMiddleLine() error {
ct.debuglog("navigatePageMiddleLine()") ct.debuglog("navigatePageMiddleLine()")
if ct.Views.Table.Backing() == nil {
return nil
}
// NOTE: return if already at the correct line // NOTE: return if already at the correct line
if ct.IsPageMiddleLine() { if ct.IsPageMiddleLine() {
return nil return nil
} }
cx, _ := ct.Views.Table.Backing().Cursor() cx := ct.Views.Table.CursorX()
_, sy := ct.Views.Table.Backing().Size() sy := ct.Views.Table.Height()
if err := ct.Views.Table.Backing().SetCursor(cx, (sy/2)-1); err != nil { if err := ct.Views.Table.SetCursor(cx, (sy/2)-1); err != nil {
return err return err
} }
ct.RowChanged() ct.RowChanged()
@ -257,18 +225,14 @@ func (ct *Cointop) NavigatePageMiddleLine() error {
// NavigatePageLastLine moves the cursor to the visible last row of the table // NavigatePageLastLine moves the cursor to the visible last row of the table
func (ct *Cointop) navigatePageLastLine() error { func (ct *Cointop) navigatePageLastLine() error {
ct.debuglog("navigatePageLastLine()") ct.debuglog("navigatePageLastLine()")
if ct.Views.Table.Backing() == nil {
return nil
}
// NOTE: return if already at the correct line // NOTE: return if already at the correct line
if ct.IsPageLastLine() { if ct.IsPageLastLine() {
return nil return nil
} }
cx, _ := ct.Views.Table.Backing().Cursor() cx, _ := ct.Views.Table.Cursor()
_, sy := ct.Views.Table.Backing().Size() sy := ct.Views.Table.Height()
if err := ct.Views.Table.Backing().SetCursor(cx, sy-1); err != nil { if err := ct.Views.Table.SetCursor(cx, sy-1); err != nil {
return err return err
} }
ct.RowChanged() ct.RowChanged()
@ -358,28 +322,20 @@ func (ct *Cointop) LastPage() error {
// IsFirstRow returns true if cursor is on first row // IsFirstRow returns true if cursor is on first row
func (ct *Cointop) IsFirstRow() bool { func (ct *Cointop) IsFirstRow() bool {
ct.debuglog("isFirstRow()") ct.debuglog("isFirstRow()")
if ct.Views.Table.Backing() == nil { oy := ct.Views.Table.OriginY()
return false cy := ct.Views.Table.CursorY()
}
_, y := ct.Views.Table.Backing().Origin()
_, cy := ct.Views.Table.Backing().Cursor()
return (cy + y) == 0 return (cy + oy) == 0
} }
// IsLastRow returns true if cursor is on last row // IsLastRow returns true if cursor is on last row
func (ct *Cointop) IsLastRow() bool { func (ct *Cointop) IsLastRow() bool {
ct.debuglog("isLastRow()") ct.debuglog("isLastRow()")
if ct.Views.Table.Backing() == nil { oy := ct.Views.Table.OriginY()
return false cy := ct.Views.Table.CursorY()
}
_, y := ct.Views.Table.Backing().Origin()
_, cy := ct.Views.Table.Backing().Cursor()
numRows := len(ct.State.coins) - 1 numRows := len(ct.State.coins) - 1
return (cy + y + 1) > numRows return (cy + oy + 1) > numRows
} }
// IsFirstPage returns true if cursor is on the first page // IsFirstPage returns true if cursor is on the first page
@ -397,23 +353,16 @@ func (ct *Cointop) IsLastPage() bool {
// IsPageFirstLine returns true if the cursor is on the visible first row // IsPageFirstLine returns true if the cursor is on the visible first row
func (ct *Cointop) IsPageFirstLine() bool { func (ct *Cointop) IsPageFirstLine() bool {
ct.debuglog("isPageFirstLine()") ct.debuglog("isPageFirstLine()")
if ct.Views.Table.Backing() == nil {
return false
}
_, cy := ct.Views.Table.Backing().Cursor() cy := ct.Views.Table.CursorY()
return cy == 0 return cy == 0
} }
// IsPageMiddleLine returns true if the cursor is on the visible middle row // IsPageMiddleLine returns true if the cursor is on the visible middle row
func (ct *Cointop) IsPageMiddleLine() bool { func (ct *Cointop) IsPageMiddleLine() bool {
ct.debuglog("isPageMiddleLine()") ct.debuglog("isPageMiddleLine()")
if ct.Views.Table.Backing() == nil { cy := ct.Views.Table.CursorY()
return false sy := ct.Views.Table.Height()
}
_, cy := ct.Views.Table.Backing().Cursor()
_, sy := ct.Views.Table.Backing().Size()
return (sy/2)-1 == cy return (sy/2)-1 == cy
} }
@ -421,19 +370,16 @@ func (ct *Cointop) IsPageMiddleLine() bool {
func (ct *Cointop) IsPageLastLine() bool { func (ct *Cointop) IsPageLastLine() bool {
ct.debuglog("isPageLastLine()") ct.debuglog("isPageLastLine()")
_, cy := ct.Views.Table.Backing().Cursor() cy := ct.Views.Table.CursorY()
_, sy := ct.Views.Table.Backing().Size() sy := ct.Views.Table.Height()
return cy+1 == sy return cy+1 == sy
} }
// GoToPageRowIndex navigates to the selected row index of the page // GoToPageRowIndex navigates to the selected row index of the page
func (ct *Cointop) GoToPageRowIndex(idx int) error { func (ct *Cointop) GoToPageRowIndex(idx int) error {
ct.debuglog("goToPageRowIndex()") ct.debuglog("goToPageRowIndex()")
if ct.Views.Table.Backing() == nil { cx := ct.Views.Table.CursorX()
return nil if err := ct.Views.Table.SetCursor(cx, idx); err != nil {
}
cx, _ := ct.Views.Table.Backing().Cursor()
if err := ct.Views.Table.Backing().SetCursor(cx, idx); err != nil {
return err return err
} }
ct.RowChanged() ct.RowChanged()
@ -455,23 +401,19 @@ func (ct *Cointop) GoToGlobalIndex(idx int) error {
// HighlightRow highlights the row at index // HighlightRow highlights the row at index
func (ct *Cointop) HighlightRow(idx int) error { func (ct *Cointop) HighlightRow(idx int) error {
ct.debuglog("highlightRow()") ct.debuglog("highlightRow()")
if ct.Views.Table.Backing() == nil { ct.Views.Table.SetOrigin(0, 0)
return nil ct.Views.Table.SetCursor(0, 0)
} ox := ct.Views.Table.OriginX()
cx := ct.Views.Table.CursorX()
ct.Views.Table.Backing().SetOrigin(0, 0) sy := ct.Views.Table.Height()
ct.Views.Table.Backing().SetCursor(0, 0)
ox, _ := ct.Views.Table.Backing().Origin()
cx, _ := ct.Views.Table.Backing().Cursor()
_, sy := ct.Views.Table.Backing().Size()
perpage := ct.TotalPerPage() perpage := ct.TotalPerPage()
p := idx % perpage p := idx % perpage
oy := (p / sy) * sy oy := (p / sy) * sy
cy := p % sy cy := p % sy
if oy > 0 { if oy > 0 {
ct.Views.Table.Backing().SetOrigin(ox, oy) ct.Views.Table.SetOrigin(ox, oy)
} }
ct.Views.Table.Backing().SetCursor(cx, cy) ct.Views.Table.SetCursor(cx, cy)
return nil return nil
} }

@ -11,19 +11,19 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/miguelmota/cointop/cointop/common/asciitable" "github.com/miguelmota/cointop/pkg/asciitable"
"github.com/miguelmota/cointop/cointop/common/humanize" "github.com/miguelmota/cointop/pkg/humanize"
"github.com/miguelmota/cointop/cointop/common/pad" "github.com/miguelmota/cointop/pkg/pad"
"github.com/miguelmota/cointop/pkg/ui"
) )
// PortfolioUpdateMenuView is structure for portfolio update menu view // PortfolioUpdateMenuView is structure for portfolio update menu view
type PortfolioUpdateMenuView struct { type PortfolioUpdateMenuView = ui.View
*View
}
// NewPortfolioUpdateMenuView returns a new portfolio update menu view // NewPortfolioUpdateMenuView returns a new portfolio update menu view
func NewPortfolioUpdateMenuView() *PortfolioUpdateMenuView { func NewPortfolioUpdateMenuView() *PortfolioUpdateMenuView {
return &PortfolioUpdateMenuView{NewView("portfolioupdatemenu")} var view *PortfolioUpdateMenuView = ui.NewView("portfolioupdatemenu")
return view
} }
// TogglePortfolio toggles the portfolio view // TogglePortfolio toggles the portfolio view
@ -71,7 +71,7 @@ func (ct *Cointop) CoinHoldings(coin *Coin) float64 {
} }
// UpdatePortfolioUpdateMenu updates the portfolio update menu view // UpdatePortfolioUpdateMenu updates the portfolio update menu view
func (ct *Cointop) UpdatePortfolioUpdateMenu() { func (ct *Cointop) UpdatePortfolioUpdateMenu() error {
ct.debuglog("updatePortfolioUpdateMenu()") ct.debuglog("updatePortfolioUpdateMenu()")
coin := ct.HighlightedRowCoin() coin := ct.HighlightedRowCoin()
exists := ct.PortfolioEntryExists(coin) exists := ct.PortfolioEntryExists(coin)
@ -92,14 +92,14 @@ func (ct *Cointop) UpdatePortfolioUpdateMenu() {
label := fmt.Sprintf(" Enter holdings for %s %s", ct.colorscheme.MenuLabel(coin.Name), current) label := fmt.Sprintf(" Enter holdings for %s %s", ct.colorscheme.MenuLabel(coin.Name), current)
content := fmt.Sprintf("%s\n%s\n\n%s%s\n\n\n [Enter] %s [ESC] Cancel", header, label, strings.Repeat(" ", 29), coin.Symbol, submitText) content := fmt.Sprintf("%s\n%s\n\n%s%s\n\n\n [Enter] %s [ESC] Cancel", header, label, strings.Repeat(" ", 29), coin.Symbol, submitText)
ct.Update(func() error { ct.UpdateUI(func() error {
ct.Views.PortfolioUpdateMenu.Backing().Clear() ct.Views.PortfolioUpdateMenu.SetFrame(true)
ct.Views.PortfolioUpdateMenu.Backing().Frame = true ct.Views.PortfolioUpdateMenu.Update(content)
fmt.Fprintln(ct.Views.PortfolioUpdateMenu.Backing(), content) ct.Views.Input.Write(value)
fmt.Fprintln(ct.Views.Input.Backing(), value) ct.Views.Input.SetCursor(len(value), 0)
ct.Views.Input.Backing().SetCursor(len(value), 0)
return nil return nil
}) })
return nil
} }
// ShowPortfolioUpdateMenu shows the portfolio update menu // ShowPortfolioUpdateMenu shows the portfolio update menu
@ -122,20 +122,13 @@ func (ct *Cointop) ShowPortfolioUpdateMenu() error {
func (ct *Cointop) HidePortfolioUpdateMenu() error { func (ct *Cointop) HidePortfolioUpdateMenu() error {
ct.debuglog("hidePortfolioUpdateMenu()") ct.debuglog("hidePortfolioUpdateMenu()")
ct.State.portfolioUpdateMenuVisible = false ct.State.portfolioUpdateMenuVisible = false
ct.SetViewOnBottom(ct.Views.PortfolioUpdateMenu.Name()) ct.ui.SetViewOnBottom(ct.Views.PortfolioUpdateMenu)
ct.SetViewOnBottom(ct.Views.Input.Name()) ct.ui.SetViewOnBottom(ct.Views.Input)
ct.SetActiveView(ct.Views.Table.Name()) ct.SetActiveView(ct.Views.Table.Name())
ct.Update(func() error { ct.UpdateUI(func() error {
if ct.Views.PortfolioUpdateMenu.Backing() == nil { ct.Views.PortfolioUpdateMenu.SetFrame(false)
return nil ct.Views.PortfolioUpdateMenu.Update("")
} ct.Views.Input.Update("")
ct.Views.PortfolioUpdateMenu.Backing().Clear()
ct.Views.PortfolioUpdateMenu.Backing().Frame = false
fmt.Fprintln(ct.Views.PortfolioUpdateMenu.Backing(), "")
ct.Views.Input.Backing().Clear()
fmt.Fprintln(ct.Views.Input.Backing(), "")
return nil return nil
}) })
@ -150,7 +143,7 @@ func (ct *Cointop) SetPortfolioHoldings() error {
// read input field // read input field
b := make([]byte, 100) b := make([]byte, 100)
n, err := ct.Views.Input.Backing().Read(b) n, err := ct.Views.Input.Read(b)
if err != nil { if err != nil {
return err return err
} }

@ -3,8 +3,8 @@ package cointop
import ( import (
"fmt" "fmt"
"github.com/miguelmota/cointop/cointop/common/api" "github.com/miguelmota/cointop/pkg/api"
"github.com/miguelmota/cointop/cointop/common/humanize" "github.com/miguelmota/cointop/pkg/humanize"
) )
// PriceConfig is the config options for the price command // PriceConfig is the config options for the price command

@ -22,7 +22,7 @@ func (ct *Cointop) QuitView() error {
ct.State.filterByFavorites = false ct.State.filterByFavorites = false
return ct.UpdateTable() return ct.UpdateTable()
} }
if ct.ActiveViewName() == ct.Views.Table.Name() { if ct.ui.ActiveViewName() == ct.Views.Table.Name() {
return ct.Quit() return ct.Quit()
} }

@ -4,27 +4,26 @@ import (
"regexp" "regexp"
"strings" "strings"
"github.com/miguelmota/cointop/cointop/common/levenshtein" "github.com/miguelmota/cointop/pkg/levenshtein"
"github.com/miguelmota/cointop/pkg/ui"
) )
// SearchFieldView is structure for search field view // SearchFieldView is structure for search field view
type SearchFieldView struct { type SearchFieldView = ui.View
*View
}
// NewSearchFieldView returns a new search field view // NewSearchFieldView returns a new search field view
func NewSearchFieldView() *SearchFieldView { func NewSearchFieldView() *SearchFieldView {
return &SearchFieldView{NewView("searchfield")} var view *SearchFieldView = ui.NewView("searchfield")
return view
} }
// InputView is structure for help view // InputView is structure for help view
type InputView struct { type InputView = ui.View
*View
}
// NewInputView returns a new help view // NewInputView returns a new help view
func NewInputView() *InputView { func NewInputView() *InputView {
return &InputView{NewView("input")} var view *InputView = ui.NewView("input")
return view
} }
// OpenSearch opens the search field // OpenSearch opens the search field
@ -46,9 +45,12 @@ func (ct *Cointop) CancelSearch() error {
// DoSearch triggers the search and sets views // DoSearch triggers the search and sets views
func (ct *Cointop) DoSearch() error { func (ct *Cointop) DoSearch() error {
ct.debuglog("doSearch()") ct.debuglog("doSearch()")
ct.Views.SearchField.Backing().Rewind() ct.Views.SearchField.Rewind()
b := make([]byte, 100) b := make([]byte, 100)
n, err := ct.Views.SearchField.Backing().Read(b) n, err := ct.Views.SearchField.Read(b)
if err != nil {
return err
}
// TODO: do this a better way (SoC) // TODO: do this a better way (SoC)
ct.State.filterByFavorites = false ct.State.filterByFavorites = false

@ -3,30 +3,18 @@ package cointop
import ( import (
"fmt" "fmt"
"github.com/miguelmota/cointop/cointop/common/open" "github.com/miguelmota/cointop/pkg/open"
"github.com/miguelmota/cointop/cointop/common/pad" "github.com/miguelmota/cointop/pkg/pad"
"github.com/miguelmota/cointop/pkg/ui"
) )
// StatusbarView is structure for statusbar view // StatusbarView is structure for statusbar view
type StatusbarView struct { type StatusbarView = ui.View
*View
}
// NewStatusbarView returns a new statusbar view // NewStatusbarView returns a new statusbar view
func NewStatusbarView() *StatusbarView { func NewStatusbarView() *StatusbarView {
return &StatusbarView{NewView("statusbar")} var view *StatusbarView = ui.NewView("statusbar")
} return view
// Update updates the content of the statusbar
func (statusbar *StatusbarView) Update(str string) error {
if statusbar.Backing() == nil {
return nil
}
statusbar.Backing().Clear()
fmt.Fprintln(statusbar.Backing(), str)
return nil
} }
// UpdateStatusbar updates the statusbar view // UpdateStatusbar updates the statusbar view
@ -63,9 +51,8 @@ func (ct *Cointop) UpdateStatusbar(s string) error {
str = str[:end] + v str = str[:end] + v
ct.Update(func() error { ct.UpdateUI(func() error {
ct.Views.Statusbar.Update(str) return ct.Views.Statusbar.Update(str)
return nil
}) })
return nil return nil

@ -8,19 +8,19 @@ import (
"strings" "strings"
"time" "time"
"github.com/miguelmota/cointop/cointop/common/humanize" "github.com/miguelmota/cointop/pkg/humanize"
"github.com/miguelmota/cointop/cointop/common/pad" "github.com/miguelmota/cointop/pkg/pad"
"github.com/miguelmota/cointop/cointop/common/table" "github.com/miguelmota/cointop/pkg/table"
"github.com/miguelmota/cointop/pkg/ui"
) )
// TableView is structure for table view // TableView is structure for table view
type TableView struct { type TableView = ui.View
*View
}
// NewTableView returns a new table view // NewTableView returns a new table view
func NewTableView() *TableView { func NewTableView() *TableView {
return &TableView{NewView("table")} var view *TableView = ui.NewView("table")
return view
} }
// TableColumnOrder returns the default order of the table columns // TableColumnOrder returns the default order of the table columns
@ -193,12 +193,8 @@ func (ct *Cointop) RefreshTable() error {
ct.HighlightRow(currentrow) ct.HighlightRow(currentrow)
} }
ct.Update(func() error { ct.UpdateUI(func() error {
if ct.Views.Table.Backing() == nil { ct.Views.Table.Clear()
return nil
}
ct.Views.Table.Backing().Clear()
ct.table.Format().Fprint(ct.Views.Table.Backing()) ct.table.Format().Fprint(ct.Views.Table.Backing())
go ct.RowChanged() go ct.RowChanged()
go ct.UpdateTableHeader() go ct.UpdateTableHeader()
@ -288,13 +284,9 @@ func (ct *Cointop) GetTableCoinsSlice() []*Coin {
// HighlightedRowIndex returns the index of the highlighted row // HighlightedRowIndex returns the index of the highlighted row
func (ct *Cointop) HighlightedRowIndex() int { func (ct *Cointop) HighlightedRowIndex() int {
ct.debuglog("HighlightedRowIndex()") ct.debuglog("HighlightedRowIndex()")
if ct.Views.Table.Backing() == nil { oy := ct.Views.Table.OriginY()
return 0 cy := ct.Views.Table.CursorY()
} idx := oy + cy
_, y := ct.Views.Table.Backing().Origin()
_, cy := ct.Views.Table.Backing().Cursor()
idx := y + cy
if idx < 0 { if idx < 0 {
idx = 0 idx = 0
} }
@ -317,7 +309,7 @@ func (ct *Cointop) HighlightedRowCoin() *Coin {
// HighlightedPageRowIndex returns the index of page row of the highlighted row // HighlightedPageRowIndex returns the index of page row of the highlighted row
func (ct *Cointop) HighlightedPageRowIndex() int { func (ct *Cointop) HighlightedPageRowIndex() int {
ct.debuglog("HighlightedPageRowIndex()") ct.debuglog("HighlightedPageRowIndex()")
_, cy := ct.Views.Table.Backing().Cursor() cy := ct.Views.Table.CursorY()
idx := cy idx := cy
if idx < 0 { if idx < 0 {
idx = 0 idx = 0

@ -3,20 +3,21 @@ package cointop
import ( import (
"fmt" "fmt"
"strings" "strings"
"github.com/miguelmota/cointop/pkg/ui"
) )
// TableHeaderView is structure for table header view // TableHeaderView is structure for table header view
type TableHeaderView struct { type TableHeaderView = ui.View
*View
}
// NewTableHeaderView returns a new table header view // NewTableHeaderView returns a new table header view
func NewTableHeaderView() *TableHeaderView { func NewTableHeaderView() *TableHeaderView {
return &TableHeaderView{NewView("header")} var view *TableHeaderView = ui.NewView("table_header")
return view
} }
// UpdateTableHeader renders the table header // UpdateTableHeader renders the table header
func (ct *Cointop) UpdateTableHeader() { func (ct *Cointop) UpdateTableHeader() error {
ct.debuglog("UpdateTableHeader()") ct.debuglog("UpdateTableHeader()")
var cols []string var cols []string
@ -89,13 +90,9 @@ func (ct *Cointop) UpdateTableHeader() {
headers = append(headers, str) headers = append(headers, str)
} }
ct.Update(func() error { ct.UpdateUI(func() error {
if ct.Views.TableHeader.Backing() == nil { return ct.Views.TableHeader.Update(strings.Join(headers, ""))
return nil
}
ct.Views.TableHeader.Backing().Clear()
fmt.Fprintln(ct.Views.TableHeader.Backing(), strings.Join(headers, ""))
return nil
}) })
return nil
} }

@ -6,9 +6,9 @@ import (
"github.com/miguelmota/gocui" "github.com/miguelmota/gocui"
) )
// Update takes a callback which updates the view // UpdateUI takes a callback which updates the view
func (ct *Cointop) Update(f func() error) { func (ct *Cointop) UpdateUI(f func() error) {
ct.debuglog(fmt.Sprintf("Update()")) ct.debuglog(fmt.Sprintf("UpdateUI()"))
if ct.g == nil { if ct.g == nil {
return return

@ -5,7 +5,7 @@ import (
"encoding/gob" "encoding/gob"
"strings" "strings"
"github.com/miguelmota/cointop/cointop/common/open" "github.com/miguelmota/cointop/pkg/open"
) )
// OpenLink opens the url in a browser // OpenLink opens the url in a browser

@ -1,83 +0,0 @@
package cointop
import (
"fmt"
"github.com/miguelmota/gocui"
)
// IView is a cointop view
type IView interface {
Backing() *gocui.View
SetBacking(gocuiView *gocui.View)
Name() string
}
// View is a cointop view
type View struct {
backing *gocui.View
name string
}
// NewView creates a new view
func NewView(name string) *View {
return &View{
name: name,
}
}
// Backing returns the backing gocui view
func (view *View) Backing() *gocui.View {
return view.backing
}
// SetBacking sets the backing gocui view
func (view *View) SetBacking(gocuiView *gocui.View) {
view.backing = gocuiView
}
// Height returns the view height
func (view *View) Height() int {
_, h := view.backing.Size()
return h
}
// Width returns the view width
func (view *View) Width() int {
w, _ := view.backing.Size()
return w
}
// Name returns the view's name
func (view *View) Name() string {
return view.name
}
// SetActiveView sets the active view
func (ct *Cointop) SetActiveView(v string) error {
ct.g.SetViewOnTop(v)
ct.g.SetCurrentView(v)
if v == ct.Views.SearchField.Name() {
ct.Views.SearchField.Backing().Clear()
ct.Views.SearchField.Backing().SetCursor(1, 0)
fmt.Fprintf(ct.Views.SearchField.Backing(), "%s", "/")
} else if v == ct.Views.Table.Name() {
ct.g.SetViewOnTop(ct.Views.Statusbar.Name())
}
if v == ct.Views.PortfolioUpdateMenu.Name() {
ct.g.SetViewOnTop(ct.Views.Input.Name())
ct.g.SetCurrentView(ct.Views.Input.Name())
}
return nil
}
// ActiveViewName returns the name of the active view
func (ct *Cointop) ActiveViewName() string {
return ct.g.CurrentView().Name()
}
// SetViewOnBottom sets the view to the bottom layer
func (ct *Cointop) SetViewOnBottom(v string) error {
_, err := ct.g.SetViewOnBottom(v)
return err
}

@ -1,7 +1,7 @@
package main package main
import ( import (
"github.com/miguelmota/cointop/cointop/cmd" cmd "github.com/miguelmota/cointop/cmd/commands"
) )
func main() { func main() {

@ -1,8 +1,8 @@
package api package api
import ( import (
cg "github.com/miguelmota/cointop/cointop/common/api/impl/coingecko" cg "github.com/miguelmota/cointop/pkg/api/impl/coingecko"
cmc "github.com/miguelmota/cointop/cointop/common/api/impl/coinmarketcap" cmc "github.com/miguelmota/cointop/pkg/api/impl/coinmarketcap"
) )
// NewCMC new CoinMarketCap API // NewCMC new CoinMarketCap API

@ -7,10 +7,10 @@ import (
"strings" "strings"
"time" "time"
gecko "github.com/miguelmota/cointop/cointop/api/coingecko/v3" apitypes "github.com/miguelmota/cointop/pkg/api/types"
geckoTypes "github.com/miguelmota/cointop/cointop/api/coingecko/v3/types" util "github.com/miguelmota/cointop/pkg/api/util"
apitypes "github.com/miguelmota/cointop/cointop/common/api/types" gecko "github.com/miguelmota/cointop/pkg/api/vendors/coingecko/v3"
util "github.com/miguelmota/cointop/cointop/common/api/util" geckoTypes "github.com/miguelmota/cointop/pkg/api/vendors/coingecko/v3/types"
) )
// ErrPingFailed is the error for when pinging the API fails // ErrPingFailed is the error for when pinging the API fails

@ -7,8 +7,8 @@ import (
"strings" "strings"
"time" "time"
apitypes "github.com/miguelmota/cointop/cointop/common/api/types" apitypes "github.com/miguelmota/cointop/pkg/api/types"
util "github.com/miguelmota/cointop/cointop/common/api/util" util "github.com/miguelmota/cointop/pkg/api/util"
cmc "github.com/miguelmota/go-coinmarketcap/pro/v1" cmc "github.com/miguelmota/go-coinmarketcap/pro/v1"
cmcv2 "github.com/miguelmota/go-coinmarketcap/v2" cmcv2 "github.com/miguelmota/go-coinmarketcap/v2"
) )

@ -1,7 +1,7 @@
package api package api
import ( import (
types "github.com/miguelmota/cointop/cointop/common/api/types" types "github.com/miguelmota/cointop/pkg/api/types"
) )
// Interface interface // Interface interface

@ -9,8 +9,8 @@ import (
"net/url" "net/url"
"strings" "strings"
"github.com/miguelmota/cointop/cointop/api/coingecko/format" "github.com/miguelmota/cointop/pkg/api/vendors/coingecko/format"
"github.com/miguelmota/cointop/cointop/api/coingecko/v3/types" "github.com/miguelmota/cointop/pkg/api/vendors/coingecko/v3/types"
) )
var baseURL = "https://api.coingecko.com/api/v3" var baseURL = "https://api.coingecko.com/api/v3"

@ -0,0 +1,84 @@
package chartplot
import (
"github.com/miguelmota/cointop/pkg/termui"
)
// ChartPlot ...
type ChartPlot struct {
t *termui.LineChart
}
// NewChartPlot ...
func NewChartPlot() *ChartPlot {
t := termui.NewLineChart()
// NOTE: empty list means don't show x-axis labels
t.DataLabels = []string{""}
t.Border = false
return &ChartPlot{
t: t,
}
}
// Height ...
func (c *ChartPlot) Height() int {
return c.t.Height
}
// SetHeight ...
func (c *ChartPlot) SetHeight(height int) {
c.t.Height = height
}
// Width ...
func (c *ChartPlot) Width() int {
return c.t.Width
}
// SetWidth ...
func (c *ChartPlot) SetWidth(width int) {
c.t.Width = width
}
// SetBorder ...
func (c *ChartPlot) SetBorder(enabled bool) {
c.t.Border = enabled
}
// SetData ...
func (c *ChartPlot) SetData(data []float64) {
// NOTE: edit `termui.LineChart.shortenFloatVal(float64)` to not
// use exponential notation.
c.t.Data = data
}
// GetChartPoints ...
func (c *ChartPlot) GetChartPoints(width int) [][]rune {
termui.Body = termui.NewGrid()
termui.Body.Width = width
termui.Body.AddRows(
termui.NewRow(
termui.NewCol(12, 0, c.t),
),
)
var points [][]rune
// calculate layout
termui.Body.Align()
w := termui.Body.Width
h := c.Height()
row := termui.Body.Rows[0]
b := row.Buffer()
for i := 0; i < h; i = i + 1 {
var rowpoints []rune
for j := 0; j < w; j = j + 1 {
p := b.At(j, i)
rowpoints = append(rowpoints, p.Ch)
}
points = append(points, rowpoints)
}
return points
}

@ -16,7 +16,7 @@ import (
"github.com/creack/pty" "github.com/creack/pty"
"github.com/gliderlabs/ssh" "github.com/gliderlabs/ssh"
"github.com/miguelmota/cointop/cointop/common/pathutil" "github.com/miguelmota/cointop/pkg/pathutil"
gossh "golang.org/x/crypto/ssh" gossh "golang.org/x/crypto/ssh"
) )

@ -6,7 +6,7 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/miguelmota/cointop/cointop/common/table/align" "github.com/miguelmota/cointop/pkg/table/align"
) )
// Table table // Table table

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save