Make messeji elements private
This commit is contained in:
parent
fe95e8209c
commit
266e1368de
11 changed files with 485 additions and 102 deletions
3
box.go
3
box.go
|
@ -22,7 +22,8 @@ type Box struct {
|
|||
// NewBox returns a new Box widget.
|
||||
func NewBox() *Box {
|
||||
return &Box{
|
||||
visible: true,
|
||||
background: transparent,
|
||||
visible: true,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
52
button.go
52
button.go
|
@ -3,17 +3,18 @@ package etk
|
|||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"sync"
|
||||
|
||||
"code.rocket9labs.com/tslocum/etk/messeji"
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"golang.org/x/image/font"
|
||||
)
|
||||
|
||||
// Button is a clickable button.
|
||||
type Button struct {
|
||||
*Box
|
||||
|
||||
Label *messeji.TextField
|
||||
|
||||
field *messeji.TextField
|
||||
borderSize int
|
||||
borderTop color.RGBA
|
||||
borderRight color.RGBA
|
||||
borderBottom color.RGBA
|
||||
|
@ -27,19 +28,18 @@ func NewButton(label string, onSelected func() error) *Button {
|
|||
if textColor.A == 0 {
|
||||
textColor = Style.TextColorDark
|
||||
}
|
||||
|
||||
l := messeji.NewTextField(Style.TextFont, Style.TextFontMutex)
|
||||
l.SetText(label)
|
||||
l.SetForegroundColor(textColor)
|
||||
l.SetBackgroundColor(transparent)
|
||||
l.SetHorizontal(messeji.AlignCenter)
|
||||
l.SetVertical(messeji.AlignCenter)
|
||||
l.SetScrollBarVisible(false)
|
||||
f := newText()
|
||||
f.SetText(label)
|
||||
f.SetForegroundColor(textColor)
|
||||
f.SetHorizontal(messeji.AlignCenter)
|
||||
f.SetVertical(messeji.AlignCenter)
|
||||
f.SetScrollBarVisible(false)
|
||||
|
||||
return &Button{
|
||||
Box: NewBox(),
|
||||
Label: l,
|
||||
field: f,
|
||||
onSelected: onSelected,
|
||||
borderSize: Scale(Style.BorderSize),
|
||||
borderTop: Style.BorderColorTop,
|
||||
borderRight: Style.BorderColorRight,
|
||||
borderBottom: Style.BorderColorBottom,
|
||||
|
@ -51,7 +51,7 @@ func NewButton(label string, onSelected func() error) *Button {
|
|||
func (b *Button) SetRect(r image.Rectangle) {
|
||||
b.Box.rect = r
|
||||
|
||||
b.Label.SetRect(r)
|
||||
b.field.SetRect(r)
|
||||
|
||||
for _, w := range b.children {
|
||||
w.SetRect(r)
|
||||
|
@ -69,6 +69,30 @@ func (b *Button) SetBorderColor(top color.RGBA, right color.RGBA, bottom color.R
|
|||
b.borderLeft = left
|
||||
}
|
||||
|
||||
// Text returns the content of the text buffer.
|
||||
func (b *Button) Text() string {
|
||||
b.Lock()
|
||||
defer b.Unlock()
|
||||
|
||||
return b.field.Text()
|
||||
}
|
||||
|
||||
// SetText sets the text in the field.
|
||||
func (b *Button) SetText(text string) {
|
||||
b.Lock()
|
||||
defer b.Unlock()
|
||||
|
||||
b.field.SetText(text)
|
||||
}
|
||||
|
||||
// SetFont sets the font face of the text within the field.
|
||||
func (b *Button) SetFont(face font.Face, mutex *sync.Mutex) {
|
||||
b.Lock()
|
||||
defer b.Unlock()
|
||||
|
||||
b.field.SetFont(face, mutex)
|
||||
}
|
||||
|
||||
// HandleKeyboard is called when a keyboard event occurs.
|
||||
func (b *Button) HandleKeyboard(ebiten.Key, rune) (handled bool, err error) {
|
||||
return false, nil
|
||||
|
@ -99,7 +123,7 @@ func (b *Button) Draw(screen *ebiten.Image) error {
|
|||
screen.SubImage(r).(*ebiten.Image).Fill(Style.ButtonBgColor)
|
||||
|
||||
// Draw label.
|
||||
b.Label.Draw(screen)
|
||||
b.field.Draw(screen)
|
||||
|
||||
// Draw border.
|
||||
const borderSize = 4
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"log"
|
||||
|
||||
"code.rocket9labs.com/tslocum/etk"
|
||||
"code.rocket9labs.com/tslocum/etk/messeji"
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
)
|
||||
|
||||
|
@ -23,8 +22,8 @@ func main() {
|
|||
|
||||
newText := func(size int) *etk.Text {
|
||||
t := etk.NewText(fmt.Sprintf("%dpx Text", size))
|
||||
t.SetHorizontal(messeji.AlignCenter)
|
||||
t.SetVertical(messeji.AlignCenter)
|
||||
t.SetHorizontal(etk.AlignCenter)
|
||||
t.SetVertical(etk.AlignCenter)
|
||||
return t
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,8 @@ func main() {
|
|||
buffer.Write([]byte("\nInput: " + text))
|
||||
return true
|
||||
}
|
||||
input := etk.NewInput(">", "", onselected)
|
||||
input := etk.NewInput("", onselected)
|
||||
input.SetPrefix(">")
|
||||
{
|
||||
inputDemo := etk.NewFlex()
|
||||
inputDemo.SetVertical(true)
|
||||
|
|
25
game.go
25
game.go
|
@ -9,12 +9,27 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"code.rocket9labs.com/tslocum/etk/messeji"
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
||||
"golang.org/x/image/font"
|
||||
"golang.org/x/image/math/fixed"
|
||||
)
|
||||
|
||||
// Alignment specifies how text is aligned within the field.
|
||||
type Alignment int
|
||||
|
||||
const (
|
||||
// AlignStart aligns text at the start of the field.
|
||||
AlignStart Alignment = 0
|
||||
|
||||
// AlignCenter aligns text at the center of the field.
|
||||
AlignCenter Alignment = 1
|
||||
|
||||
// AlignEnd aligns text at the end of the field.
|
||||
AlignEnd Alignment = 2
|
||||
)
|
||||
|
||||
var root Widget
|
||||
|
||||
var drawDebug bool
|
||||
|
@ -386,6 +401,16 @@ func draw(w Widget, screen *ebiten.Image) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func newText() *messeji.TextField {
|
||||
f := messeji.NewTextField(Style.TextFont, Style.TextFontMutex)
|
||||
f.SetForegroundColor(Style.TextColorLight)
|
||||
f.SetBackgroundColor(transparent)
|
||||
f.SetScrollBarColors(Style.ScrollAreaColor, Style.ScrollHandleColor)
|
||||
f.SetScrollBorderSize(Scale(Style.ScrollBorderSize))
|
||||
f.SetScrollBorderColors(Style.ScrollBorderColorTop, Style.ScrollBorderColorRight, Style.ScrollBorderColorBottom, Style.ScrollBorderColorLeft)
|
||||
return f
|
||||
}
|
||||
|
||||
func rectAtOrigin(r image.Rectangle) image.Rectangle {
|
||||
r.Max.X, r.Max.Y = r.Dx(), r.Dy()
|
||||
r.Min.X, r.Min.Y = 0, 0
|
||||
|
|
202
input.go
202
input.go
|
@ -2,56 +2,107 @@ package etk
|
|||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"sync"
|
||||
|
||||
"code.rocket9labs.com/tslocum/etk/messeji"
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"golang.org/x/image/font"
|
||||
)
|
||||
|
||||
// Input is a text input widget. The Input widget is simply a Text widget that
|
||||
// also accepts user input.
|
||||
type Input struct {
|
||||
*Box
|
||||
Field *messeji.InputField
|
||||
Cursor string
|
||||
field *messeji.InputField
|
||||
cursor string
|
||||
focus bool
|
||||
}
|
||||
|
||||
// NewInput returns a new Input widget.
|
||||
func NewInput(prefix string, text string, onSelected func(text string) (handled bool)) *Input {
|
||||
func NewInput(text string, onSelected func(text string) (handled bool)) *Input {
|
||||
textColor := Style.TextColorDark
|
||||
/*if TextColor == nil {
|
||||
textColor = Style.InputColor
|
||||
}*/
|
||||
|
||||
i := messeji.NewInputField(Style.TextFont, Style.TextFontMutex)
|
||||
i.SetPrefix(prefix)
|
||||
i.SetSuffix("")
|
||||
i.SetText(text)
|
||||
i.SetForegroundColor(textColor)
|
||||
i.SetBackgroundColor(Style.InputBgColor)
|
||||
i.SetHandleKeyboard(true)
|
||||
i.SetSelectedFunc(func() (accept bool) {
|
||||
return onSelected(i.Text())
|
||||
f := messeji.NewInputField(Style.TextFont, Style.TextFontMutex)
|
||||
f.SetForegroundColor(textColor)
|
||||
f.SetBackgroundColor(transparent)
|
||||
f.SetScrollBarColors(Style.ScrollAreaColor, Style.ScrollHandleColor)
|
||||
f.SetScrollBorderSize(Scale(Style.ScrollBorderSize))
|
||||
f.SetScrollBorderColors(Style.ScrollBorderColorTop, Style.ScrollBorderColorRight, Style.ScrollBorderColorBottom, Style.ScrollBorderColorLeft)
|
||||
f.SetPrefix("")
|
||||
f.SetSuffix("")
|
||||
f.SetText(text)
|
||||
f.SetHandleKeyboard(true)
|
||||
f.SetSelectedFunc(func() (accept bool) {
|
||||
return onSelected(f.Text())
|
||||
})
|
||||
|
||||
return &Input{
|
||||
i := &Input{
|
||||
Box: NewBox(),
|
||||
Field: i,
|
||||
Cursor: "_",
|
||||
field: f,
|
||||
cursor: "_",
|
||||
}
|
||||
i.SetBackground(Style.InputBgColor)
|
||||
return i
|
||||
}
|
||||
|
||||
// SetRect sets the position and size of the widget.
|
||||
func (i *Input) SetRect(r image.Rectangle) {
|
||||
i.Box.rect = r
|
||||
|
||||
i.Field.SetRect(r)
|
||||
i.field.SetRect(r)
|
||||
|
||||
for _, w := range i.children {
|
||||
w.SetRect(r)
|
||||
}
|
||||
}
|
||||
|
||||
// Foreground return the color of the text within the field.
|
||||
func (i *Input) Foreground() color.RGBA {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
return i.field.ForegroundColor()
|
||||
}
|
||||
|
||||
// SetForegroundColor sets the color of the text within the field.
|
||||
func (i *Input) SetForeground(c color.RGBA) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.field.SetForegroundColor(c)
|
||||
}
|
||||
|
||||
// SetPrefix sets the text shown before the input text.
|
||||
func (i *Input) SetPrefix(prefix string) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.field.SetPrefix(prefix)
|
||||
}
|
||||
|
||||
// SetSuffix sets the text shown after the input text.
|
||||
func (i *Input) SetSuffix(suffix string) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.field.SetSuffix(suffix)
|
||||
}
|
||||
|
||||
// SetCursor sets the cursor appended to the text buffer when focused.
|
||||
func (i *Input) SetCursor(cursor string) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.cursor = cursor
|
||||
if i.focus {
|
||||
i.field.SetSuffix(cursor)
|
||||
}
|
||||
}
|
||||
|
||||
// Focus returns the focus state of the widget.
|
||||
func (i *Input) Focus() bool {
|
||||
return i.focus
|
||||
|
@ -63,25 +114,112 @@ func (i *Input) SetFocus(focus bool) bool {
|
|||
|
||||
var cursor string
|
||||
if focus {
|
||||
cursor = i.Cursor
|
||||
cursor = i.cursor
|
||||
}
|
||||
i.Field.SetSuffix(cursor)
|
||||
i.field.SetSuffix(cursor)
|
||||
return true
|
||||
}
|
||||
|
||||
// Clear clears the textbuffer.
|
||||
func (i *Input) Clear() {
|
||||
i.Field.SetText("")
|
||||
}
|
||||
|
||||
// Write writes to the text buffer.
|
||||
func (i *Input) Write(p []byte) (n int, err error) {
|
||||
return i.Field.Write(p)
|
||||
}
|
||||
|
||||
// Text returns the content of the text buffer.
|
||||
func (i *Input) Text() string {
|
||||
return i.Field.Text()
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
return i.field.Text()
|
||||
}
|
||||
|
||||
// SetText sets the text in the field.
|
||||
func (i *Input) SetText(text string) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.field.SetText(text)
|
||||
}
|
||||
|
||||
// SetScrollBarWidth sets the width of the scroll bar.
|
||||
func (i *Input) SetScrollBarWidth(width int) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.field.SetScrollBarWidth(width)
|
||||
}
|
||||
|
||||
// SetScrollBarColors sets the color of the scroll bar area and handle.
|
||||
func (i *Input) SetScrollBarColors(area color.RGBA, handle color.RGBA) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.field.SetScrollBarColors(Style.ScrollAreaColor, Style.ScrollHandleColor)
|
||||
}
|
||||
|
||||
// SetScrollBarVisible sets whether the scroll bar is visible on the screen.
|
||||
func (i *Input) SetScrollBarVisible(scrollVisible bool) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.field.SetScrollBarVisible(scrollVisible)
|
||||
}
|
||||
|
||||
// SetAutoHideScrollBar sets whether the scroll bar is automatically hidden
|
||||
// when the entire text buffer is visible.
|
||||
func (i *Input) SetAutoHideScrollBar(autoHide bool) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.field.SetAutoHideScrollBar(autoHide)
|
||||
}
|
||||
|
||||
// SetFont sets the font face of the text within the field.
|
||||
func (i *Input) SetFont(face font.Face, mutex *sync.Mutex) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.field.SetFont(face, mutex)
|
||||
}
|
||||
|
||||
// Padding returns the amount of padding around the text within the field.
|
||||
func (i *Input) Padding() int {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
return i.field.Padding()
|
||||
}
|
||||
|
||||
// SetPadding sets the amount of padding around the text within the field.
|
||||
func (i *Input) SetPadding(padding int) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.field.SetPadding(padding)
|
||||
}
|
||||
|
||||
// SetWordWrap sets a flag which, when enabled, causes text to wrap without breaking words.
|
||||
func (i *Input) SetWordWrap(wrap bool) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.field.SetWordWrap(wrap)
|
||||
}
|
||||
|
||||
// SetHorizontal sets the horizontal alignment of the text within the field.
|
||||
func (i *Input) SetHorizontal(h Alignment) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.field.SetHorizontal(messeji.Alignment(h))
|
||||
}
|
||||
|
||||
// SetVertical sets the vertical alignment of the text within the field.
|
||||
func (i *Input) SetVertical(h Alignment) {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
i.field.SetVertical(messeji.Alignment(h))
|
||||
}
|
||||
|
||||
// Write writes to the text buffer.
|
||||
func (i *Input) Write(p []byte) (n int, err error) {
|
||||
return i.field.Write(p)
|
||||
}
|
||||
|
||||
// HandleKeyboard is called when a keyboard event occurs.
|
||||
|
@ -90,16 +228,16 @@ func (i *Input) HandleKeyboard(key ebiten.Key, r rune) (handled bool, err error)
|
|||
return false, nil
|
||||
}
|
||||
|
||||
return i.Field.HandleKeyboardEvent(key, r)
|
||||
return i.field.HandleKeyboardEvent(key, r)
|
||||
}
|
||||
|
||||
// HandleMouse is called when a mouse event occurs.
|
||||
func (i *Input) HandleMouse(cursor image.Point, pressed bool, clicked bool) (handled bool, err error) {
|
||||
return i.Field.HandleMouseEvent(cursor, pressed, clicked)
|
||||
return i.field.HandleMouseEvent(cursor, pressed, clicked)
|
||||
}
|
||||
|
||||
// Draw draws the widget on the screen.
|
||||
func (i *Input) Draw(screen *ebiten.Image) error {
|
||||
i.Field.Draw(screen)
|
||||
i.field.Draw(screen)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -39,8 +39,8 @@ type Keyboard struct {
|
|||
|
||||
op *ebiten.DrawImageOptions
|
||||
|
||||
backgroundColor color.Color
|
||||
lastBackgroundColor color.Color
|
||||
backgroundColor color.RGBA
|
||||
lastBackgroundColor color.RGBA
|
||||
|
||||
shift bool
|
||||
|
||||
|
@ -78,7 +78,7 @@ func NewKeyboard() *Keyboard {
|
|||
normalKeys: KeysQWERTY,
|
||||
backgroundLower: ebiten.NewImage(1, 1),
|
||||
backgroundUpper: ebiten.NewImage(1, 1),
|
||||
backgroundColor: color.Black,
|
||||
backgroundColor: color.RGBA{0, 0, 0, 255},
|
||||
holdTouchID: -1,
|
||||
labelFont: fontFace,
|
||||
backspaceDelay: 500 * time.Millisecond,
|
||||
|
|
|
@ -113,10 +113,10 @@ type TextField struct {
|
|||
lineOffset int
|
||||
|
||||
// textColor is the color of the text within the field.
|
||||
textColor color.Color
|
||||
textColor color.RGBA
|
||||
|
||||
// backgroundColor is the color of the background of the field.
|
||||
backgroundColor color.Color
|
||||
backgroundColor color.RGBA
|
||||
|
||||
// padding is the amount of padding around the text within the field.
|
||||
padding int
|
||||
|
@ -150,6 +150,15 @@ type TextField struct {
|
|||
// scrollHandleColor is the color of the scroll handle.
|
||||
scrollHandleColor color.RGBA
|
||||
|
||||
// scrollBorderSize is the size of the border around the scroll bar handle.
|
||||
scrollBorderSize int
|
||||
|
||||
// Scroll bar handle border colors.
|
||||
scrollBorderTop color.RGBA
|
||||
scrollBorderRight color.RGBA
|
||||
scrollBorderBottom color.RGBA
|
||||
scrollBorderLeft color.RGBA
|
||||
|
||||
// scrollVisible is whether the scroll bar is visible on the screen.
|
||||
scrollVisible bool
|
||||
|
||||
|
@ -272,7 +281,7 @@ func (f *TextField) SetPrefix(text string) {
|
|||
f.modified = true
|
||||
}
|
||||
|
||||
// SetSuffix sets the text shown before the content of the field.
|
||||
// SetSuffix sets the text shown after the content of the field.
|
||||
func (f *TextField) SetSuffix(text string) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
@ -361,8 +370,16 @@ func (f *TextField) SetLineHeight(height int) {
|
|||
f.modified = true
|
||||
}
|
||||
|
||||
// ForegroundColor returns the color of the text within the field.
|
||||
func (f *TextField) ForegroundColor() color.RGBA {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
return f.textColor
|
||||
}
|
||||
|
||||
// SetForegroundColor sets the color of the text within the field.
|
||||
func (f *TextField) SetForegroundColor(c color.Color) {
|
||||
func (f *TextField) SetForegroundColor(c color.RGBA) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
|
@ -371,7 +388,7 @@ func (f *TextField) SetForegroundColor(c color.Color) {
|
|||
}
|
||||
|
||||
// SetBackgroundColor sets the color of the background of the field.
|
||||
func (f *TextField) SetBackgroundColor(c color.Color) {
|
||||
func (f *TextField) SetBackgroundColor(c color.RGBA) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
|
@ -463,6 +480,28 @@ func (f *TextField) SetScrollBarColors(area color.RGBA, handle color.RGBA) {
|
|||
f.redraw = true
|
||||
}
|
||||
|
||||
// SetScrollBorderSize sets the size of the border around the scroll bar handle.
|
||||
func (f *TextField) SetScrollBorderSize(size int) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.scrollBorderSize = size
|
||||
f.redraw = true
|
||||
}
|
||||
|
||||
// SetScrollBorderColor sets the color of the top, right, bottom and left border
|
||||
// of the scroll bar handle.
|
||||
func (f *TextField) SetScrollBorderColors(top color.RGBA, right color.RGBA, bottom color.RGBA, left color.RGBA) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.scrollBorderTop = top
|
||||
f.scrollBorderRight = right
|
||||
f.scrollBorderBottom = bottom
|
||||
f.scrollBorderLeft = left
|
||||
f.redraw = true
|
||||
}
|
||||
|
||||
// SetScrollBarVisible sets whether the scroll bar is visible on the screen.
|
||||
func (f *TextField) SetScrollBarVisible(scrollVisible bool) {
|
||||
f.Lock()
|
||||
|
@ -870,7 +909,11 @@ func (f *TextField) wrapContent(withScrollBar bool) {
|
|||
|
||||
// drawContent draws the text buffer to img.
|
||||
func (f *TextField) drawContent() (overflow bool) {
|
||||
f.img.Fill(f.backgroundColor)
|
||||
if f.backgroundColor.A != 0 {
|
||||
f.img.Fill(f.backgroundColor)
|
||||
} else {
|
||||
f.img.Clear()
|
||||
}
|
||||
fieldWidth := f.r.Dx()
|
||||
fieldHeight := f.r.Dy()
|
||||
if f.showScrollBar() {
|
||||
|
@ -1017,8 +1060,20 @@ func (f *TextField) drawImage() {
|
|||
scrollY += int(float64(h-scrollBarH) * pct)
|
||||
scrollBarRect := image.Rect(scrollX, scrollY, scrollX+f.scrollWidth, scrollY+scrollBarH)
|
||||
|
||||
// Draw scroll area.
|
||||
f.img.SubImage(f.scrollRect).(*ebiten.Image).Fill(f.scrollAreaColor)
|
||||
|
||||
// Draw scroll handle.
|
||||
f.img.SubImage(scrollBarRect).(*ebiten.Image).Fill(f.scrollHandleColor)
|
||||
|
||||
// Draw scroll handle border.
|
||||
if f.scrollBorderSize != 0 {
|
||||
r := scrollBarRect
|
||||
f.img.SubImage(image.Rect(r.Min.X, r.Min.Y, r.Min.X+f.scrollBorderSize, r.Max.Y)).(*ebiten.Image).Fill(f.scrollBorderLeft)
|
||||
f.img.SubImage(image.Rect(r.Min.X, r.Min.Y, r.Max.X, r.Min.Y+f.scrollBorderSize)).(*ebiten.Image).Fill(f.scrollBorderTop)
|
||||
f.img.SubImage(image.Rect(r.Max.X-f.scrollBorderSize, r.Min.Y, r.Max.X, r.Max.Y)).(*ebiten.Image).Fill(f.scrollBorderRight)
|
||||
f.img.SubImage(image.Rect(r.Min.X, r.Max.Y-f.scrollBorderSize, r.Max.X, r.Max.Y)).(*ebiten.Image).Fill(f.scrollBorderBottom)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
12
select.go
12
select.go
|
@ -4,14 +4,12 @@ import (
|
|||
"image"
|
||||
"image/color"
|
||||
|
||||
"code.rocket9labs.com/tslocum/etk/messeji"
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
)
|
||||
|
||||
// Select is a dropdown selection widget.
|
||||
type Select struct {
|
||||
*Box
|
||||
|
||||
label *Text
|
||||
list *List
|
||||
onSelect func(index int) (accept bool)
|
||||
|
@ -26,9 +24,9 @@ func NewSelect(itemHeight int, onSelect func(index int) (accept bool)) *Select {
|
|||
label: NewText(""),
|
||||
onSelect: onSelect,
|
||||
}
|
||||
s.label.SetVertical(messeji.AlignCenter)
|
||||
s.label.SetForegroundColor(Style.ButtonTextColor)
|
||||
s.label.SetBackgroundColor(Style.ButtonBgColor)
|
||||
s.label.SetVertical(AlignCenter)
|
||||
s.label.SetForeground(Style.ButtonTextColor)
|
||||
s.SetBackground(Style.ButtonBgColor)
|
||||
s.list = NewList(itemHeight, s.selectList)
|
||||
s.list.SetBackground(Style.ButtonBgColor)
|
||||
s.list.SetDrawBorder(true)
|
||||
|
@ -109,8 +107,8 @@ func (s *Select) AddOption(label string) {
|
|||
}
|
||||
|
||||
t := NewText(label)
|
||||
t.SetVertical(messeji.AlignCenter)
|
||||
t.SetForegroundColor(Style.ButtonTextColor)
|
||||
t.SetVertical(AlignCenter)
|
||||
t.SetForeground(Style.ButtonTextColor)
|
||||
s.list.AddChildAt(t, 0, len(s.items)-1)
|
||||
}
|
||||
|
||||
|
|
34
style.go
34
style.go
|
@ -29,7 +29,7 @@ func defaultFont() font.Face {
|
|||
return defaultFont
|
||||
}
|
||||
|
||||
// Attributes represents a default attribute configuration.
|
||||
// Attributes represents a default attribute configuration. Integer values will be scaled.
|
||||
type Attributes struct {
|
||||
TextFont font.Face
|
||||
TextFontMutex *sync.Mutex
|
||||
|
@ -39,14 +39,23 @@ type Attributes struct {
|
|||
|
||||
TextBgColor color.RGBA
|
||||
|
||||
ScrollAreaColor color.RGBA
|
||||
ScrollHandleColor color.RGBA
|
||||
BorderSize int
|
||||
|
||||
BorderColorTop color.RGBA
|
||||
BorderColorRight color.RGBA
|
||||
BorderColorBottom color.RGBA
|
||||
BorderColorLeft color.RGBA
|
||||
|
||||
ScrollAreaColor color.RGBA
|
||||
ScrollHandleColor color.RGBA
|
||||
|
||||
ScrollBorderSize int
|
||||
|
||||
ScrollBorderColorTop color.RGBA
|
||||
ScrollBorderColorRight color.RGBA
|
||||
ScrollBorderColorBottom color.RGBA
|
||||
ScrollBorderColorLeft color.RGBA
|
||||
|
||||
InputBgColor color.RGBA
|
||||
|
||||
ButtonTextColor color.RGBA
|
||||
|
@ -54,7 +63,7 @@ type Attributes struct {
|
|||
ButtonBgColorDisabled color.RGBA
|
||||
}
|
||||
|
||||
// Style is the current default attribute configuration.
|
||||
// Style is the current default attribute configuration. Integer values will be scaled.
|
||||
var Style = &Attributes{
|
||||
TextFont: defaultFont(),
|
||||
TextFontMutex: &sync.Mutex{},
|
||||
|
@ -64,13 +73,22 @@ var Style = &Attributes{
|
|||
|
||||
TextBgColor: transparent,
|
||||
|
||||
BorderSize: 4,
|
||||
|
||||
BorderColorTop: color.RGBA{220, 220, 220, 255},
|
||||
BorderColorRight: color.RGBA{0, 0, 0, 255},
|
||||
BorderColorBottom: color.RGBA{0, 0, 0, 255},
|
||||
BorderColorLeft: color.RGBA{220, 220, 220, 255},
|
||||
|
||||
ScrollAreaColor: color.RGBA{200, 200, 200, 255},
|
||||
ScrollHandleColor: color.RGBA{108, 108, 108, 255},
|
||||
|
||||
BorderColorTop: color.RGBA{255, 255, 255, 255},
|
||||
BorderColorRight: color.RGBA{0, 0, 0, 255},
|
||||
BorderColorBottom: color.RGBA{0, 0, 0, 255},
|
||||
BorderColorLeft: color.RGBA{255, 255, 255, 255},
|
||||
ScrollBorderSize: 2,
|
||||
|
||||
ScrollBorderColorTop: color.RGBA{240, 240, 240, 255},
|
||||
ScrollBorderColorRight: color.RGBA{0, 0, 0, 255},
|
||||
ScrollBorderColorBottom: color.RGBA{0, 0, 0, 255},
|
||||
ScrollBorderColorLeft: color.RGBA{240, 240, 240, 255},
|
||||
|
||||
InputBgColor: color.RGBA{0, 128, 0, 255},
|
||||
|
||||
|
|
178
text.go
178
text.go
|
@ -3,49 +3,56 @@ package etk
|
|||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"sync"
|
||||
|
||||
"code.rocket9labs.com/tslocum/etk/messeji"
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"golang.org/x/image/font"
|
||||
)
|
||||
|
||||
// Text is a text display widget.
|
||||
type Text struct {
|
||||
*messeji.TextField
|
||||
|
||||
background color.RGBA
|
||||
children []Widget
|
||||
*Box
|
||||
field *messeji.TextField
|
||||
children []Widget
|
||||
}
|
||||
|
||||
// NewText returns a new Text widget.
|
||||
func NewText(text string) *Text {
|
||||
textColor := Style.TextColorLight
|
||||
|
||||
l := messeji.NewTextField(Style.TextFont, Style.TextFontMutex)
|
||||
l.SetText(text)
|
||||
l.SetForegroundColor(textColor)
|
||||
l.SetBackgroundColor(Style.TextBgColor)
|
||||
l.SetScrollBarColors(Style.ScrollAreaColor, Style.ScrollHandleColor)
|
||||
l.SetHandleKeyboard(true)
|
||||
f := newText()
|
||||
f.SetText(text)
|
||||
f.SetForegroundColor(Style.TextColorLight)
|
||||
f.SetHandleKeyboard(true)
|
||||
|
||||
return &Text{
|
||||
TextField: l,
|
||||
Box: NewBox(),
|
||||
field: f,
|
||||
}
|
||||
}
|
||||
|
||||
// Background returns the background color of the widget.
|
||||
func (t *Text) Background() color.RGBA {
|
||||
// SetRect sets the position and size of the widget.
|
||||
func (t *Text) SetRect(r image.Rectangle) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
return t.background
|
||||
t.rect = r
|
||||
t.field.SetRect(r)
|
||||
}
|
||||
|
||||
// SetBackground sets the background color of the widget.
|
||||
func (t *Text) SetBackground(background color.RGBA) {
|
||||
// Foreground return the color of the text within the field.
|
||||
func (t *Text) Foreground() color.RGBA {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.background = background
|
||||
return t.field.ForegroundColor()
|
||||
}
|
||||
|
||||
// SetForegroundColor sets the color of the text within the field.
|
||||
func (t *Text) SetForeground(c color.RGBA) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.field.SetForegroundColor(c)
|
||||
}
|
||||
|
||||
// Focus returns the focus state of the widget.
|
||||
|
@ -58,34 +65,151 @@ func (t *Text) SetFocus(focus bool) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// Clear clears the text buffer.
|
||||
func (t *Text) Clear() {
|
||||
t.TextField.SetText("")
|
||||
// SetScrollBarWidth sets the width of the scroll bar.
|
||||
func (t *Text) SetScrollBarWidth(width int) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.field.SetScrollBarWidth(width)
|
||||
}
|
||||
|
||||
// SetScrollBarColors sets the color of the scroll bar area and handle.
|
||||
func (t *Text) SetScrollBarColors(area color.RGBA, handle color.RGBA) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.field.SetScrollBarColors(Style.ScrollAreaColor, Style.ScrollHandleColor)
|
||||
}
|
||||
|
||||
// SetScrollBorderColor sets the color of the top, right, bottom and left border
|
||||
// of the scroll bar handle.
|
||||
func (t *Text) SetScrollBorderColors(top color.RGBA, right color.RGBA, bottom color.RGBA, left color.RGBA) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.field.SetScrollBorderColors(top, right, bottom, left)
|
||||
}
|
||||
|
||||
// SetWordWrap sets a flag which, when enabled, causes text to wrap without breaking words.
|
||||
func (t *Text) SetWordWrap(wrap bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.field.SetWordWrap(wrap)
|
||||
}
|
||||
|
||||
// SetHorizontal sets the horizontal alignment of the text within the field.
|
||||
func (t *Text) SetHorizontal(h Alignment) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.field.SetHorizontal(messeji.Alignment(h))
|
||||
}
|
||||
|
||||
// SetVertical sets the vertical alignment of the text within the field.
|
||||
func (t *Text) SetVertical(h Alignment) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.field.SetVertical(messeji.Alignment(h))
|
||||
}
|
||||
|
||||
// Write writes to the text buffer.
|
||||
func (t *Text) Write(p []byte) (n int, err error) {
|
||||
return t.TextField.Write(p)
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
return t.field.Write(p)
|
||||
}
|
||||
|
||||
// Text returns the content of the text buffer.
|
||||
func (t *Text) Text() string {
|
||||
return t.TextField.Text()
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
return t.field.Text()
|
||||
}
|
||||
|
||||
// SetText sets the text in the field.
|
||||
func (t *Text) SetText(text string) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.field.SetText(text)
|
||||
}
|
||||
|
||||
// SetScrollBarVisible sets whether the scroll bar is visible on the screen.
|
||||
func (t *Text) SetScrollBarVisible(scrollVisible bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.field.SetScrollBarVisible(scrollVisible)
|
||||
}
|
||||
|
||||
// SetAutoHideScrollBar sets whether the scroll bar is automatically hidden
|
||||
// when the entire text buffer is visible.
|
||||
func (t *Text) SetAutoHideScrollBar(autoHide bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.field.SetAutoHideScrollBar(autoHide)
|
||||
}
|
||||
|
||||
// SetFont sets the font face of the text within the field.
|
||||
func (t *Text) SetFont(face font.Face, mutex *sync.Mutex) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.field.SetFont(face, mutex)
|
||||
}
|
||||
|
||||
// Padding returns the amount of padding around the text within the field.
|
||||
func (t *Text) Padding() int {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
return t.field.Padding()
|
||||
}
|
||||
|
||||
// SetPadding sets the amount of padding around the text within the field.
|
||||
func (t *Text) SetPadding(padding int) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.field.SetPadding(padding)
|
||||
}
|
||||
|
||||
// SetFollow sets whether the field should automatically scroll to the end when
|
||||
// content is added to the buffer.
|
||||
func (t *Text) SetFollow(follow bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.field.SetFollow(follow)
|
||||
}
|
||||
|
||||
// SetSingleLine sets whether the field displays all text on a single line.
|
||||
// When enabled, the field scrolls horizontally. Otherwise, it scrolls vertically.
|
||||
func (t *Text) SetSingleLine(single bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.field.SetSingleLine(single)
|
||||
}
|
||||
|
||||
// HandleKeyboard is called when a keyboard event occurs.
|
||||
func (t *Text) HandleKeyboard(key ebiten.Key, r rune) (handled bool, err error) {
|
||||
return t.TextField.HandleKeyboardEvent(key, r)
|
||||
return t.field.HandleKeyboardEvent(key, r)
|
||||
}
|
||||
|
||||
// HandleMouse is called when a mouse event occurs.
|
||||
func (t *Text) HandleMouse(cursor image.Point, pressed bool, clicked bool) (handled bool, err error) {
|
||||
return t.TextField.HandleMouseEvent(cursor, pressed, clicked)
|
||||
return t.field.HandleMouseEvent(cursor, pressed, clicked)
|
||||
}
|
||||
|
||||
// Draw draws the widget on the screen.
|
||||
func (t *Text) Draw(screen *ebiten.Image) error {
|
||||
t.TextField.Draw(screen)
|
||||
t.field.Draw(screen)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue