Changed the way minimum sizes are calculated
Boxes that need their minimum size to be updated now use a map like for layout and drawing. Size set with MinimumSize is now treated as separate from the content size and the larger size is used.
This commit is contained in:
		
							parent
							
								
									00629a863d
								
							
						
					
					
						commit
						ff8875535d
					
				
							
								
								
									
										10
									
								
								backend.go
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								backend.go
									
									
									
									
									
								
							| @ -48,9 +48,7 @@ func (backend *Backend) Run () error { | |||||||
| 		case <- pingQuit: | 		case <- pingQuit: | ||||||
| 			return nil // FIXME: if we exited due to an error say so | 			return nil // FIXME: if we exited due to an error say so | ||||||
| 		} | 		} | ||||||
| 		for _, window := range backend.windows { | 		backend.afterEvent() | ||||||
| 			window.afterEvent() |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -78,3 +76,9 @@ func (backend *Backend) Do (callback func ()) { | |||||||
| func (backend *Backend) assert () { | func (backend *Backend) assert () { | ||||||
| 	if backend == nil { panic("nil backend") } | 	if backend == nil { panic("nil backend") } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func (backend *Backend) afterEvent () { | ||||||
|  | 	for _, window := range backend.windows { | ||||||
|  | 		window.afterEvent() | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										88
									
								
								box.go
									
									
									
									
									
								
							
							
						
						
									
										88
									
								
								box.go
									
									
									
									
									
								
							| @ -13,8 +13,12 @@ type box struct { | |||||||
| 	parent   parent | 	parent   parent | ||||||
| 	outer    anyBox | 	outer    anyBox | ||||||
| 
 | 
 | ||||||
| 	bounds  image.Rectangle | 	bounds      image.Rectangle | ||||||
| 	minSize image.Point | 	minSize     image.Point | ||||||
|  | 	userMinSize image.Point | ||||||
|  | 	 | ||||||
|  | 	minSizeQueued bool | ||||||
|  | 	focusQueued   *bool | ||||||
| 
 | 
 | ||||||
| 	padding tomo.Inset | 	padding tomo.Inset | ||||||
| 	border  []tomo.Border | 	border  []tomo.Border | ||||||
| @ -45,13 +49,23 @@ type box struct { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (backend *Backend) NewBox() tomo.Box { | func (backend *Backend) newBox (outer anyBox) *box { | ||||||
| 	box := &box { | 	box := &box { | ||||||
| 		backend: backend, | 		backend: backend, | ||||||
| 		color:   color.White, | 		color:   color.White, | ||||||
|  | 		outer:   outer, | ||||||
|  | 		drawer:  outer, | ||||||
| 	} | 	} | ||||||
| 	box.drawer = box | 	if outer == nil { | ||||||
| 	box.outer  = box | 		box.drawer = box | ||||||
|  | 		box.outer  = box | ||||||
|  | 	} | ||||||
|  | 	box.invalidateMinimum() | ||||||
|  | 	return box | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (backend *Backend) NewBox() tomo.Box { | ||||||
|  | 	box := backend.newBox(nil) | ||||||
| 	return box | 	return box | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -105,23 +119,20 @@ func (this *box) SetColor (c color.Color) { | |||||||
| func (this *box) SetBorder (border ...tomo.Border) { | func (this *box) SetBorder (border ...tomo.Border) { | ||||||
| 	this.border = border | 	this.border = border | ||||||
| 	this.invalidateLayout() | 	this.invalidateLayout() | ||||||
| 	this.recalculateMinimumSize() | 	this.invalidateMinimum() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *box) SetMinimumSize (size image.Point) { | func (this *box) SetMinimumSize (size image.Point) { | ||||||
| 	if this.minSize == size { return } | 	if this.userMinSize == size { return } | ||||||
| 	this.minSize = size | 	this.userMinSize = size | ||||||
| 	 | 	this.invalidateMinimum() | ||||||
| 	if this.parent != nil { |  | ||||||
| 		this.parent.notifyMinimumSizeChange(this) |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *box) SetPadding (padding tomo.Inset) { | func (this *box) SetPadding (padding tomo.Inset) { | ||||||
| 	if this.padding == padding { return } | 	if this.padding == padding { return } | ||||||
| 	this.padding = padding | 	this.padding = padding | ||||||
| 	this.invalidateLayout() | 	this.invalidateLayout() | ||||||
| 	this.recalculateMinimumSize() | 	this.invalidateMinimum() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *box) SetDNDData (dat data.Data) { | func (this *box) SetDNDData (dat data.Data) { | ||||||
| @ -133,9 +144,11 @@ func (this *box) SetDNDAccept (types ...data.Mime) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *box) SetFocused (focused bool) { | func (this *box) SetFocused (focused bool) { | ||||||
| 	if this.parent == nil { return } | 	if this.parent == nil || this.parent.window () == nil { | ||||||
| 	window := this.parent.window() | 		focusedCopy := focused | ||||||
| 	if window == nil { return } | 		this.focusQueued = &focusedCopy | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
| 	if !this.focusable { return } | 	if !this.focusable { return } | ||||||
| 	 | 	 | ||||||
| 	if this.Focused () && !focused { | 	if this.Focused () && !focused { | ||||||
| @ -251,6 +264,30 @@ func (this *box) drawBorders (can canvas.Canvas) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (this *box) contentMinimum () image.Point { | ||||||
|  | 	var minimum image.Point | ||||||
|  | 	minimum.X += this.padding.Horizontal() | ||||||
|  | 	minimum.Y += this.padding.Vertical() | ||||||
|  | 	borderSum := this.borderSum() | ||||||
|  | 	minimum.X += borderSum.Horizontal() | ||||||
|  | 	minimum.Y += borderSum.Vertical() | ||||||
|  | 	return minimum | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (this *box) doMinimumSize () { | ||||||
|  | 	this.minSize = this.outer.contentMinimum() | ||||||
|  | 	if this.minSize.X < this.userMinSize.X { | ||||||
|  | 		this.minSize.X = this.userMinSize.X | ||||||
|  | 	} | ||||||
|  | 	if this.minSize.Y < this.userMinSize.Y { | ||||||
|  | 		this.minSize.Y = this.userMinSize.Y | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	if this.parent != nil { | ||||||
|  | 		this.parent.notifyMinimumSizeChange(this) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (this *box) doDraw () { | func (this *box) doDraw () { | ||||||
| 	if this.canvas == nil { return } | 	if this.canvas == nil { return } | ||||||
| 	if this.drawer != nil { | 	if this.drawer != nil { | ||||||
| @ -273,6 +310,17 @@ func (this *box) setParent (parent parent) { | |||||||
| 	this.parent = parent | 	this.parent = parent | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (this *box) flushActionQueue () { | ||||||
|  | 	if this.parent == nil || this.parent.window() == nil { return } | ||||||
|  | 
 | ||||||
|  | 	if this.minSizeQueued { | ||||||
|  | 		this.invalidateMinimum() | ||||||
|  | 	} | ||||||
|  | 	if this.focusQueued != nil { | ||||||
|  | 		this.SetFocused(*this.focusQueued) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (this *box) recursiveRedo () { | func (this *box) recursiveRedo () { | ||||||
| 	this.doLayout() | 	this.doLayout() | ||||||
| 	this.doDraw() | 	this.doDraw() | ||||||
| @ -288,10 +336,12 @@ func (this *box) invalidateDraw () { | |||||||
| 	this.parent.window().invalidateDraw(this.outer) | 	this.parent.window().invalidateDraw(this.outer) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *box) recalculateMinimumSize () { | func (this *box) invalidateMinimum () { | ||||||
| 	if this.outer != anyBox(this) { | 	if this.parent == nil || this.parent.window() == nil { | ||||||
| 		this.outer.recalculateMinimumSize() | 		this.minSizeQueued = true | ||||||
|  | 		return | ||||||
| 	} | 	} | ||||||
|  | 	this.parent.window().invalidateMinimum(this.outer) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *box) canBeFocused () bool { | func (this *box) canBeFocused () bool { | ||||||
|  | |||||||
| @ -8,11 +8,9 @@ type canvasBox struct { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (backend *Backend) NewCanvasBox () tomo.CanvasBox { | func (backend *Backend) NewCanvasBox () tomo.CanvasBox { | ||||||
| 	box := &canvasBox { | 	this    := &canvasBox { } | ||||||
| 		box: backend.NewBox().(*box), | 	this.box = backend.newBox(this) | ||||||
| 	} | 	return this | ||||||
| 	box.outer = box |  | ||||||
| 	return box |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *canvasBox) Box () tomo.Box { | func (this *canvasBox) Box () tomo.Box { | ||||||
|  | |||||||
| @ -24,13 +24,9 @@ type containerBox struct { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (backend *Backend) NewContainerBox() tomo.ContainerBox { | func (backend *Backend) NewContainerBox() tomo.ContainerBox { | ||||||
| 	box := &containerBox { | 	this    := &containerBox { propagateEvents: true } | ||||||
| 		box:             backend.NewBox().(*box), | 	this.box = backend.newBox(this) | ||||||
| 		propagateEvents: true, | 	return this | ||||||
| 	} |  | ||||||
| 	box.drawer = box |  | ||||||
| 	box.outer  = box |  | ||||||
| 	return box |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *containerBox) SetOverflow (horizontal, vertical bool) { | func (this *containerBox) SetOverflow (horizontal, vertical bool) { | ||||||
| @ -69,7 +65,7 @@ func (this *containerBox) SetGap (gap image.Point) { | |||||||
| 	if this.gap == gap { return } | 	if this.gap == gap { return } | ||||||
| 	this.gap = gap | 	this.gap = gap | ||||||
| 	this.invalidateLayout() | 	this.invalidateLayout() | ||||||
| 	this.recalculateMinimumSize() | 	this.invalidateMinimum() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *containerBox) Add (child tomo.Object) { | func (this *containerBox) Add (child tomo.Object) { | ||||||
| @ -77,9 +73,10 @@ func (this *containerBox) Add (child tomo.Object) { | |||||||
| 	if indexOf(this.children, tomo.Box(box)) > -1 { return } | 	if indexOf(this.children, tomo.Box(box)) > -1 { return } | ||||||
| 	 | 	 | ||||||
| 	box.setParent(this) | 	box.setParent(this) | ||||||
|  | 	box.flushActionQueue() | ||||||
| 	this.children = append(this.children, box) | 	this.children = append(this.children, box) | ||||||
| 	this.invalidateLayout() | 	this.invalidateLayout() | ||||||
| 	this.recalculateMinimumSize() | 	this.invalidateMinimum() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *containerBox) Delete (child tomo.Object) { | func (this *containerBox) Delete (child tomo.Object) { | ||||||
| @ -90,7 +87,7 @@ func (this *containerBox) Delete (child tomo.Object) { | |||||||
| 	box.setParent(nil) | 	box.setParent(nil) | ||||||
| 	this.children = remove(this.children, index) | 	this.children = remove(this.children, index) | ||||||
| 	this.invalidateLayout() | 	this.invalidateLayout() | ||||||
| 	this.recalculateMinimumSize() | 	this.invalidateMinimum() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *containerBox) Insert (child, before tomo.Object) { | func (this *containerBox) Insert (child, before tomo.Object) { | ||||||
| @ -104,7 +101,7 @@ func (this *containerBox) Insert (child, before tomo.Object) { | |||||||
| 	box.setParent(this) | 	box.setParent(this) | ||||||
| 	this.children = insert(this.children, index, tomo.Box(box)) | 	this.children = insert(this.children, index, tomo.Box(box)) | ||||||
| 	this.invalidateLayout() | 	this.invalidateLayout() | ||||||
| 	this.recalculateMinimumSize() | 	this.invalidateMinimum() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *containerBox) Clear () { | func (this *containerBox) Clear () { | ||||||
| @ -113,7 +110,7 @@ func (this *containerBox) Clear () { | |||||||
| 	} | 	} | ||||||
| 	this.children = nil | 	this.children = nil | ||||||
| 	this.invalidateLayout() | 	this.invalidateLayout() | ||||||
| 	this.recalculateMinimumSize() | 	this.invalidateMinimum() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *containerBox) Length () int { | func (this *containerBox) Length () int { | ||||||
| @ -130,7 +127,7 @@ func (this *containerBox) At (index int) tomo.Object { | |||||||
| func (this *containerBox) SetLayout (layout tomo.Layout) { | func (this *containerBox) SetLayout (layout tomo.Layout) { | ||||||
| 	this.layout = layout | 	this.layout = layout | ||||||
| 	this.invalidateLayout() | 	this.invalidateLayout() | ||||||
| 	this.recalculateMinimumSize() | 	this.invalidateMinimum() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *containerBox) Draw (can canvas.Canvas) { | func (this *containerBox) Draw (can canvas.Canvas) { | ||||||
| @ -148,6 +145,13 @@ func (this *containerBox) Draw (can canvas.Canvas) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (this *containerBox) flushActionQueue () { | ||||||
|  | 	for _, box := range this.children { | ||||||
|  | 		box.(anyBox).flushActionQueue() | ||||||
|  | 	} | ||||||
|  | 	this.box.flushActionQueue() | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (this *containerBox) window () *window { | func (this *containerBox) window () *window { | ||||||
| 	if this.parent == nil { return nil } | 	if this.parent == nil { return nil } | ||||||
| 	return this.parent.window() | 	return this.parent.window() | ||||||
| @ -158,8 +162,7 @@ func (this *containerBox) canvas () canvas.Canvas { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *containerBox) notifyMinimumSizeChange (child anyBox) { | func (this *containerBox) notifyMinimumSizeChange (child anyBox) { | ||||||
| 	this.recalculateMinimumSize() | 	this.invalidateMinimum() | ||||||
| 
 |  | ||||||
| 	size   := child.MinimumSize() | 	size   := child.MinimumSize() | ||||||
| 	bounds := child.Bounds() | 	bounds := child.Bounds() | ||||||
| 	if bounds.Dx() < size.X || bounds.Dy() < size.Y { | 	if bounds.Dx() < size.X || bounds.Dy() < size.Y { | ||||||
| @ -179,18 +182,15 @@ func (this *containerBox) layoutHints () tomo.LayoutHints { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *containerBox) recalculateMinimumSize () { | func (this *containerBox) contentMinimum () image.Point { | ||||||
| 	if this.layout == nil { | 	minimum := this.box.contentMinimum() | ||||||
| 		this.SetMinimumSize(image.Point { }) | 	if this.layout != nil { | ||||||
| 		return | 		minimum = minimum.Add ( | ||||||
|  | 			this.layout.MinimumSize ( | ||||||
|  | 				this.layoutHints(), | ||||||
|  | 				this.children)) | ||||||
| 	} | 	} | ||||||
| 	minimum := this.layout.MinimumSize(this.layoutHints(), this.children) | 	return minimum | ||||||
| 	minimum.X += this.padding.Horizontal() |  | ||||||
| 	minimum.Y += this.padding.Vertical() |  | ||||||
| 	borderSum := this.borderSum() |  | ||||||
| 	minimum.X += borderSum.Horizontal() |  | ||||||
| 	minimum.Y += borderSum.Vertical() |  | ||||||
| 	this.SetMinimumSize(minimum) |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *containerBox) doLayout () { | func (this *containerBox) doLayout () { | ||||||
|  | |||||||
							
								
								
									
										35
									
								
								system.go
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								system.go
									
									
									
									
									
								
							| @ -40,13 +40,17 @@ type parent interface { | |||||||
| 
 | 
 | ||||||
| type anyBox interface { | type anyBox interface { | ||||||
| 	tomo.Box | 	tomo.Box | ||||||
| 	doDraw        () | 	canvas.Drawer | ||||||
| 	doLayout      () | 	 | ||||||
| 	setParent     (parent) | 	doDraw           () | ||||||
| 	recursiveRedo () | 	doLayout         () | ||||||
| 	canBeFocused  () bool | 	doMinimumSize    () | ||||||
| 	boxUnder      (image.Point) anyBox | 	contentMinimum   () image.Point | ||||||
| 	recalculateMinimumSize () | 	setParent        (parent) | ||||||
|  | 	flushActionQueue () | ||||||
|  | 	recursiveRedo    () | ||||||
|  | 	canBeFocused     () bool | ||||||
|  | 	boxUnder         (image.Point) anyBox | ||||||
| 
 | 
 | ||||||
| 	propagate    (func (anyBox) bool) bool | 	propagate    (func (anyBox) bool) bool | ||||||
| 	propagateAlt (func (anyBox) bool) bool | 	propagateAlt (func (anyBox) bool) bool | ||||||
| @ -83,10 +87,11 @@ func (window *window) SetRoot (root tomo.Object) { | |||||||
| 	} else { | 	} else { | ||||||
| 		box := assertAnyBox(root.GetBox()) | 		box := assertAnyBox(root.GetBox()) | ||||||
| 		box.setParent(window) | 		box.setParent(window) | ||||||
|  | 		box.flushActionQueue() | ||||||
| 		window.invalidateLayout(box) | 		window.invalidateLayout(box) | ||||||
| 		window.root = box | 		window.root = box | ||||||
| 	} | 	} | ||||||
| 	window.recalculateMinimumSize() | 	window.minimumClean = false | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (window *window) window () *window { | func (window *window) window () *window { | ||||||
| @ -98,7 +103,11 @@ func (window *window) canvas () canvas.Canvas { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (window *window) notifyMinimumSizeChange (anyBox) { | func (window *window) notifyMinimumSizeChange (anyBox) { | ||||||
| 	window.recalculateMinimumSize() | 	window.minimumClean = false | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (window *window) invalidateMinimum (box anyBox) { | ||||||
|  | 	window.needMinimum.Add(box) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (window *window) invalidateDraw (box anyBox) { | func (window *window) invalidateDraw (box anyBox) { | ||||||
| @ -106,8 +115,6 @@ func (window *window) invalidateDraw (box anyBox) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (window *window) invalidateLayout (box anyBox) { | func (window *window) invalidateLayout (box anyBox) { | ||||||
| 	// TODO: use a priority queue for this and have the value be the amount |  | ||||||
| 	// of parents a box has |  | ||||||
| 	window.needLayout.Add(box) | 	window.needLayout.Add(box) | ||||||
| 	window.invalidateDraw(box) | 	window.invalidateDraw(box) | ||||||
| } | } | ||||||
| @ -214,6 +221,12 @@ func (window *window) afterEvent () { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	for len(window.needMinimum) > 0 { | ||||||
|  | 		window.needMinimum.Pop().doMinimumSize() | ||||||
|  | 	} | ||||||
|  | 	if !window.minimumClean { | ||||||
|  | 		window.doMinimumSize() | ||||||
|  | 	} | ||||||
| 	for len(window.needLayout) > 0 { | 	for len(window.needLayout) > 0 { | ||||||
| 		window.needLayout.Pop().doLayout() | 		window.needLayout.Pop().doLayout() | ||||||
| 	} | 	} | ||||||
|  | |||||||
							
								
								
									
										25
									
								
								textbox.go
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								textbox.go
									
									
									
									
									
								
							| @ -39,14 +39,12 @@ type textBox struct { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (backend *Backend) NewTextBox() tomo.TextBox { | func (backend *Backend) NewTextBox() tomo.TextBox { | ||||||
| 	box := &textBox { | 	this := &textBox { | ||||||
| 		box:       backend.NewBox().(*box), |  | ||||||
| 		textColor: color.Black, | 		textColor: color.Black, | ||||||
| 		dotColor:  color.RGBA { B: 255, G: 255, A: 255 }, | 		dotColor:  color.RGBA { B: 255, G: 255, A: 255 }, | ||||||
| 	} | 	} | ||||||
| 	box.box.drawer = box | 	this.box = backend.newBox(this) | ||||||
| 	box.outer  = box | 	return this | ||||||
| 	return box |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *textBox) SetOverflow (horizontal, vertical bool) { | func (this *textBox) SetOverflow (horizontal, vertical bool) { | ||||||
| @ -74,7 +72,7 @@ func (this *textBox) SetText (text string) { | |||||||
| 	if this.text == text { return } | 	if this.text == text { return } | ||||||
| 	this.text = text | 	this.text = text | ||||||
| 	this.drawer.SetText([]rune(text)) | 	this.drawer.SetText([]rune(text)) | ||||||
| 	this.recalculateMinimumSize() | 	this.invalidateMinimum() | ||||||
| 	this.invalidateLayout() | 	this.invalidateLayout() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -88,14 +86,14 @@ func (this *textBox) SetFace (face font.Face) { | |||||||
| 	if this.face == face { return } | 	if this.face == face { return } | ||||||
| 	this.face = face | 	this.face = face | ||||||
| 	this.drawer.SetFace(face) | 	this.drawer.SetFace(face) | ||||||
| 	this.recalculateMinimumSize() | 	this.invalidateMinimum() | ||||||
| 	this.invalidateLayout() | 	this.invalidateLayout() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *textBox) SetWrap (wrap bool) { | func (this *textBox) SetWrap (wrap bool) { | ||||||
| 	if this.wrap == wrap { return } | 	if this.wrap == wrap { return } | ||||||
| 	this.drawer.SetWrap(wrap) | 	this.drawer.SetWrap(wrap) | ||||||
| 	this.recalculateMinimumSize() | 	this.invalidateMinimum() | ||||||
| 	this.invalidateLayout() | 	this.invalidateLayout() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -271,7 +269,7 @@ func (this *textBox) normalizedLayoutBoundsSpace () image.Rectangle { | |||||||
| 	return bounds.Sub(bounds.Min) | 	return bounds.Sub(bounds.Min) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *textBox) recalculateMinimumSize () { | func (this *textBox) contentMinimum () image.Point { | ||||||
| 	minimum := image.Pt ( | 	minimum := image.Pt ( | ||||||
| 		this.drawer.Em().Round(), | 		this.drawer.Em().Round(), | ||||||
| 		this.drawer.LineHeight().Round()) | 		this.drawer.LineHeight().Round()) | ||||||
| @ -283,13 +281,8 @@ func (this *textBox) recalculateMinimumSize () { | |||||||
| 	if !this.vOverflow { | 	if !this.vOverflow { | ||||||
| 		 minimum.Y = textSize.Y | 		 minimum.Y = textSize.Y | ||||||
| 	} | 	} | ||||||
| 	 | 
 | ||||||
| 	minimum.X += this.padding.Horizontal() | 	return minimum.Add(this.box.contentMinimum()) | ||||||
| 	minimum.Y += this.padding.Vertical() |  | ||||||
| 	borderSum := this.borderSum() |  | ||||||
| 	minimum.X += borderSum.Horizontal() |  | ||||||
| 	minimum.Y += borderSum.Vertical() |  | ||||||
| 	this.SetMinimumSize(minimum) |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (this *textBox) doLayout () { | func (this *textBox) doLayout () { | ||||||
|  | |||||||
							
								
								
									
										31
									
								
								window.go
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								window.go
									
									
									
									
									
								
							| @ -46,9 +46,17 @@ type window struct { | |||||||
| 	focused anyBox | 	focused anyBox | ||||||
| 	hovered anyBox | 	hovered anyBox | ||||||
| 
 | 
 | ||||||
| 	needDraw   boxSet | 	// TODO: needMinimum and needLayout should be priority queues. for the | ||||||
| 	needLayout boxSet | 	// minimums, we need to start at the deeper parts of the layout tree and | ||||||
| 	needRedo   bool | 	// go upward towards the top. for the layouts, we need to start at the | ||||||
|  | 	// top of the layout tree and progressively go deeper. this will | ||||||
|  | 	// eliminate redundant layout calculations. | ||||||
|  | 
 | ||||||
|  | 	needMinimum  boxSet | ||||||
|  | 	needLayout   boxSet | ||||||
|  | 	needDraw     boxSet | ||||||
|  | 	needRedo     bool | ||||||
|  | 	minimumClean bool | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (backend *Backend) NewWindow ( | func (backend *Backend) NewWindow ( | ||||||
| @ -130,7 +138,7 @@ func (backend *Backend) newWindow ( | |||||||
| 		// Connect(backend.x, window.xWindow.Id) | 		// Connect(backend.x, window.xWindow.Id) | ||||||
| 	 | 	 | ||||||
| 	window.metrics.bounds = bounds | 	window.metrics.bounds = bounds | ||||||
| 	window.setMinimumSize(image.Pt(8, 8)) | 	window.doMinimumSize() | ||||||
| 
 | 
 | ||||||
| 	backend.windows[window.xWindow.Id] = window | 	backend.windows[window.xWindow.Id] = window | ||||||
| 
 | 
 | ||||||
| @ -353,15 +361,14 @@ func (window *window) pushRegion (region image.Rectangle) { | |||||||
| 	subCanvas.(*xcanvas.Canvas).Push(window.xWindow.Id) | 	subCanvas.(*xcanvas.Canvas).Push(window.xWindow.Id) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (window *window) recalculateMinimumSize () { | func (window *window) doMinimumSize () { | ||||||
| 	rootMinimum := image.Point { } | 	window.minimumClean = true | ||||||
| 	if window.root != nil { |  | ||||||
| 		rootMinimum = window.root.MinimumSize() |  | ||||||
| 	} |  | ||||||
| 	window.setMinimumSize(rootMinimum) |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| func (window *window) setMinimumSize (size image.Point) { | 	size := image.Point { } | ||||||
|  | 	if window.root != nil { | ||||||
|  | 		size = window.root.MinimumSize() | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
| 	if size.X < 8 { size.X = 8 } | 	if size.X < 8 { size.X = 8 } | ||||||
| 	if size.Y < 8 { size.Y = 8 } | 	if size.Y < 8 { size.Y = 8 } | ||||||
| 	icccm.WmNormalHintsSet ( | 	icccm.WmNormalHintsSet ( | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user