Explorar el Código

Добавление кода для отрисовка стека элементов

SVI hace 3 años
padre
commit
1d6476c347

+ 3 - 0
libtui/v0/alias/alias.go

@@ -24,6 +24,9 @@ type Lit rune
 // IsVisible -- признак видимости
 type IsVisible bool
 
+// ObjID -- ID объекта
+type ObjID uint32
+
 // Фейковый метод для типа покрытия тестами
 func do() error {
 	return nil

+ 10 - 2
libtui/v0/examples/show_app/main.go

@@ -11,14 +11,22 @@ import (
 )
 
 func main() {
-	app, err := kernel.NewKernel()
+	app, err := kernel.NewKernel(nil)
 	if err != nil {
 		log.Printf("main(): in create IApp, err=\n\t%v\n", err)
 		os.Exit(1)
 	}
+	posBeg:=app.MakePos(5,5)
+	posEnd:=app.MakePos(10,8)
+	color:=app.MakeColor(255,0,0)
+	_,err=app.MakeLine(posBeg, posEnd, color)
+	if err!=nil{
+		log.Printf("main(): in create ILine, err=\n\t%v\n", err)
+		os.Exit(2)
+	}
 	// 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)
+		os.Exit(3)
 	}
 }

+ 7 - 2
libtui/v0/lib/color/color.go

@@ -20,11 +20,16 @@ func NewColor() *Color {
 	return sf
 }
 
-// Get -- возвращает фактическое значение цвета
-func (sf *Color) Get() alias.Color {
+// Color -- возвращает фактическое значение цвета
+func (sf *Color) Color() alias.Color {
 	return sf.val
 }
 
+// Get -- возвращает фактическое значение цвета
+func (sf *Color) Get() (r, g, b uint8) {
+	return sf.r, sf.g, sf.b
+}
+
 // Set -- устанавливаетхранимое значение цвета
 func (sf *Color) Set(r, g, b uint8) {
 	clr := tcell.NewRGBColor(int32(r), int32(g), int32(b))

+ 2 - 2
libtui/v0/lib/color/color_test.go

@@ -28,7 +28,7 @@ func TestColor(t *testing.T) {
 func (sf *tester) set() {
 	sf.t.Logf("set")
 	sf.icol.Set(1, 3, 5)
-	if col := sf.icol.Get(); col != 16843525 {
+	if col := sf.icol.Color(); col != 16843525 {
 		sf.t.Fatalf("create(): color(%v)!=16843525", col)
 	}
 	if r := sf.icol.R(); r != 1 {
@@ -50,7 +50,7 @@ func (sf *tester) create() {
 		sf.t.Fatalf("create(): color==nil")
 	}
 	sf.icol = sf.col
-	if col := sf.icol.Get(); col != 0 {
+	if col := sf.icol.Color(); col != 0 {
 		sf.t.Fatalf("create(): color!=0")
 	}
 	if r := sf.icol.R(); r != 0 {

+ 1 - 31
libtui/v0/lib/cursor/cursor.go

@@ -4,8 +4,6 @@ package cursor
 import (
 	"fmt"
 
-	"github.com/gdamore/tcell"
-
 	"p78git.ddns.net/svi/libtui/alias"
 	"p78git.ddns.net/svi/libtui/lib/line_cell/cell"
 	"p78git.ddns.net/svi/libtui/types"
@@ -39,35 +37,7 @@ func (sf *Cursor) Draw() {
 	sf.screen.SetCell(sf)
 	posX, posY := sf.Pos()
 	strOut := fmt.Sprintf("WinDebug.Draw(): pos=%v:%v", posX, posY)
-	colorFg := tcell.NewRGBColor(200, 200, 200)
-	style1 := tcell.StyleDefault
-	colorBg := tcell.NewRGBColor(0, 0, 255)
-	style1 = style1.Foreground(colorFg).Background(colorBg)
-	sf.drawText(alias.Style(style1), strOut)
-}
-
-func (sf *Cursor) drawText(style alias.Style, text string) {
-	posX0, posY0 := sf.Pos()
-	posX, posY := posX0, posY0
-	// Сначала вычислить квадрант экрана
-	sizeX, sizeY := sf.screen.Size()
-	if alias.SizeX(posX) >= sizeX/2 { // Кусор в правой половине
-		posX -= 30
-	} else {
-		posX += 5
-	}
-	if alias.SizeY(posY) >= sizeY/2 { // Курсор в нижней половине
-		posY -= 5
-	} else {
-		posY += 5
-	}
-	for adr, r := range text {
-		cell := cell.NewCell()
-		cell.SetPos(posX+alias.PosX(adr), posY)
-		cell.SetLit(alias.Lit(r))
-		cell.SetStyle(style)
-		sf.screen.SetCell(cell)
-	}
+	sf.screen.DrawText(posX, posY, strOut)
 }
 
 // SetPos -- устанавливает позицию курсора с подстройкой фона

+ 54 - 5
libtui/v0/lib/kernel/kernel.go

@@ -5,13 +5,20 @@ import (
 	"context"
 	"fmt"
 
+	"p78git.ddns.net/svi/libtui/alias"
+	"p78git.ddns.net/svi/libtui/lib/color"
 	"p78git.ddns.net/svi/libtui/lib/cursor"
+	"p78git.ddns.net/svi/libtui/lib/line"
+	"p78git.ddns.net/svi/libtui/lib/pos"
 	"p78git.ddns.net/svi/libtui/lib/screen"
+	"p78git.ddns.net/svi/libtui/lib/tui_obj"
+	"p78git.ddns.net/svi/libtui/mock/mock_screen"
 	"p78git.ddns.net/svi/libtui/types"
 )
 
 // Kernel -- объектприложения
 type Kernel struct {
+	*tui_obj.TuiObj
 	screen   types.IScreen   // Объект приложения
 	cursor   types.ICursor   // Глобальный курсор
 	ctxBg    context.Context // Неотменяемый контекст ядра
@@ -20,19 +27,33 @@ type Kernel struct {
 }
 
 // NewKernel -- возвращает новый объект приложения
-func NewKernel() (*Kernel, error) {
+// Если params==nil -- будет создан дефолтный
+func NewKernel(params map[string]string) (*Kernel, error) {
+	if params == nil {
+		params = make(map[string]string)
+	}
 	ctxBg := context.Background()
 	ctx, fnCancel := context.WithCancel(ctxBg)
 	sf := &Kernel{
+		TuiObj: tui_obj.NewTuiObj(),
 		ctxBg:    ctxBg,
 		ctx:      ctx,
 		fnCancel: fnCancel,
 	}
 	var err error
-	sf.screen, err = screen.NewScreen(sf)
-	if err != nil {
-		return nil, fmt.Errorf("NewKernel(): i create IScreen, err=\n\t%w", err)
+	mockScreen, isOk := params["mock_screen"]
+	if !(isOk || mockScreen == "true") {
+		sf.screen, err = screen.NewScreen(sf)
+		if err != nil {
+			return nil, fmt.Errorf("NewKernel(): in create IScreen, err=\n\t%w", err)
+		}
+	} else {
+		sf.screen, err = mock_screen.NewMockScreen(sf)
+		if err != nil {
+			return nil, fmt.Errorf("NewKernel(): in create IScreen, err=\n\t%w", err)
+		}
 	}
+
 	sf.cursor, err = cursor.NewCursor(sf)
 	if err != nil {
 		return nil, fmt.Errorf("NewKernel(): in create ICursor, err=\n\t%w", err)
@@ -52,8 +73,8 @@ func (sf *Kernel) Cursor() types.ICursor {
 
 // Run -- запускает объект приложения в работу
 func (sf *Kernel) Run() error {
+	sf.screen.Run()
 	<-sf.ctx.Done()
-	go sf.screen.Run()
 	return nil
 }
 
@@ -66,3 +87,31 @@ func (sf *Kernel) CancelApp() {
 func (sf *Kernel) Ctx() context.Context {
 	return sf.ctx
 }
+
+// MakeLine -- создаёт новую линию
+func (sf *Kernel) MakeLine(beg, end types.IPos, color types.IColor) (types.ILine, error) {
+	line, err := line.NewLine(sf, beg, end, color)
+	if err != nil {
+		return nil, fmt.Errorf("Kernel.MakeLine(); in make ILine, err=\n\t%w", err)
+	}
+	return line, nil
+}
+
+// MakePos -- создаёт новую позицию
+func (sf *Kernel) MakePos(posX alias.PosX, posY alias.PosY) types.IPos {
+	pos := pos.NewPos()
+	pos.Set(posX, posY)
+	return pos
+}
+
+// MakeColor -- создаёт новый цвет
+func (sf *Kernel) MakeColor(r, g, b uint8) types.IColor {
+	color := color.NewColor()
+	color.Set(r, g, b)
+	return color
+}
+
+// Draw -- отрисовывает приложение
+func (sf *Kernel)Draw(){
+	sf.cursor.Draw()
+}

+ 66 - 0
libtui/v0/lib/kernel/lst_drawer/lst_drawer.go

@@ -0,0 +1,66 @@
+// package lst_drawer -- потокобезопасный список отрисовываемых элементов
+package lst_drawer
+
+import (
+	"fmt"
+	"sync"
+
+	"p78git.ddns.net/svi/libtui/alias"
+	"p78git.ddns.net/svi/libtui/types"
+)
+
+// LstDrawer -- потокобезопасный список отрисовываемых элементов
+type LstDrawer struct {
+	dict  map[alias.ObjID]types.IDrawer
+	lstZ  []alias.ObjID // Z-список объектов для отображения (глубина)
+	block sync.RWMutex
+}
+
+// NewLstDrawer -- возвращает новый потокобезопасный список отрисовываемых элементов
+func NewLstDrawer() *LstDrawer {
+	sf := &LstDrawer{
+		dict: make(map[alias.ObjID]types.IDrawer, 0),
+	}
+	return sf
+}
+
+// Add -- добавляет новый отрисовываемый элемент
+func (sf *LstDrawer) Add(dr types.IDrawer) error {
+	sf.block.Lock()
+	defer sf.block.Unlock()
+	_, isOk := sf.dict[dr.Id()]
+	if isOk {
+		return fmt.Errorf("LstDriwer.Add(): DrawerID(%v) already exists", dr.Id())
+	}
+	sf.dict[dr.Id()] = dr
+	sf.lstZ = append(sf.lstZ, dr.Id())
+	return nil
+}
+
+// Delete -- удаляет указанный элемент из списка отображения
+func (sf *LstDrawer) Delete(id alias.ObjID) {
+	_, isOk := sf.dict[id]
+	if !isOk {
+		return
+	}
+	for adr, id_ := range sf.lstZ {
+		if id != id_ {
+			continue
+		}
+		delete(sf.dict, id)
+		lstZ := sf.lstZ[adr:]
+		sf.lstZ = sf.lstZ[:adr]
+		if len(lstZ) > 0 {
+			sf.lstZ = append(sf.lstZ, lstZ[1:]...)
+		}
+		return
+	}
+}
+
+// Draw -- отрисовывает все элементы на экране
+func (sf *LstDrawer) Draw() {
+	for _, id := range sf.lstZ {
+		dr := sf.dict[id]
+		dr.Draw()
+	}
+}

+ 49 - 1
libtui/v0/lib/line/line.go

@@ -1,11 +1,59 @@
 // package line -- графический примитив линия
 package line
 
-import "p78git.ddns.net/svi/libtui/types"
+import (
+	"fmt"
+
+	"p78git.ddns.net/svi/libtui/alias"
+	"p78git.ddns.net/svi/libtui/lib/tui_obj"
+	"p78git.ddns.net/svi/libtui/types"
+)
 
 // Line -- графический примитив линия
 type Line struct {
+	*tui_obj.TuiObj
+	kern   types.IKernel
+	screen types.IScreen
 	posBeg types.IPos   // Начало линии
 	posEnd types.IPos   // Конец линии
 	color  types.IColor // Цвет линии
 }
+
+// NewLine -- возвращает новый объект линии
+func NewLine(kern types.IKernel, posBeg types.IPos, posEnd types.IPos, color types.IColor) (*Line, error) {
+	{ // Предусловия
+		if kern == nil {
+			return nil, fmt.Errorf("NewLine(): IKernel==nil")
+		}
+		if posBeg == nil {
+			return nil, fmt.Errorf("NewLine(): posBeg==nil")
+		}
+		if posEnd == nil {
+			return nil, fmt.Errorf("NewLine(): posEnd==nil")
+		}
+		if color == nil {
+			return nil, fmt.Errorf("NewLine(): color==nil")
+		}
+	}
+
+	sf := &Line{
+		TuiObj: tui_obj.NewTuiObj(),
+		kern:   kern,
+		posBeg: posBeg,
+		posEnd: posEnd,
+		color:  color,
+	}
+	return sf, nil
+}
+
+// Draw -- отрисовывает линию на экране
+func (sf *Line) Draw() {
+	dx := sf.posBeg.X().Get() - sf.posEnd.X().Get()
+	dy := sf.posBeg.Y().Get() - sf.posEnd.Y().Get()
+	ky := float32(dx) / float32(dy)
+	lit := []rune(" ")[0]
+	for x := sf.posBeg.X().Get(); x < sf.posEnd.X().Get(); x++ {
+		y := float32(x) * ky
+		sf.screen.Plot(x, alias.PosY(y), alias.Lit(lit), sf.color.Color())
+	}
+}

+ 0 - 77
libtui/v0/lib/line/line_cell/line_cell.go

@@ -1,77 +0,0 @@
-// package line_cell -- строка ячеек
-package line_cell
-
-import (
-	"fmt"
-
-	"github.com/gdamore/tcell"
-
-	"p78git.ddns.net/svi/libtui/alias"
-	"p78git.ddns.net/svi/libtui/lib/line_cell/cell"
-	"p78git.ddns.net/svi/libtui/types"
-)
-
-// LineCell -- строка ячеек
-type LineCell struct {
-	app types.IKernel
-	scr types.IScreen
-	lst []types.ICell
-}
-
-// NewLineCell -- возвращает новую строку ячеек
-func NewLineCell(app types.IKernel) (*LineCell, error) {
-	if app == nil {
-		return nil, fmt.Errorf("NewLineCell(): IApp==nil")
-	}
-	sf := &LineCell{
-		app: app,
-		scr: app.Screen(),
-		lst: make([]types.ICell, 0),
-	}
-	return sf, nil
-}
-
-// Draw -- отрисовывает линию ячеек
-func (sf *LineCell) Draw() {
-	// for adr, _ := range sf.lst {
-	// fmt.Printf("LineCell.Draw(): %v\n", adr)
-	// sf.scr.SetCell(cell)
-	cell := cell.NewCell()
-	cell.SetLit(alias.Lit([]rune("=")[0]))
-	st0 := tcell.StyleDefault
-	st0 = st0.Background(tcell.ColorBlue).Foreground(tcell.ColorYellow)
-	cell.SetStyle(alias.Style(st0))
-	x0, y0 := sf.app.Cursor().Pos()
-	scr := sf.app.Screen()
-	for x := x0; x < x0+20; x++ {
-		for y := y0; y < y0+5; y++ {
-			cell.SetPos(x, y)
-			scr.SetCell(cell)
-		}
-	}
-	// }
-}
-
-// GetCell -- возвращает ячейку по смещению
-func (sf *LineCell) GetCell(adr int) (types.ICell, error) {
-	if adr >= len(sf.lst) {
-		return nil, fmt.Errorf("LineCell.GetCell(): adr(%v)>=lenLine(%v)", adr, len(sf.lst))
-	}
-	return sf.lst[adr], nil
-}
-
-// AddCell -- добавляет ячейку в линию
-func (sf *LineCell) AddCell(cell types.ICell) error {
-	if cell == nil {
-		return fmt.Errorf("LineCell.AddCell(): ICell==nil")
-	}
-	sf.lst = append(sf.lst, cell)
-	return nil
-}
-
-// SetPos -- устанавливает новую позицию линии
-func (sf *LineCell) SetPos(posX alias.PosX, posY alias.PosY) {
-	for adr, cell := range sf.lst {
-		cell.SetPos(posX+alias.PosX(adr), posY)
-	}
-}

+ 0 - 92
libtui/v0/lib/line/screen/win_debug/win_debug.go

@@ -1,92 +0,0 @@
-// package win_debug -- окно отладки для экрана
-package win_debug
-
-import (
-	"fmt"
-
-	"github.com/gdamore/tcell"
-
-	"p78git.ddns.net/svi/libtui/alias"
-	"p78git.ddns.net/svi/libtui/lib/line_cell/cell"
-	"p78git.ddns.net/svi/libtui/types"
-	"p78git.ddns.net/svi/libtui/lib/widget"
-)
-
-// WinDebug -- окно отладки для экрана
-type WinDebug struct {
-	*widget.Widget
-	app    types.IKernel
-	screen types.IScreen
-}
-
-// NewWinDebug -- возвращает новое окно отладки для экрана
-func NewWinDebug(app types.IKernel) (*WinDebug, error) {
-	if app == nil {
-		return nil, fmt.Errorf("NewWinDebug(): IApp==nil")
-	}
-	widget, err := widget.NewWidget(app)
-	if err != nil {
-		return nil, fmt.Errorf("NewWinDebug(): in create IWidget, err=\n\t%w", err)
-	}
-	sf := &WinDebug{
-		Widget: widget,
-		app:    app,
-		screen: app.Screen(),
-	}
-	return sf, nil
-}
-
-// Hide -- скрыть окно отладки экрана
-func (sf *WinDebug) Hide() {
-	sf.Widget.Hide()
-}
-
-// Show -- показать окно отладки экрана
-func (sf *WinDebug) Show() {
-	sf.Widget.Show()
-}
-
-// 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
-	}
-	sf.Widget.SetPos(x, y)
-}
-
-// Draw -- перерисовывает окноотладки по требованию
-func (sf *WinDebug) Draw() {
-	if !sf.Widget.IsVisible() {
-		return
-	}
-	sf.Widget.Draw()
-
-	posX, posY := sf.app.Cursor().Pos()
-	strOut := fmt.Sprintf("WinDebug.Draw(): pos=%v:%v", posX, posY)
-	colorFg := tcell.NewRGBColor(200, 200, 200)
-	style1 := tcell.StyleDefault
-	colorBg := tcell.NewRGBColor(0, 0, 255)
-	style1 = style1.Foreground(colorFg).Background(colorBg)
-	sf.drawText(alias.Style(style1), strOut)
-
-}
-
-func (sf *WinDebug) drawText(style alias.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))
-		cell.SetStyle(style)
-		sf.screen.SetCell(cell)
-	}
-}

+ 45 - 8
libtui/v0/lib/screen/screen.go

@@ -3,12 +3,14 @@ package screen
 
 import (
 	"fmt"
+	"log"
 
 	"github.com/gdamore/tcell"
 
 	"p78git.ddns.net/svi/libtui/alias"
 	"p78git.ddns.net/svi/libtui/lib/line_cell/cell"
 	"p78git.ddns.net/svi/libtui/lib/pos"
+	"p78git.ddns.net/svi/libtui/lib/tui_obj"
 
 	// "p78git.ddns.net/svi/libtui/screen/win_debug"
 	"p78git.ddns.net/svi/libtui/lib/size"
@@ -17,7 +19,8 @@ import (
 
 // Screen -- объект экрана
 type Screen struct {
-	app      types.IKernel
+	*tui_obj.TuiObj
+	kern     types.IKernel
 	scr      tcell.Screen // Библиотечный экран
 	size     types.ISize  // Размер экрана
 	posShift types.IPos   // Смещение начала координат
@@ -33,7 +36,7 @@ func NewScreen(app types.IKernel) (*Screen, error) {
 		return nil, fmt.Errorf("NewScreen(): in create tcell.Screen, err=\n\t%w", err)
 	}
 	sf := &Screen{
-		app:      app,
+		kern:     app,
 		scr:      scr,
 		size:     size.NewSize(),
 		posShift: pos.NewPos(),
@@ -42,13 +45,14 @@ func NewScreen(app types.IKernel) (*Screen, error) {
 }
 
 // Run -- запускает экран в работу
-func (sf *Screen) Run() error {
+func (sf *Screen) Run() {
 	defer func() {
 		sf.scr.Fini()
-		sf.app.CancelApp()
+		sf.kern.CancelApp()
 	}()
 	if err := sf.scr.Init(); err != nil {
-		return fmt.Errorf("Screen.Run(): in init tcell.Screen, err=\n\t%w", err)
+		log.Printf("Screen.Run(): in init tcell.Screen, err=\n\t%v\n", err)
+		return
 	}
 	sf.scr.EnableMouse()
 	sf.scr.HideCursor()
@@ -65,7 +69,7 @@ func (sf *Screen) Run() error {
 			sf.size.Set(alias.SizeX(x), alias.SizeY(y))
 		case *tcell.EventKey:
 			if ev.Key() == tcell.KeyCtrlQ { // ev.Key() == tcell.KeyEscape
-				return nil
+				return
 			}
 			if ev.Key() == tcell.KeyCtrlD { // Показать отладочную информацию
 				// if sf.screen.WinDebug().IsVisible() { // Переключение состояния показа окна отладки
@@ -76,7 +80,7 @@ func (sf *Screen) Run() error {
 			}
 		case *tcell.EventMouse: // Мышка подвинулась
 			x, y := ev.Position()
-			sf.app.Cursor().SetPos(alias.PosX(x), alias.PosY(y))
+			sf.kern.Cursor().SetPos(alias.PosX(x), alias.PosY(y))
 		}
 		sf.Draw()
 	}
@@ -125,7 +129,7 @@ func (sf *Screen) SetCell(cell types.ICell) {
 func (sf *Screen) Draw() {
 	sf.scr.Clear()
 	// sf.winDebug.Draw()
-	// sf.cursor.Draw()
+	sf.kern.Draw()
 	sf.scr.Show() // Обновить экран
 
 }
@@ -134,3 +138,36 @@ func (sf *Screen) Draw() {
 func (sf *Screen) Clear() {
 	sf.scr.Clear() // Зачистить экран перед началом работы
 }
+
+// DrawText -- отрисовывает текст по требованию в произвольной точке
+func (sf *Screen) DrawText(posX0 alias.PosX, posY0 alias.PosY, text string) {
+	colorFg := tcell.NewRGBColor(200, 200, 200)
+	style := tcell.StyleDefault
+	colorBg := tcell.NewRGBColor(0, 0, 255)
+	style = style.Foreground(colorFg).Background(colorBg)
+	posX, posY := posX0, posY0
+	// Сначала вычислить квадрант экрана
+	sizeX, sizeY := sf.size.Get()
+	if alias.SizeX(posX) >= sizeX/2 { // Кусор в правой половине
+		posX -= 30
+	} else {
+		posX += 5
+	}
+	if alias.SizeY(posY) >= sizeY/2 { // Курсор в нижней половине
+		posY -= 5
+	} else {
+		posY += 5
+	}
+	for adr, r := range text {
+		cell := cell.NewCell()
+		cell.SetPos(posX+alias.PosX(adr), posY)
+		cell.SetLit(alias.Lit(r))
+		cell.SetStyle(alias.Style(style))
+		sf.SetCell(cell)
+	}
+}
+
+// Plot -- отрисовывает точку на экане
+func (sf *Screen) Plot(posX alias.PosX, posY alias.PosY, lit alias.Lit, color alias.Color) {
+	sf.scr.SetContent(int(posX), int(posY), rune(lit), []rune{}, tcell.Style(color))
+}

+ 1 - 1
libtui/v0/lib/screen/win_debug/win_debug.go

@@ -8,8 +8,8 @@ import (
 
 	"p78git.ddns.net/svi/libtui/alias"
 	"p78git.ddns.net/svi/libtui/lib/line_cell/cell"
-	"p78git.ddns.net/svi/libtui/types"
 	"p78git.ddns.net/svi/libtui/lib/widget"
+	"p78git.ddns.net/svi/libtui/types"
 )
 
 // WinDebug -- окно отладки для экрана

+ 41 - 0
libtui/v0/lib/tui_obj/tui_obj.go

@@ -0,0 +1,41 @@
+// package tui_obj -- базовый объект
+package tui_obj
+
+import (
+	"sync"
+
+	"p78git.ddns.net/svi/libtui/alias"
+)
+
+// TuiObj -- дравер (то что можно нарисовать на экране)
+type TuiObj struct {
+	id alias.ObjID
+}
+
+// NewTuiObj -- возвращает новый дравер
+func NewTuiObj() *TuiObj {
+	sf := &TuiObj{
+		id: getNext(),
+	}
+	return sf
+}
+
+// Id -- возвращает ID дравера
+func (sf *TuiObj) Id() alias.ObjID {
+	return sf.id
+}
+
+var (
+	id    alias.ObjID
+	block sync.Mutex
+)
+
+// Возвращает новый id
+func getNext() alias.ObjID {
+	defer func() {
+		block.Lock()
+		id++
+		block.Unlock()
+	}()
+	return id
+}

+ 7 - 4
libtui/v0/lib/widget/widget.go

@@ -51,8 +51,11 @@ func NewWidget(app types.IKernel) (*Widget, error) {
 	}
 	sf.bgColor.Set(0, 0, 255)
 	sf.fgColor.Set(0, 255, 0)
-	color := tcell.Color(sf.bgColor.Get())
-	sf.style = alias.Style(tcell.StyleDefault.Background(color).Foreground(tcell.Color(sf.fgColor.Get())))
+	r, g, b := sf.bgColor.Get()
+	colorBg := tcell.NewRGBColor(int32(r), int32(g), int32(b))
+	r, g, b = sf.fgColor.Get()
+	colorFg := tcell.NewRGBColor(int32(r), int32(g), int32(b))
+	sf.style = alias.Style(tcell.StyleDefault.Background(colorBg).Foreground(colorFg))
 	sf.Resize(15, 5)
 	sf.isVisible.Set()
 	return sf, nil
@@ -112,8 +115,8 @@ func (sf *Widget) Resize(sizeX alias.SizeX, sizeY alias.SizeY) {
 		for dx := posX; dx < posX+alias.PosX(sizeX); dx++ {
 			cell_ := cell.NewCell()
 			cell_.SetStyle(sf.style)
-			cell_.BgColorSet(sf.bgColor.Get())
-			cell_.FgColorSet(sf.FgColor().Get())
+			cell_.BgColorSet(sf.bgColor.Color())
+			cell_.FgColorSet(sf.FgColor().Color())
 			cell_.SetLit(sf.lit)
 			cell_.SetPos(dx, _y_)
 			if err = line.AddCell(cell_); err != nil {

+ 2 - 0
libtui/v0/mock/mock.go

@@ -0,0 +1,2 @@
+// package mock -- мок-объекты для тестирования приложения
+package mock

+ 60 - 0
libtui/v0/mock/mock_screen/mock_screen.go

@@ -0,0 +1,60 @@
+// package mock_screen -- мок-экран для тестов
+package mock_screen
+
+import (
+	"fmt"
+
+	"p78git.ddns.net/svi/libtui/alias"
+	"p78git.ddns.net/svi/libtui/types"
+)
+
+// MockScreen -- мок-экран для тестов
+type MockScreen struct {
+	kern types.IKernel
+}
+
+// NewMockScreen -- возвращает новый мок-экран для тестов
+func NewMockScreen(kern types.IKernel) (*MockScreen, error) {
+	if kern == nil {
+		return nil, fmt.Errorf("NewMockScreen(): IKernel==nil")
+	}
+	sf := &MockScreen{
+		kern: kern,
+	}
+	return sf, nil
+}
+
+// Clear -- очищает экран
+func (sf *MockScreen) Clear() {}
+
+// Draw -- отрисовывает экран
+func (sf *MockScreen) Draw() {}
+
+// DrawText -- отрисовывает текст по заданной позиции
+func (sf *MockScreen) DrawText(posX alias.PosX, posy alias.PosY, text string) {}
+
+// GetCell -- возвращает ячейку по указанной позиции
+func (sf *MockScreen) GetCell(posX alias.PosX, posY alias.PosY) types.ICell {
+	return nil
+}
+
+// Resize -- изменяет размер экрана
+func (sf *MockScreen) Resize(sizeX alias.SizeX, sizeY alias.SizeY) {}
+
+// Run -- типа запускает экран в работу
+func (sf *MockScreen) Run() {
+
+}
+
+// SetCell -- печатает ячейку на экране
+func (sf *MockScreen) SetCell(cell types.ICell) {
+
+}
+
+// Size -- возвращает собственный размер экрана
+func (sf *MockScreen) Size() (alias.SizeX, alias.SizeY) {
+	return -1, -1
+}
+
+// Plot -- рисует точку на экране
+func (sf *MockScreen) Plot(posX alias.PosX, posY alias.PosY, lit alias.Lit, color alias.Color) {}

+ 11 - 0
libtui/v0/mock/mock_test.go

@@ -0,0 +1,11 @@
+package mock
+
+import (
+	"testing"
+)
+
+/*
+	Тест для мок объектов
+*/
+
+func TestMock(t *testing.T) {}

+ 2 - 2
libtui/v0/tui.go

@@ -1,5 +1,5 @@
-// package libtui -- библиотека терминального графического интерфейса
-package libtui
+// package tui -- библиотека терминального графического интерфейса
+package tui
 
 import (
 	"p78git.ddns.net/svi/libtui/alias"

+ 1 - 1
libtui/v0/tui_test.go

@@ -1,4 +1,4 @@
-package libtui
+package tui
 
 import (
 	"testing"

+ 3 - 1
libtui/v0/types/icolor.go

@@ -6,8 +6,10 @@ import (
 
 // IColor -- цвет эелемента
 type IColor interface {
+	// Color -- возвращает полный цвет
+	Color() alias.Color
 	// Get -- возвращает хранимое значение цвета
-	Get() alias.Color
+	Get() (r, g, b uint8)
 	// Set -- Устанавливает цвет
 	Set(r, g, b uint8)
 	// R -- возвращает красную компоненту

+ 2 - 0
libtui/v0/types/icursor.go

@@ -11,4 +11,6 @@ type ICursor interface {
 	Hide()
 	// IsVisible -- признак видимости курсора
 	IsVisible() alias.IsVisible
+	// Draw -- отрисовывает курсор
+	Draw()
 }

+ 8 - 0
libtui/v0/types/idrawer.go

@@ -0,0 +1,8 @@
+package types
+
+// IDrawer -- дравер (то что можно отрисовать на экране)
+type IDrawer interface {
+	IObj
+	// Draw -- отрисовает дравер на экране
+	Draw()
+}

+ 12 - 1
libtui/v0/types/ikernel.go

@@ -1,9 +1,14 @@
 package types
 
-import "context"
+import (
+	"context"
+
+	"p78git.ddns.net/svi/libtui/alias"
+)
 
 // IKernel -- объект ядра
 type IKernel interface {
+	IDrawer
 	// Screen -- объект экрана
 	Screen() IScreen
 	// Run -- запускает объект ядра в работу
@@ -14,4 +19,10 @@ type IKernel interface {
 	Ctx() context.Context
 	// CancelApp -- отмена контекста ядра
 	CancelApp()
+	// MakePos -- создаёт новую позицию
+	MakePos(alias.PosX, alias.PosY) IPos
+	// MakeColor -- создаёт новый цвет
+	MakeColor(r, g, b uint8) IColor
+	// MakeLine -- создаёт новую линию
+	MakeLine(beg, end IPos, color IColor) (ILine, error)
 }

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

@@ -0,0 +1,6 @@
+package types
+
+// ILine -- графическая линия на экране
+type ILine interface{
+	IDrawer
+}

+ 9 - 0
libtui/v0/types/iobj.go

@@ -0,0 +1,9 @@
+package types
+
+import "p78git.ddns.net/svi/libtui/alias"
+
+// IObj -- базовый объект библиотеки
+type IObj interface {
+	// Id -- возвращает ID объекта
+	Id() alias.ObjID
+}

+ 5 - 1
libtui/v0/types/iscreen.go

@@ -14,10 +14,14 @@ type IScreen interface {
 	SetCell(ICell)
 	// Draw -- отрисовывает себя по  требованию
 	Draw()
+	// DrawText -- отображает текст в заданной позиции
+	DrawText(alias.PosX, alias.PosY, string)
 	// Clear -- очистка экрана
 	Clear()
 	// GetCell -- возвращает ячейку по указанным координатам
 	GetCell(alias.PosX, alias.PosY) ICell
 	// Run -- запускает экран в работу
-	Run() error
+	Run()
+	// Plot -- отрисовывает точку на экране
+	Plot(alias.PosX, alias.PosY, alias.Lit, alias.Color)
 }