Labels may request an expanding height change
This commit is contained in:
parent
7754679710
commit
d9281b139f
@ -17,6 +17,7 @@ type wordLayout struct {
|
||||
position image.Point
|
||||
width int
|
||||
spaceAfter int
|
||||
breaksAfter int
|
||||
text []characterLayout
|
||||
}
|
||||
|
||||
@ -167,13 +168,16 @@ func (drawer *TextDrawer) LineHeight () (height fixed.Int26_6) {
|
||||
func (drawer *TextDrawer) ReccomendedHeightFor (width int) (height int) {
|
||||
if !drawer.layoutClean { drawer.recalculate() }
|
||||
metrics := drawer.face.Metrics()
|
||||
dot := fixed.Point26_6 { 0, 0 }
|
||||
dot := fixed.Point26_6 { 0, metrics.Height }
|
||||
for _, word := range drawer.layout {
|
||||
dot.X += fixed.Int26_6((word.width + word.spaceAfter) << 6)
|
||||
|
||||
if word.width + word.position.X > width && word.position.X > 0 {
|
||||
if word.width + dot.X.Round() > width {
|
||||
dot.Y += metrics.Height
|
||||
dot.X = fixed.Int26_6(word.width << 6)
|
||||
dot.X = 0
|
||||
}
|
||||
dot.X += fixed.I(word.width + word.spaceAfter)
|
||||
if word.breaksAfter > 0 {
|
||||
dot.Y += fixed.I(word.breaksAfter).Mul(metrics.Height)
|
||||
dot.X = 0
|
||||
}
|
||||
}
|
||||
|
||||
@ -246,6 +250,7 @@ func (drawer *TextDrawer) recalculate () {
|
||||
if character == '\n' {
|
||||
dot.Y += metrics.Height
|
||||
dot.X = 0
|
||||
word.breaksAfter ++
|
||||
previousCharacter = character
|
||||
index ++
|
||||
} else {
|
||||
@ -290,7 +295,6 @@ func (drawer *TextDrawer) recalculate () {
|
||||
|
||||
if drawer.wrap {
|
||||
drawer.layoutBounds.Max.X = drawer.width
|
||||
println("aaa")
|
||||
} else {
|
||||
drawer.layoutBounds.Max.X = horizontalExtent
|
||||
}
|
||||
|
@ -89,6 +89,7 @@ func (window *Window) Adopt (child tomo.Element) {
|
||||
child.SetParentHooks (tomo.ParentHooks {
|
||||
Draw: window.childDrawCallback,
|
||||
MinimumSizeChange: window.childMinimumSizeChangeCallback,
|
||||
ExpandingHeightChange: window.resizeChildToFit,
|
||||
SelectionRequest: window.childSelectionRequestCallback,
|
||||
})
|
||||
|
||||
@ -205,8 +206,25 @@ func (window *Window) resizeChildToFit () {
|
||||
if child, ok := window.child.(tomo.Expanding); ok {
|
||||
minimumHeight := child.MinimumHeightFor(window.metrics.width)
|
||||
_, minimumWidth := child.MinimumSize()
|
||||
window.childMinimumSizeChangeCallback (
|
||||
minimumWidth, minimumHeight)
|
||||
|
||||
|
||||
icccm.WmNormalHintsSet (
|
||||
window.backend.connection,
|
||||
window.xWindow.Id,
|
||||
&icccm.NormalHints {
|
||||
Flags: icccm.SizeHintPMinSize,
|
||||
MinWidth: uint(minimumWidth),
|
||||
MinHeight: uint(minimumHeight),
|
||||
})
|
||||
|
||||
if window.metrics.height >= minimumHeight &&
|
||||
window.metrics.width >= minimumWidth {
|
||||
|
||||
window.child.Resize (
|
||||
window.metrics.width,
|
||||
window.metrics.height)
|
||||
window.redrawChildEntirely()
|
||||
}
|
||||
} else {
|
||||
window.child.Resize (
|
||||
window.metrics.width,
|
||||
|
12
element.go
12
element.go
@ -16,6 +16,10 @@ type ParentHooks struct {
|
||||
// event.
|
||||
MinimumSizeChange func (width, height int)
|
||||
|
||||
// ExpandingHeightChange is called when the parameters affecting the
|
||||
// element's expanding height have changed.
|
||||
ExpandingHeightChange func ()
|
||||
|
||||
// SelectionRequest is called when the child element element wants
|
||||
// itself to be selected. If the parent element chooses to grant the
|
||||
// request, it must send the child element a selection event and return
|
||||
@ -42,6 +46,14 @@ func (hooks ParentHooks) RunMinimumSizeChange (width, height int) {
|
||||
}
|
||||
}
|
||||
|
||||
// RunExpandingHeightChange runs the ExpandingHeightChange hook if it is not
|
||||
// nil. If it is nil, it does nothing.
|
||||
func (hooks ParentHooks) RunExpandingHeightChange () {
|
||||
if hooks.ExpandingHeightChange != nil {
|
||||
hooks.ExpandingHeightChange()
|
||||
}
|
||||
}
|
||||
|
||||
// RunSelectionRequest runs the SelectionRequest hook if it is not nil. If it is
|
||||
// nil, it does nothing.
|
||||
func (hooks ParentHooks) RunSelectionRequest () (granted bool) {
|
||||
|
@ -27,6 +27,7 @@ func NewLabel (text string, wrap bool) (element *Label) {
|
||||
return
|
||||
}
|
||||
|
||||
// Resize resizes the label and re-wraps the text if wrapping is enabled.
|
||||
func (element *Label) Resize (width, height int) {
|
||||
element.core.AllocateCanvas(width, height)
|
||||
if element.wrap {
|
||||
@ -37,6 +38,17 @@ func (element *Label) Resize (width, height int) {
|
||||
return
|
||||
}
|
||||
|
||||
// MinimumHeightFor returns the reccomended height for this element based on the
|
||||
// given width in order to allow the text to wrap properly.
|
||||
func (element *Label) MinimumHeightFor (width int) (height int) {
|
||||
if element.wrap {
|
||||
return element.drawer.ReccomendedHeightFor(width)
|
||||
} else {
|
||||
_, height = element.MinimumSize()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// SetText sets the label's text.
|
||||
func (element *Label) SetText (text string) {
|
||||
if element.text == text { return }
|
||||
@ -76,6 +88,7 @@ func (element *Label) updateMinimumSize () {
|
||||
if em < 1 { em = theme.Padding() }
|
||||
element.core.SetMinimumSize (
|
||||
em, element.drawer.LineHeight().Round())
|
||||
element.core.NotifyExpandingHeightChange()
|
||||
} else {
|
||||
bounds := element.drawer.LayoutBounds()
|
||||
element.core.SetMinimumSize(bounds.Dx(), bounds.Dy())
|
||||
|
@ -144,6 +144,12 @@ func (control CoreControl) SetMinimumSize (width, height int) {
|
||||
}
|
||||
}
|
||||
|
||||
// NotifyExpandingHeightChange notifies the parent element that this element's
|
||||
// expanding height has changed.
|
||||
func (control CoreControl) NotifyExpandingHeightChange () {
|
||||
control.core.hooks.RunExpandingHeightChange()
|
||||
}
|
||||
|
||||
// ConstrainSize contstrains the specified width and height to the minimum width
|
||||
// and height, and returns wether or not anything ended up being constrained.
|
||||
func (control CoreControl) ConstrainSize (
|
||||
|
@ -21,7 +21,7 @@ func run () {
|
||||
world.Stages = map [string] func () {
|
||||
"start": func () {
|
||||
label := basic.NewLabel (
|
||||
"you are standing next to a river.", false)
|
||||
"you are standing next to a river.", true)
|
||||
|
||||
button0 := basic.NewButton("go in the river")
|
||||
button0.OnClick(world.SwitchFunc("wet"))
|
||||
@ -41,7 +41,7 @@ func run () {
|
||||
"wet": func () {
|
||||
label := basic.NewLabel (
|
||||
"you get completely soaked.\n" +
|
||||
"you die of hypothermia.", false)
|
||||
"you die of hypothermia.", true)
|
||||
|
||||
button0 := basic.NewButton("try again")
|
||||
button0.OnClick(world.SwitchFunc("start"))
|
||||
@ -58,7 +58,7 @@ func run () {
|
||||
"house": func () {
|
||||
label := basic.NewLabel (
|
||||
"you are standing in front of a delapidated " +
|
||||
"house.", false)
|
||||
"house.", true)
|
||||
|
||||
button1 := basic.NewButton("go inside")
|
||||
button1.OnClick(world.SwitchFunc("inside"))
|
||||
@ -78,7 +78,7 @@ func run () {
|
||||
"it is dark, but rays of light stream " +
|
||||
"through the window.\n" +
|
||||
"there is nothing particularly interesting " +
|
||||
"here.", false)
|
||||
"here.", true)
|
||||
|
||||
button0 := basic.NewButton("go back outside")
|
||||
button0.OnClick(world.SwitchFunc("house"))
|
||||
@ -92,7 +92,7 @@ func run () {
|
||||
"bear": func () {
|
||||
label := basic.NewLabel (
|
||||
"you come face to face with a bear.\n" +
|
||||
"it eats you (it was hungry).", false)
|
||||
"it eats you (it was hungry).", true)
|
||||
|
||||
button0 := basic.NewButton("try again")
|
||||
button0.OnClick(world.SwitchFunc("start"))
|
||||
|
@ -9,7 +9,7 @@ func main () {
|
||||
}
|
||||
|
||||
func run () {
|
||||
window, _ := tomo.NewWindow(480, 360)
|
||||
window, _ := tomo.NewWindow(480, 2)
|
||||
window.SetTitle("example label")
|
||||
window.Adopt(basic.NewLabel(text, true))
|
||||
window.OnClose(tomo.Stop)
|
||||
|
Reference in New Issue
Block a user