@ -13,8 +13,22 @@ import (
"golang.org/x/image/font"
)
// 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
)
const (
initialPadding = 2
initialPadding = 5
initialScrollWidth = 32
)
@ -51,9 +65,18 @@ type TextField struct {
// line mode is enabled,
bufferSize int
// lineWidths is the size (in pixels) of each line as it appears on the screen.
lineWidths [ ] int
// singleLine is whether the field displays all text on a single line.
singleLine bool
// horizontal is the horizontal alignment of the text within field.
horizontal Alignment
// vertical is the vertical alignment of the text within field.
vertical Alignment
// face is the font face of the text within the field.
face font . Face
@ -207,6 +230,32 @@ func (f *TextField) SetSingleLine(single bool) {
f . bufferModified ( )
}
// SetHorizontal sets the horizontal alignment of the text within the field.
func ( f * TextField ) SetHorizontal ( h Alignment ) {
f . Lock ( )
defer f . Unlock ( )
if f . horizontal == h {
return
}
f . horizontal = h
f . bufferModified ( )
}
// SetVertical sets the veritcal alignment of the text within the field.
func ( f * TextField ) SetVertical ( v Alignment ) {
f . Lock ( )
defer f . Unlock ( )
if f . vertical == v {
return
}
f . vertical = v
f . bufferModified ( )
}
// LineHeight returns the line height for the field.
func ( f * TextField ) LineHeight ( ) int {
f . Lock ( )
@ -467,10 +516,15 @@ func (f *TextField) setDefaultLineHeight() {
}
func ( f * TextField ) wrapContent ( withScrollBar bool ) {
f . lineWidths = f . lineWidths [ : 0 ]
buffer := f . prefix + f . buffer + f . suffix
if f . singleLine {
f . bufferWrapped = [ ] string { strings . ReplaceAll ( buffer , "\n" , "" ) }
buffer = strings . ReplaceAll ( buffer , "\n" , "" )
bounds := text . BoundString ( f . face , buffer )
f . bufferWrapped = [ ] string { buffer }
f . lineWidths = append ( f . lineWidths , bounds . Dx ( ) )
return
}
@ -483,8 +537,11 @@ func (f *TextField) wrapContent(withScrollBar bool) {
l := len ( line )
var start int
var end int
var initialEnd int
for start < l {
for end = l ; end > start ; end -- {
initialEnd = end
bounds := text . BoundString ( f . face , line [ start : end ] )
if bounds . Dx ( ) < w - ( f . padding * 2 ) - 2 {
if f . wordWrap {
@ -492,12 +549,21 @@ func (f *TextField) wrapContent(withScrollBar bool) {
for endOffset := 0 ; endOffset < end - start ; endOffset ++ {
if unicode . IsSpace ( rune ( line [ end - endOffset ] ) ) {
end = end - endOffset
if end < l - 1 {
end ++
}
break
}
}
}
}
if end != initialEnd && f . horizontal != AlignStart {
bounds = text . BoundString ( f . face , line [ start : end ] )
}
f . bufferWrapped = append ( f . bufferWrapped , line [ start : end ] )
f . lineWidths = append ( f . lineWidths , bounds . Dx ( ) )
break
}
}
@ -510,12 +576,19 @@ func (f *TextField) wrapContent(withScrollBar bool) {
func ( f * TextField ) drawContent ( ) ( overflow bool ) {
f . img . Fill ( f . backgroundColor )
fieldWidth := f . r . Dx ( )
fieldHeight := f . r . Dy ( )
if f . showScrollBar ( ) {
fieldWidth -= f . scrollWidth
}
lines := len ( f . bufferWrapped )
h := f . r . Dy ( )
lineHeight := f . overrideLineHeight
if lineHeight == 0 {
lineHeight = f . lineHeight
}
lineOffset := 7
lineOffset := lineHeight / 3
f . bufferSize = 0
for i , line := range f . bufferWrapped {
lineX := f . padding
@ -545,6 +618,18 @@ func (f *TextField) drawContent() (overflow bool) {
lineY -= f . offset
}
if f . horizontal == AlignCenter {
lineX = ( fieldWidth - f . lineWidths [ i ] ) / 2
} else if f . horizontal == AlignEnd {
lineX = ( fieldWidth - f . lineWidths [ i ] ) - f . padding * 2
}
if f . vertical == AlignCenter && lineHeight * lines <= h {
lineY = ( fieldHeight - ( lineHeight * lines ) ) / 2 + lineHeight * ( i + 1 ) - lineOffset
} else if f . vertical == AlignEnd && lineHeight * lines <= h {
lineY = ( fieldHeight - lineHeight * i ) - f . padding * 2
}
text . Draw ( f . img , line , f . face , lineX , lineY , f . textColor )
}
@ -596,22 +681,20 @@ func (f *TextField) drawImage() {
f . drawContent ( )
}
scrollBarW := 32
// Draw scrollbar.
if f . showScrollBar ( ) {
scrollAreaX , scrollAreaY := w - scrollBar W, 0
f . scrollRect = image . Rect ( scrollAreaX , scrollAreaY , scrollAreaX + scrollBar W, h )
scrollAreaX , scrollAreaY := w - f. scrollWidth , 0
f . scrollRect = image . Rect ( scrollAreaX , scrollAreaY , scrollAreaX + f. scrollWidth , h )
scrollBarH := f . scrollWidth / 2
if scrollBarH < 4 {
scrollBarH = 4
}
scrollX , scrollY := w - scrollBar W, 0
scrollX , scrollY := w - f. scrollWidth , 0
pct := float64 ( f . offset ) / float64 ( f . bufferSize - h )
scrollY += int ( float64 ( h - scrollBarH ) * pct )
scrollBarRect := image . Rect ( scrollX , scrollY , scrollX + scrollBar W, scrollY + scrollBarH )
scrollBarRect := image . Rect ( scrollX , scrollY , scrollX + f. scrollWidth , scrollY + scrollBarH )
f . img . SubImage ( f . scrollRect ) . ( * ebiten . Image ) . Fill ( color . RGBA { 200 , 200 , 200 , 255 } )
f . img . SubImage ( scrollBarRect ) . ( * ebiten . Image ) . Fill ( color . RGBA { 108 , 108 , 108 , 255 } )