1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-11-10 06:16:27 -05:00
OpenDiablo2/d2core/d2ui/textbox.go
Maxime Lavigne (malavv) 0a78a1adcc
Centralized usage of Fonts to fix cache #515 (#556)
The split between d2ui and d2asset Font version caused incorrect caching between the two. After looking at d2interface.Font, I saw the d2asset was the most recent and more tightly and cleanly packaged.

I therefore removed the old d2ui.Font and embedded the d2asset version in the d2ui.Label and d2ui.Button.

Looking at the code of d2ui, it would be logical to completly swap it for their d2gui version. But at least for the moment, the d2ui.Button as more functionality since it embeds a Label (instead of a font), and this label now has multiline horizontal alignement.
2020-07-07 20:16:22 -04:00

183 lines
3.5 KiB
Go

package d2ui
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"strings"
"time"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
)
// TextBox with cursor focus
var focusedTextBox *TextBox
// TextBox represents a text input box
type TextBox struct {
text string
x int
y int
visible bool
enabled bool
bgSprite *Sprite
textLabel Label
lineBar Label
filter string
}
func CreateTextbox(renderer d2interface.Renderer) TextBox {
animation, _ := d2asset.LoadAnimation(d2resource.TextBox2, d2resource.PaletteUnits)
bgSprite, _ := LoadSprite(animation)
tb := TextBox{
filter: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
bgSprite: bgSprite,
textLabel: CreateLabel(d2resource.FontFormal11, d2resource.PaletteUnits),
lineBar: CreateLabel(d2resource.FontFormal11, d2resource.PaletteUnits),
enabled: true,
visible: true,
}
tb.lineBar.SetText("_")
return tb
}
func (v *TextBox) SetFilter(filter string) {
v.filter = filter
}
func (v *TextBox) Render(target d2interface.Surface) {
if !v.visible {
return
}
v.bgSprite.Render(target)
v.textLabel.Render(target)
if (time.Now().UnixNano()/1e6)&(1<<8) > 0 {
v.lineBar.Render(target)
}
}
func (v *TextBox) OnKeyChars(event d2interface.KeyCharsEvent) bool {
if !(focusedTextBox == v) || !v.visible || !v.enabled {
return false
}
newText := string(event.Chars())
if len(newText) > 0 {
v.text += newText
v.SetText(v.text)
return true
}
return false
}
func (v *TextBox) OnKeyRepeat(event d2interface.KeyEvent) bool {
if event.Key() == d2enum.KeyBackspace && debounceEvents(event.Duration()) {
if len(v.text) >= 1 {
v.text = v.text[:len(v.text)-1]
}
v.SetText(v.text)
}
return false
}
func debounceEvents(numFrames int) bool {
const (
delay = 30
interval = 3
)
if numFrames == 1 {
return true
}
if numFrames >= delay && (numFrames-delay)%interval == 0 {
return true
}
return false
}
func (v *TextBox) Advance(_ float64) {
if !v.visible || !v.enabled {
return
}
}
func (v *TextBox) Update() {
}
func (v *TextBox) GetText() string {
return v.text
}
func (v *TextBox) SetText(newText string) {
result := ""
for _, c := range newText {
if !strings.Contains(v.filter, string(c)) {
continue
}
result += string(c)
}
if len(result) > 15 {
result = result[0:15]
}
v.text = result
for {
tw, _ := v.textLabel.GetTextMetrics(result)
if tw > 150 {
result = result[1:]
continue
}
v.lineBar.SetPosition(v.x+6+tw, v.y+3)
v.textLabel.SetText(result)
break
}
}
func (v *TextBox) GetSize() (width, height int) {
return v.bgSprite.GetCurrentFrameSize()
}
func (v *TextBox) SetPosition(x, y int) {
lw, _ := v.textLabel.GetSize()
v.x = x
v.y = y
v.textLabel.SetPosition(v.x+6, v.y+3)
v.lineBar.SetPosition(v.x+6+lw, v.y+3)
v.bgSprite.SetPosition(v.x, v.y+26)
}
func (v *TextBox) GetPosition() (x, y int) {
return v.x, v.y
}
func (v *TextBox) GetVisible() bool {
return v.visible
}
func (v *TextBox) SetVisible(visible bool) {
v.visible = visible
}
func (v *TextBox) GetEnabled() bool {
return v.enabled
}
func (v *TextBox) SetEnabled(enabled bool) {
v.enabled = enabled
}
func (v *TextBox) SetPressed(pressed bool) {
// no op
}
func (v *TextBox) GetPressed() bool {
return false
}
func (v *TextBox) OnActivated(callback func()) {
// no op
}
func (v *TextBox) Activate() {
focusedTextBox = v
}