This repository has been archived on 2024-06-03. You can view files and clone it, but cannot push or open issues or pull requests.
x/textbox.go

131 lines
3.1 KiB
Go

package x
import "image"
import "image/color"
import "golang.org/x/image/font"
import "git.tebibyte.media/tomo/tomo"
import "git.tebibyte.media/tomo/typeset"
import "git.tebibyte.media/tomo/tomo/event"
import "git.tebibyte.media/tomo/tomo/canvas"
type textBox struct {
*box
hOverflow, vOverflow bool
contentBounds image.Rectangle
scroll image.Point
text string
textColor color.Color
face font.Face
hAlign tomo.Align
drawer typeset.Drawer
on struct {
contentBoundsChange event.FuncBroadcaster
}
}
func (backend *Backend) NewTextBox() tomo.TextBox {
box := &textBox {
box: backend.NewBox().(*box),
textColor: color.Black,
}
box.box.drawer = box
box.outer = box
return box
}
func (this *textBox) SetOverflow (horizontal, vertical bool) {
if this.hOverflow == horizontal && this.vOverflow == vertical { return }
this.hOverflow = horizontal
this.vOverflow = vertical
this.invalidateLayout()
}
func (this *textBox) ContentBounds () image.Rectangle {
return this.contentBounds
}
func (this *textBox) ScrollTo (point image.Point) {
// TODO: constrain scroll
this.scroll = point
this.invalidateLayout()
}
func (this *textBox) OnContentBoundsChange (callback func()) event.Cookie {
return this.on.contentBoundsChange.Connect(callback)
}
func (this *textBox) SetText (text string) {
if this.text == text { return }
this.text = text
this.drawer.SetText([]rune(text))
this.recalculateMinimumSize()
this.invalidateLayout()
}
func (this *textBox) SetTextColor (c color.Color) {
if this.textColor == c { return }
this.textColor = c
this.invalidateDraw()
}
func (this *textBox) SetFace (face font.Face) {
if this.face == face { return }
this.face = face
this.drawer.SetFace(face)
this.recalculateMinimumSize()
this.invalidateLayout()
}
func (this *textBox) SetHAlign (align tomo.Align) {
if this.hAlign == align { return }
this.hAlign = align
switch align {
case tomo.AlignStart: this.drawer.SetAlign(typeset.AlignLeft)
case tomo.AlignMiddle: this.drawer.SetAlign(typeset.AlignCenter)
case tomo.AlignEnd: this.drawer.SetAlign(typeset.AlignRight)
case tomo.AlignEven: this.drawer.SetAlign(typeset.AlignJustify)
}
this.invalidateDraw()
}
func (this *textBox) SetVAlign (align tomo.Align) {
// TODO
}
func (this *textBox) Draw (can canvas.Canvas) {
if can == nil { return }
this.drawBorders(can)
pen := can.Pen()
pen.Fill(this.color)
pen.Rectangle(can.Bounds())
if this.face == nil { return }
offset := this.InnerBounds().Min.
Sub(this.scroll).
Sub(this.drawer.LayoutBoundsSpace().Min)
this.drawer.Draw(can, this.textColor, offset)
}
func (this *textBox) recalculateMinimumSize () {
// TODO calculate minimum size and use SetMinimumSize
}
func (this *textBox) doLayout () {
this.box.doLayout()
previousContentBounds := this.contentBounds
this.contentBounds = this.drawer.LayoutBoundsSpace()
this.contentBounds = this.contentBounds.Sub(this.contentBounds.Min)
this.contentBounds = this.contentBounds.Sub(this.scroll)
if previousContentBounds != this.contentBounds {
this.on.contentBoundsChange.Broadcast()
}
}