瀏覽代碼

Добавление кода библиотеки

SVI 3 年之前
父節點
當前提交
8c6a3abc65

+ 13 - 4
libtui/v0/alias/alias.go

@@ -1,16 +1,25 @@
 package alias
 
 // PosX -- позиция по X
-type PosX int
+type PosX int16
 
 // PosY -- позиция по Y
-type PosY int
+type PosY int16
 
 // SizeX -- размер по X
-type SizeX int
+type SizeX int16
 
 // SizeY -- размер по Y
-type SizeY int
+type SizeY int16
+
+// Color -- цвет объекта
+type Color int32
+
+// Style -- стиль отображения на экране
+type Style int64
+
+// Lit -- литера для отображения на экране
+type Lit rune
 
 // Фейковый метод для типа покрытия тестами
 func do() error {

+ 30 - 15
libtui/v0/app/app.go

@@ -18,11 +18,18 @@ type App struct {
 }
 
 // NewApp -- возвращает новый объект приложения
-func NewApp() *App {
-	sf := &App{
-		screen: screen.NewScreen(),
+func NewApp() (*App, error) {
+	sf := &App{}
+	var err error
+	sf.scr, err = tcell.NewScreen()
+	if err != nil {
+		return nil, fmt.Errorf("NewApp(): in create tcell.Screen, err=\n\t%w", err)
 	}
-	return sf
+	sf.screen, err = screen.NewScreen(sf)
+	if err != nil {
+		return nil, fmt.Errorf("NewApp(): i create IScreen, err=\n\t%w", err)
+	}
+	return sf, nil
 }
 
 // Screen -- возвращает объект экрана
@@ -39,9 +46,9 @@ func (sf *App) Run() error {
 		return fmt.Errorf("App.Run(): ininit screen, err=\n\t%w", err)
 	}
 	sf.scr.Clear() // Зачистить экран перед началом работы
-	for {          // Главный цикл работы
-		sf.scr.Show() // Обновить экран
-
+	sf.scr.Show()  // Обновить экран
+	sf.scr.EnableMouse()
+	for { // Главный цикл работы
 		ev := sf.scr.PollEvent() // Получить событие
 
 		// Process event
@@ -55,24 +62,32 @@ func (sf *App) Run() error {
 				return nil
 			}
 			if ev.Key() == tcell.KeyCtrlD { // Показать отладочную информацию
-				sf.screen.IsDebug().Set()
+				if sf.screen.WinDebug().IsVisible() { // Переключение состояния показа окна отладки
+					sf.screen.WinDebug().Hide()
+				} else {
+					sf.screen.WinDebug().Show()
+				}
 			}
+		case *tcell.EventMouse: // Мышка подвинулась
+			x, y := ev.Position()
+			sf.screen.SetMousePos(alias.PosX(x), alias.PosY(y))
 		}
-		if sf.screen.IsDebug().Get() {
-			sf.screen.WinDebug().Show()
-		}
+		sf.scr.Clear()
+		sf.screen.WinDebug().Draw()
+		sf.scr.Show() // Обновить экран
 	}
 }
 
 // Включение экрана терминала
 func (sf *App) run_init() error {
 	var err error
-	sf.scr, err = tcell.NewScreen()
-	if err != nil {
-		return fmt.Errorf("App.run_init(): in create tcell.Screen, err=\n\t%w", err)
-	}
 	if err = sf.scr.Init(); err != nil {
 		return fmt.Errorf("App.run_init(): in init tcell.Screen, err=\n\t%w", err)
 	}
 	return nil
 }
+
+// Scr -- возвращает аппаратный экран
+func (sf *App) Scr() tcell.Screen {
+	return sf.scr
+}

+ 53 - 0
libtui/v0/cell/cell.go

@@ -0,0 +1,53 @@
+// package cell -- ячейка для отрисовки на экране
+package cell
+
+import (
+	"p78git.ddns.net/svi/libtui/alias"
+	"p78git.ddns.net/svi/libtui/pos"
+	"p78git.ddns.net/svi/libtui/types"
+)
+
+// Cell -- ячейка для отрисовки на экране
+type Cell struct {
+	pos   types.IPos
+	lit   alias.Lit
+	style alias.Style
+}
+
+// NewCell -- возвращает новую знакоместо экрана
+func NewCell() *Cell {
+	sf := &Cell{
+		pos: pos.NewPos(),
+	}
+	return sf
+}
+
+// Pos -- возвращает позицию ячейки на экране
+func (sf *Cell) Pos() (alias.PosX, alias.PosY) {
+	return sf.pos.Get()
+}
+
+// SetPos -- устанавливает позицию литеры на экране
+func (sf *Cell) SetPos(posX alias.PosX, posY alias.PosY) {
+	sf.pos.Set(posX, posY)
+}
+
+// Lit -- возвращает хранимую литеру
+func (sf *Cell) Lit() alias.Lit {
+	return sf.lit
+}
+
+// SetLit -- устанавливае тлитеру для отображения
+func (sf *Cell) SetLit(lit alias.Lit) {
+	sf.lit = lit
+}
+
+// Style -- возвращает стиль ячейки
+func (sf *Cell) Style() alias.Style {
+	return sf.style
+}
+
+// SetStyle -- устанавливает стиль ячейки
+func (sf *Cell) SetStyle(style alias.Style) {
+	sf.style = style
+}

+ 50 - 0
libtui/v0/color/color.go

@@ -0,0 +1,50 @@
+// package color -- объект цвета
+package color
+
+import (
+	"github.com/gdamore/tcell"
+	"p78git.ddns.net/svi/libtui/alias"
+)
+
+// Color -- объект цвета
+type Color struct {
+	val alias.Color // Фктическое значение цвета
+	r   uint8
+	g   uint8
+	b   uint8
+}
+
+// NewColor -- возвращает новый цвет
+func NewColor() *Color {
+	sf := &Color{}
+	return sf
+}
+
+// Get -- возвращает фактическое значение цвета
+func (sf *Color) Get() alias.Color {
+	return sf.val
+}
+
+// Set -- устанавливаетхранимое значение цвета
+func (sf *Color) Set(r, g, b uint8) {
+	clr := tcell.NewRGBColor(int32(r), int32(g), int32(b))
+	sf.val = alias.Color(clr)
+	sf.r = r
+	sf.g = g
+	sf.b = b
+}
+
+// R -- возвращает красную компоненту
+func (sf *Color) R() uint8 {
+	return sf.r
+}
+
+// G -- возвращает зелёную компоненту
+func (sf *Color) G() uint8 {
+	return sf.g
+}
+
+// B -- возвращает голубую компоненту
+func (sf *Color) B() uint8 {
+	return sf.g
+}

+ 16 - 3
libtui/v0/examples/show_app/show_app.go

@@ -3,9 +3,22 @@
 //	go run ./examples/show_app
 package main
 
-import "p78git.ddns.net/svi/libtui/app"
+import (
+	"log"
+	"os"
+
+	"p78git.ddns.net/svi/libtui/app"
+)
 
 func main() {
-	app := app.NewApp()
-	_ = app.Run()
+	app, err := app.NewApp()
+	if err != nil {
+		log.Printf("main(): in create IApp, err=\n\t%v\n", err)
+		os.Exit(1)
+	}
+	app.Screen().WinDebug().Show()
+	if err = app.Run(); err != nil {
+		log.Printf("main(): in run IApp, err=\n\t%v\n", err)
+		os.Exit(2)
+	}
 }

+ 47 - 12
libtui/v0/screen/screen.go

@@ -2,8 +2,11 @@
 package screen
 
 import (
+	"fmt"
+
+	"github.com/gdamore/tcell"
 	"p78git.ddns.net/svi/libtui/alias"
-	"p78git.ddns.net/svi/libtui/safe_bool"
+	"p78git.ddns.net/svi/libtui/pos"
 	"p78git.ddns.net/svi/libtui/screen/win_debug"
 	"p78git.ddns.net/svi/libtui/size"
 	"p78git.ddns.net/svi/libtui/types"
@@ -11,19 +14,30 @@ import (
 
 // Screen -- объект экрана
 type Screen struct {
+	app      types.IApp
+	scr      tcell.Screen
 	size     types.ISize     // Размер экрана
-	isDebug  types.ISafeBool // Признак показа отладки
-	winDebug types.IWinDebug // Окно отладк
+	winDebug types.IWinDebug // Окно отладки
+	mousePos types.IPos      // Позиция мыши на экране
 }
 
 // NewScreen -- возвращаетновый экран
-func NewScreen() *Screen {
+func NewScreen(app types.IApp) (*Screen, error) {
+	if app == nil {
+		return nil, fmt.Errorf("NewScreen(): IApp==nil")
+	}
 	sf := &Screen{
+		app:      app,
+		scr:      app.Scr(),
 		size:     size.NewSize(),
-		isDebug:  safe_bool.NewSafeBool(),
-		winDebug: win_debug.NewWinDebug(),
+		mousePos: pos.NewPos(),
 	}
-	return sf
+	var err error
+	sf.winDebug, err = win_debug.NewWinDebug(sf)
+	if err != nil {
+		return nil, fmt.Errorf("NewScreen(): in creatre IWinDebug, err=\n\t%w", err)
+	}
+	return sf, nil
 }
 
 // Size -- возвращает размер экрана
@@ -31,11 +45,6 @@ func (sf *Screen) Size() (alias.SizeX, alias.SizeY) {
 	return sf.size.Get()
 }
 
-// IsDebug -- возвращает признак показа отладки
-func (sf *Screen) IsDebug() types.ISafeBool {
-	return sf.isDebug
-}
-
 // WinDebug -- возвращает объект окна отладки экрана
 func (sf *Screen) WinDebug() types.IWinDebug {
 	return sf.winDebug
@@ -45,3 +54,29 @@ func (sf *Screen) WinDebug() types.IWinDebug {
 func (sf *Screen) Resize(x alias.SizeX, y alias.SizeY) {
 	sf.size.Set(x, y)
 }
+
+// SetMousePos -- устанавливает позицию мыши
+func (sf *Screen) SetMousePos(x alias.PosX, y alias.PosY) {
+	sf.mousePos.Set(x, y)
+	if sf.winDebug.IsVisible() { // Установить позицию окна отладки, если оно видно
+		sf.winDebug.SetPos(x, y)
+	}
+}
+
+// App -- возвращает объект приложения
+func (sf *Screen) App() types.IApp {
+	return sf.app
+}
+
+// MousePos -- возвращает позицию мыши
+func (sf *Screen) MousePos() (alias.PosX, alias.PosY) {
+	return sf.mousePos.X().Get(), sf.mousePos.Y().Get()
+}
+
+// Set -- устанавливает ячейку на экран
+func (sf *Screen) Set(cell types.ICell) {
+	x, y := cell.Pos()
+	style := cell.Style()
+	lit := cell.Lit()
+	sf.scr.SetCell(int(x), int(y), tcell.Style(style), rune(lit))
+}

+ 6 - 1
libtui/v0/screen/screen_test.go

@@ -9,8 +9,10 @@ import (
 // Тестер для экрана
 type tester struct {
 	t    *testing.T
+	app  types.IApp
 	scr  *Screen
 	iscr types.IScreen
+	err  error
 }
 
 func TestScreen(t *testing.T) {
@@ -23,7 +25,10 @@ func TestScreen(t *testing.T) {
 // Создание экрана
 func (sf *tester) create() {
 	sf.t.Logf("create")
-	sf.scr = NewScreen()
+	sf.scr, sf.err = NewScreen(sf.app)
+	if sf.err != nil {
+		sf.t.Fatalf("create(): err=\n\t%v", sf.err)
+	}
 	if sf.scr == nil {
 		sf.t.Fatalf("create(): screen=nil")
 	}

+ 72 - 2
libtui/v0/screen/win_debug/win_debug.go

@@ -2,21 +2,40 @@
 package win_debug
 
 import (
+	"fmt"
+
+	"github.com/gdamore/tcell"
+	"p78git.ddns.net/svi/libtui/alias"
+	"p78git.ddns.net/svi/libtui/cell"
 	"p78git.ddns.net/svi/libtui/safe_bool"
 	"p78git.ddns.net/svi/libtui/types"
+	"p78git.ddns.net/svi/libtui/widget"
 )
 
 // WinDebug -- окно отладки для экрана
 type WinDebug struct {
+	*widget.Widget
+	app       types.IApp
+	screen    types.IScreen
 	isVisible types.ISafeBool
 }
 
 // NewWinDebug -- возвращает новое окно отладки для экрана
-func NewWinDebug() *WinDebug {
+func NewWinDebug(screen types.IScreen) (*WinDebug, error) {
+	if screen == nil {
+		return nil, fmt.Errorf("NewWinDebug(): IScreen==nil")
+	}
+	widget, err := widget.NewWidget(screen)
+	if err != nil {
+		return nil, fmt.Errorf("NewWinDebug(): in create IWidget, err=\n\t%w", err)
+	}
 	sf := &WinDebug{
+		Widget:    widget,
+		app:       screen.App(),
+		screen:    screen,
 		isVisible: safe_bool.NewSafeBool(),
 	}
-	return sf
+	return sf, nil
 }
 
 // IsVisible -- возвращает признак видимости окна экрана
@@ -33,3 +52,54 @@ func (sf *WinDebug) Hide() {
 func (sf *WinDebug) Show() {
 	sf.isVisible.Set()
 }
+
+// SetPos -- устанавливает позицию окна отладки
+func (sf *WinDebug) SetPos(x alias.PosX, y alias.PosY) {
+	// Сначала вычислить квадрант экрана
+	sizeX, sizeY := sf.app.Screen().Size()
+	if alias.SizeX(x) >= sizeX/2 { // Кусор в правой половине
+		x -= 30
+	} else {
+		x += 5
+	}
+	if alias.SizeY(y) >= sizeY/2 { // Курсор в нижней половине
+		y -= 5
+	} else {
+		y += 5
+	}
+}
+
+// Draw -- перерисовывает окноотладки по требованию
+func (sf *WinDebug) Draw() {
+	if !sf.isVisible.Get() {
+		return
+	}
+	color := tcell.NewRGBColor(0, 0, 255)
+	style := tcell.StyleDefault
+	style = style.Background(color)
+	posX, posY := sf.Pos()
+	for x := posX; x < 30; x++ {
+		for y := posY; y < 5; y++ {
+			// int(x), int(y), style, []rune(" ")[0]
+			cell := cell.NewCell()
+			cell.SetPos(x, y)
+			cell.SetStyle(alias.Style(style))
+			sf.screen.Set(cell)
+		}
+	}
+	strOut := fmt.Sprintf("WinDebug.Draw(): pos=%v:%v", posX, posY)
+	color1 := tcell.NewRGBColor(200, 200, 200)
+	style1 := tcell.StyleDefault
+	style1 = style1.Foreground(color1).Background(color)
+	sf.drawText(style1, strOut)
+}
+
+func (sf *WinDebug) drawText(style tcell.Style, text string) {
+	posX, posY := sf.Pos()
+	for adr, r := range text {
+		cell := cell.NewCell()
+		cell.SetPos(posX+alias.PosX(adr), posY)
+		cell.SetLit(alias.Lit(r))
+		sf.screen.Set(cell)
+	}
+}

+ 6 - 0
libtui/v0/types/iapp.go

@@ -1,9 +1,15 @@
 package types
 
+import (
+	"github.com/gdamore/tcell"
+)
+
 // IApp -- объект приложения
 type IApp interface {
 	// Screen -- объект экрана
 	Screen() IScreen
 	// Run -- запускает объект приложения в работу
 	Run() error
+	// Scr -- возвращает аппаратный экран
+	Scr() tcell.Screen
 }

+ 19 - 0
libtui/v0/types/icell.go

@@ -0,0 +1,19 @@
+package types
+
+import "p78git.ddns.net/svi/libtui/alias"
+
+// ICell -- ячейка отображения на экране
+type ICell interface {
+	// Pos -- позиция ячейка на экране
+	Pos() (alias.PosX, alias.PosY)
+	// SetPos -- устанавливает позицию литеры на экране
+	SetPos(alias.PosX, alias.PosY)
+	// Style -- стиль ячейки
+	Style() alias.Style
+	// SetStyle -- устанавливает стиль ячейки
+	SetStyle(alias.Style)
+	// Lit -- литера ячейки
+	Lit() alias.Lit
+	// SetLit -- устанавливает литеру для отображения
+	SetLit(alias.Lit)
+}

+ 11 - 0
libtui/v0/types/icolor.go

@@ -0,0 +1,11 @@
+package types
+
+import (
+	"p78git.ddns.net/svi/libtui/alias"
+)
+
+// IColor -- цвет эелемента
+type IColor interface{
+	// Get -- возвращает хранимое значение цвета
+	Get()alias.Color
+}

+ 11 - 3
libtui/v0/types/iscreen.go

@@ -1,6 +1,8 @@
 package types
 
-import "p78git.ddns.net/svi/libtui/alias"
+import (
+	"p78git.ddns.net/svi/libtui/alias"
+)
 
 // IScreen -- экран приложения
 type IScreen interface {
@@ -8,8 +10,14 @@ type IScreen interface {
 	Size() (alias.SizeX, alias.SizeY)
 	// Resize -- изменить размеры экрана
 	Resize(alias.SizeX, alias.SizeY)
-	// IsDebug -- возвращает признак показа окна отладки
-	IsDebug() ISafeBool
 	// WinDebug -- возвращает объект окна отладки экрана
 	WinDebug() IWinDebug
+	// SetMousePos -- устанавливает позицию мыши экрана
+	SetMousePos(alias.PosX, alias.PosY)
+	// MousePos -- возвращаетпозицию мыши
+	MousePos() (alias.PosX, alias.PosY)
+	// App -- возвращает объект приложения
+	App() IApp
+	// Set -- отрисовывает знакоместо на экране
+	Set(ICell)
 }

+ 11 - 0
libtui/v0/types/iwidget.go

@@ -0,0 +1,11 @@
+package types
+
+import "p78git.ddns.net/svi/libtui/alias"
+
+// IWidget -- базовый виджет для отображения
+type IWidget interface {
+	// Resize -- изменяет размер виджета
+	Resize(alias.SizeX, alias.SizeY)
+	// Pos -- возвращает позицию виджета
+	Pos() (alias.PosX, alias.PosY)
+}

+ 7 - 1
libtui/v0/types/iwindebug.go

@@ -1,5 +1,7 @@
 package types
 
+import "p78git.ddns.net/svi/libtui/alias"
+
 // IWinDebug -- окно отладки экрана
 //
 //	Это окно показывается поверх всех окон
@@ -8,6 +10,10 @@ type IWinDebug interface {
 	Show()
 	// Hide -- скрыть окно отладки экрана
 	Hide()
-	// IsVisible -- признак показа окна отладки экрана
+	// SetPos -- устанавливает позицию окнаотладке на экране
+	SetPos(alias.PosX, alias.PosY)
+	// Draw -- перерисовывает окно отладки по требованию
+	Draw()
+	// IsVisible -- признак, что окно отладки показано
 	IsVisible() bool
 }

+ 96 - 0
libtui/v0/widget/widget.go

@@ -0,0 +1,96 @@
+// package widget -- базовый виджет для построения других виджетов
+package widget
+
+import (
+	"fmt"
+
+	"github.com/gdamore/tcell"
+
+	"p78git.ddns.net/svi/libtui/alias"
+	"p78git.ddns.net/svi/libtui/cell"
+	"p78git.ddns.net/svi/libtui/color"
+	"p78git.ddns.net/svi/libtui/pos"
+	"p78git.ddns.net/svi/libtui/safe_bool"
+	"p78git.ddns.net/svi/libtui/size"
+	"p78git.ddns.net/svi/libtui/types"
+)
+
+// Widget -- базовый виджет для построения других виджетов
+type Widget struct {
+	app       types.IApp
+	screen    types.IScreen
+	pos       types.IPos
+	size      types.ISize
+	lstCell   []types.ICell
+	bgColor   types.IColor
+	fgColor   types.IColor
+	isVisible types.ISafeBool
+	style     alias.Style
+	lit       rune
+}
+
+// NewWidget -- возвращает новый виджет
+func NewWidget(screen types.IScreen) (*Widget, error) {
+	if screen == nil {
+		return nil, fmt.Errorf("NewWidget(): IScreen==nil")
+	}
+	sf := &Widget{
+		app:       screen.App(),
+		screen:    screen,
+		pos:       pos.NewPos(),
+		size:      size.NewSize(),
+		lstCell:   make([]types.ICell, 0),
+		bgColor:   color.NewColor(),
+		fgColor:   color.NewColor(),
+		isVisible: safe_bool.NewSafeBool(),
+		style:     0,
+		lit:       []rune(" ")[0],
+	}
+	color := tcell.Color(sf.bgColor.Get())
+	sf.style = alias.Style(tcell.StyleDefault.Background(color))
+	return sf, nil
+}
+
+// Draw -- отрисовывает виджет потребованию
+func (sf *Widget) Draw() {
+	if !sf.isVisible.Get() {
+		return
+	}
+	for _, cell := range sf.lstCell {
+		sf.screen.Set(cell)
+	}
+}
+
+// FgColor -- возвращает цвет переднего фона
+func (sf *Widget) FgColor() types.IColor {
+	return sf.fgColor
+}
+
+// BgColor -- возвращает цвет фона
+func (sf *Widget) BgColor() types.IColor {
+	return sf.bgColor
+}
+
+// Size -- возвращает объект размера виджета
+func (sf *Widget) Size() (alias.SizeX, alias.SizeY) {
+	return sf.size.Get()
+}
+
+// Resize -- изменяет размер виджета
+func (sf *Widget) Resize(sizeX alias.SizeX, sizeY alias.SizeY) {
+	x_, y_ := sf.size.Get()
+	if x_ == sizeX && y_ == sizeY {
+		return
+	}
+	sf.size.Set(sizeX, sizeY)
+	for len(sf.lstCell) < int(sizeX)*int(sizeY) {
+		cell := cell.NewCell()
+		cell.SetStyle(sf.style)
+		sf.lstCell = append(sf.lstCell, cell)
+	}
+}
+
+// Pos -- возвращает размера виджета
+func (sf *Widget) Pos() (alias.PosX, alias.PosY) {
+	return sf.pos.Get()
+}