Add: pages, text component
This commit is contained in:
86
api/api.go
Normal file
86
api/api.go
Normal file
@ -0,0 +1,86 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"gitea.unprism.ru/yotia/display-test/api/pages"
|
||||
"gitea.unprism.ru/yotia/display-test/display"
|
||||
"gitea.unprism.ru/yotia/display-test/drawer"
|
||||
)
|
||||
|
||||
const (
|
||||
loopTimeout = 10 * time.Millisecond
|
||||
)
|
||||
|
||||
type displayApi struct {
|
||||
d drawer.Drawer
|
||||
|
||||
curPage pages.Page
|
||||
|
||||
initPage pages.InitPage
|
||||
// statusPage pages.StatusPage
|
||||
|
||||
st status
|
||||
}
|
||||
|
||||
// Work process:
|
||||
// Display has pages that you can switch between. Switch returns page controller.
|
||||
// Every page has values that you can change:
|
||||
// Init page - title, progress bar
|
||||
// Status page - gps, time, rssi, service, ...
|
||||
|
||||
type Display interface {
|
||||
SwitchToInitPage() pages.InitPageContent
|
||||
io.Closer
|
||||
}
|
||||
|
||||
func New() (Display, error) {
|
||||
// Device
|
||||
dev, err := display.New(log.New(log.Writer(), "display", log.LstdFlags), display.MT12232A)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create display: %w", err)
|
||||
}
|
||||
// Drawer
|
||||
d := drawer.New(dev)
|
||||
|
||||
// Pages
|
||||
|
||||
// Init page
|
||||
initPage, err := pages.NewInitPage(d)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("new init page: %w", err)
|
||||
}
|
||||
|
||||
return &displayApi{
|
||||
d: d,
|
||||
initPage: initPage,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *displayApi) switchToPage(p pages.Page) {
|
||||
if d.curPage != nil {
|
||||
d.curPage.Diactivate()
|
||||
}
|
||||
if p != nil {
|
||||
p.Activate()
|
||||
}
|
||||
d.curPage = p
|
||||
}
|
||||
|
||||
func (d *displayApi) SwitchToInitPage() pages.InitPageContent {
|
||||
d.switchToPage(d.initPage)
|
||||
return d.initPage
|
||||
}
|
||||
|
||||
func (d *displayApi) Close() error {
|
||||
// !!! TMP DEBUG BAD CODE
|
||||
d.d.Clear()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
// !!!
|
||||
|
||||
d.switchToPage(nil) // To deactivate cur page
|
||||
return d.d.GetDisplay().Close()
|
||||
}
|
77
api/pages/initpage.go
Normal file
77
api/pages/initpage.go
Normal file
@ -0,0 +1,77 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gitea.unprism.ru/yotia/display-test/components"
|
||||
"gitea.unprism.ru/yotia/display-test/drawer"
|
||||
)
|
||||
|
||||
type initPage struct {
|
||||
drawer drawer.Drawer // Drawer with dysplay
|
||||
|
||||
title components.Text
|
||||
bar components.ProgressBar
|
||||
}
|
||||
|
||||
// Only functions that control content of page
|
||||
type InitPageContent interface {
|
||||
SetTitle(title string)
|
||||
GetProgressBar() components.ProgressBar
|
||||
}
|
||||
|
||||
type InitPage interface {
|
||||
Page
|
||||
InitPageContent
|
||||
}
|
||||
|
||||
func NewInitPage(d drawer.Drawer) (InitPage, error) {
|
||||
if err := d.GetDisplay().IsReady(); err != nil {
|
||||
return nil, fmt.Errorf("display is ready: %w", err)
|
||||
}
|
||||
|
||||
title, err := components.NewText(d, 0, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create title: %w", err)
|
||||
}
|
||||
pb, err := components.NewProgressBar(d, 0, drawer.LineH*3, d.W(), drawer.LineH) // Bottom
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create progress bar: %w", err)
|
||||
}
|
||||
return &initPage{
|
||||
drawer: d,
|
||||
title: title,
|
||||
bar: pb,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *initPage) Activate() {
|
||||
// Draw
|
||||
p.drawer.Clear()
|
||||
p.title.Draw()
|
||||
p.bar.Draw()
|
||||
}
|
||||
|
||||
func (p *initPage) Diactivate() {
|
||||
// Do not clear because next page will have to clear whole screen any way
|
||||
}
|
||||
|
||||
func (p *initPage) SetTitle(title string) {
|
||||
p.title.SetPos((p.drawer.W()-len(title)*(drawer.FontCharW+drawer.CharGap))/2, drawer.FontCharH) // Text in center
|
||||
p.title.SetStr(title)
|
||||
}
|
||||
|
||||
func (p *initPage) GetProgressBar() components.ProgressBar {
|
||||
return p.bar
|
||||
}
|
||||
|
||||
func (p *initPage) Close() (outErr error) {
|
||||
// TODO Not the best way...
|
||||
if err := p.title.Close(); err != nil {
|
||||
outErr = fmt.Errorf("title close: %w:", err)
|
||||
}
|
||||
if err := p.bar.Close(); err != nil {
|
||||
outErr = fmt.Errorf("progress bar close: %w:", err)
|
||||
}
|
||||
return
|
||||
}
|
10
api/pages/pages.go
Normal file
10
api/pages/pages.go
Normal file
@ -0,0 +1,10 @@
|
||||
package pages
|
||||
|
||||
import "io"
|
||||
|
||||
type Page interface {
|
||||
Activate()
|
||||
Diactivate()
|
||||
|
||||
io.Closer
|
||||
}
|
62
api/progress/handler.go
Normal file
62
api/progress/handler.go
Normal file
@ -0,0 +1,62 @@
|
||||
package progress
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"gitea.unprism.ru/yotia/display-test/components"
|
||||
)
|
||||
|
||||
type handler struct {
|
||||
bar components.ProgressBar
|
||||
checkpointN int // Number of check points
|
||||
curP int
|
||||
}
|
||||
|
||||
// Handles progress bar update
|
||||
// You set the amount of
|
||||
type Handler interface {
|
||||
Checkpoint() // Increments current progress
|
||||
// SetProgress(n int) // Do not want to make it public because there is no places it is needed yet
|
||||
Finish() // Set progress to end
|
||||
GetBar() components.ProgressBar
|
||||
Reset()
|
||||
|
||||
io.Closer
|
||||
}
|
||||
|
||||
func NewHandler(bar components.ProgressBar, checkpointN int) Handler {
|
||||
return &handler{
|
||||
bar: bar,
|
||||
checkpointN: checkpointN,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) GetBar() components.ProgressBar {
|
||||
return h.bar
|
||||
}
|
||||
|
||||
func (h *handler) Checkpoint() {
|
||||
h.curP = min(h.curP+1, h.checkpointN)
|
||||
h.bar.SetProgress(float64(h.curP) / float64(h.checkpointN))
|
||||
}
|
||||
|
||||
func (h *handler) SetProgress(n int) {
|
||||
h.curP = min(max(n, 0), h.checkpointN)
|
||||
h.bar.SetProgress(float64(h.curP) / float64(h.checkpointN))
|
||||
}
|
||||
|
||||
func (h *handler) Finish() {
|
||||
h.curP = h.checkpointN
|
||||
h.bar.SetProgress(1)
|
||||
}
|
||||
|
||||
func (h *handler) Reset() {
|
||||
h.curP = 0
|
||||
h.bar.SetProgress(0)
|
||||
}
|
||||
|
||||
func (h *handler) Close() error {
|
||||
h.curP = 0
|
||||
h.checkpointN = 0
|
||||
return h.bar.Close()
|
||||
}
|
67
api/status.go
Normal file
67
api/status.go
Normal file
@ -0,0 +1,67 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"gitea.unprism.ru/KRBL/mpu/mpu"
|
||||
"gitea.unprism.ru/KRBL/sim-modem/api/modem/gps"
|
||||
)
|
||||
|
||||
// Some supplement types and constants
|
||||
|
||||
// This struct contains status of the system that will be on the display
|
||||
type status struct {
|
||||
mutex sync.Mutex
|
||||
|
||||
// Status data
|
||||
time time.Time
|
||||
gpsData gps.Data
|
||||
mpuData mpu.Data
|
||||
|
||||
rssi int // Received signal strength indicator (check gitea.unprism.ru/KRBL/sim-modem/api/modem/utils/signal.go)
|
||||
service string // Internet service name, could be: "NO SERVICE", "GSM", "WCDMA", "LTE", "TDS"
|
||||
}
|
||||
|
||||
type StatusUpdater interface {
|
||||
UpdateTime(newTime time.Time)
|
||||
UpdateGps(newData gps.Data)
|
||||
UpdateMpu(newData mpu.Data)
|
||||
UpdateRssi(newData int)
|
||||
UpdateService(newData string)
|
||||
}
|
||||
|
||||
func (st *status) UpdateTime(newTime time.Time) {
|
||||
st.mutex.Lock()
|
||||
defer st.mutex.Unlock()
|
||||
|
||||
st.time = newTime
|
||||
}
|
||||
|
||||
func (st *status) UpdateGps(newData gps.Data) {
|
||||
st.mutex.Lock()
|
||||
defer st.mutex.Unlock()
|
||||
|
||||
st.gpsData = newData
|
||||
}
|
||||
|
||||
func (st *status) UpdateMpu(newData mpu.Data) {
|
||||
st.mutex.Lock()
|
||||
defer st.mutex.Unlock()
|
||||
|
||||
st.mpuData = newData
|
||||
}
|
||||
|
||||
func (st *status) UpdateRssi(newData int) {
|
||||
st.mutex.Lock()
|
||||
defer st.mutex.Unlock()
|
||||
|
||||
st.rssi = newData
|
||||
}
|
||||
|
||||
func (st *status) UpdateService(newData string) {
|
||||
st.mutex.Lock()
|
||||
defer st.mutex.Unlock()
|
||||
|
||||
st.service = newData
|
||||
}
|
Reference in New Issue
Block a user