LauncherGoDev/sysgo/UI/textarea.go
2021-10-11 13:55:54 +08:00

231 lines
4.6 KiB
Go

package UI
import (
"fmt"
"strings"
"github.com/veandco/go-sdl2/sdl"
"github.com/veandco/go-sdl2/ttf"
"github.com/cuu/gogame/color"
"github.com/cuu/gogame/draw"
"github.com/cuu/gogame/font"
"github.com/cuu/gogame/rect"
"github.com/cuu/gogame/surface"
)
type Textarea struct {
Widget
BackgroundColor *color.Color
CanvasHWND *sdl.Surface
MyWords []string
BlitWords []string
FontObj *ttf.Font
LineNumber int
TextLimit int
TextFull bool
TextIndex int
BlitIndex int
}
func NewTextarea() *Textarea {
p := &Textarea{}
p.TextLimit = 63
p.TextFull = false
p.MyWords = make([]string, 0)
p.BlitWords = make([]string, 0)
p.BackgroundColor = &color.Color{228, 228, 228, 255}
return p
}
func (self *Textarea) Init() {
self.FontObj = Fonts["veramono24"]
}
func (self *Textarea) SubTextIndex() {
self.TextIndex -= 1
if self.TextIndex < 0 {
self.TextIndex = 0
}
}
func (self *Textarea) AddTextIndex() {
self.TextIndex += 1
if self.TextIndex > len(self.MyWords) {
self.TextIndex = len(self.MyWords)
}
}
func (self *Textarea) ResetMyWords() {
self.MyWords = nil
self.TextIndex = 0
}
func (self *Textarea) RemoveFromLastText() []string {
if len(self.MyWords) > 0 {
self.SubTextIndex()
if self.TextIndex < len(self.MyWords) {
self.MyWords = append(self.MyWords[:self.TextIndex], self.MyWords[(self.TextIndex+1):]...)
}
}
return self.MyWords
}
func (self *Textarea) AppendText(alphabet string) {
self.AppendAndBlitText(alphabet)
}
func (self *Textarea) AppendAndBlitText(alphabet string) {
if self.TextFull == false {
if self.TextIndex <= len(self.MyWords) {
self.MyWords = append(self.MyWords[:self.TextIndex],
append([]string{alphabet}, self.MyWords[self.TextIndex:]...)...)
self.BlitText()
self.AddTextIndex()
}
} else {
fmt.Printf("is Full %s\n", strings.Join(self.MyWords, ""))
}
}
func (self *Textarea) BuildBlitText() {
blit_rows := make([][]string, 0)
blit_rows = append(blit_rows, []string{})
w := 0
// xmargin := 5
endmargin := 15
linenumber := 0
cursor_row := 0
for i, v := range self.MyWords {
t := font.Render(self.FontObj, v, true, &color.Color{8, 135, 174, 255}, nil)
t_width := surface.GetWidth(t)
w += t_width
blit_rows[linenumber] = append(blit_rows[linenumber], v)
if i == self.TextIndex-1 {
cursor_row = linenumber
}
if w+t_width >= self.Width-endmargin {
w = 0
linenumber += 1
blit_rows = append(blit_rows, []string{})
}
t.Free()
}
if len(blit_rows) == 1 {
self.BlitWords = blit_rows[0]
self.BlitIndex = self.TextIndex
} else if len(blit_rows) == 2 || cursor_row < 2 {
self.BlitWords = append(blit_rows[0], blit_rows[1]...)
self.BlitIndex = self.TextIndex
} else {
self.BlitWords = append(blit_rows[cursor_row-1], blit_rows[cursor_row]...)
self.BlitIndex = self.TextIndex
for i, v := range blit_rows {
if i == cursor_row-1 {
break
}
self.BlitIndex -= len(v)
}
}
}
func (self *Textarea) BlitText() {
//blit every single word into surface and calc the width ,check multi line
self.BuildBlitText()
w := 0
xmargin := 5
endmargin := 15
x := self.PosX + xmargin
y := self.PosY
linenumber := 0
if len(self.MyWords) > self.TextLimit {
self.TextFull = true
} else {
self.TextFull = false
}
for _, v := range self.BlitWords {
t := font.Render(self.FontObj, v, true, &color.Color{8, 135, 174, 255}, nil)
w += surface.GetWidth(t)
if w >= self.Width-endmargin && linenumber == 0 {
linenumber += 1
x = self.PosX + xmargin
y = self.PosY + surface.GetHeight(t)*linenumber
w = 0
}
rect_ := rect.Rect(x, y, 0, 0)
surface.Blit(self.CanvasHWND, t, &rect_, nil)
x += surface.GetWidth(t)
t.Free()
}
}
func (self *Textarea) Cursor() {
w := 0
xmargin := 5
endmargin := 15
x := self.PosX + xmargin
y := self.PosY
linenumber := 0
for _, v := range self.BlitWords[:self.BlitIndex] {
t := font.Render(self.FontObj, v, true, &color.Color{8, 135, 174, 255}, nil)
w += surface.GetWidth(t)
if w >= self.Width-endmargin && linenumber == 0 {
x = self.PosX + xmargin
y = self.PosY + surface.GetHeight(t)
w = 0
linenumber += 1
}
if w >= self.Width-endmargin*3 && linenumber > 0 {
x += surface.GetWidth(t)
break
}
x += surface.GetWidth(t)
t.Free()
}
c_t := font.Render(self.FontObj, "_", true, &color.Color{0, 0, 0, 255}, nil)
rect_ := rect.Rect(x+1, y-2, 0, 0)
surface.Blit(self.CanvasHWND, c_t, &rect_, nil)
c_t.Free()
}
func (self *Textarea) Draw() {
rect_ := rect.Rect(self.PosX, self.PosY, self.Width, self.Height)
draw.AARoundRect(self.CanvasHWND, &rect_, self.BackgroundColor, 4, 0, self.BackgroundColor)
self.BlitText()
self.Cursor()
}