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