Update code for layouts, objects
This commit is contained in:
@@ -2,7 +2,9 @@ package objects
|
||||
|
||||
import "image"
|
||||
import "git.tebibyte.media/tomo/tomo"
|
||||
import "git.tebibyte.media/tomo/tomo/input"
|
||||
import "git.tebibyte.media/tomo/tomo/event"
|
||||
import "git.tebibyte.media/tomo/objects/layouts"
|
||||
|
||||
// ScrollSide determines which Scrollbars are active in a ScrollContainer.
|
||||
type ScrollSide int; const (
|
||||
@@ -38,8 +40,11 @@ func (sides ScrollSide) String () string {
|
||||
// ScrollContainer couples a ContentBox with one or two Scrollbars.
|
||||
type ScrollContainer struct {
|
||||
tomo.ContainerBox
|
||||
layout *scrollContainerLayout
|
||||
|
||||
root tomo.ContentObject
|
||||
horizontal *Scrollbar
|
||||
vertical *Scrollbar
|
||||
|
||||
horizontalCookie event.Cookie
|
||||
verticalCookie event.Cookie
|
||||
|
||||
@@ -52,22 +57,23 @@ type ScrollContainer struct {
|
||||
func NewScrollContainer (sides ScrollSide) *ScrollContainer {
|
||||
this := &ScrollContainer {
|
||||
ContainerBox: tomo.NewContainerBox(),
|
||||
layout: &scrollContainerLayout { },
|
||||
}
|
||||
if sides.Vertical() {
|
||||
this.layout.vertical = NewVerticalScrollbar()
|
||||
this.layout.vertical.OnValueChange(this.handleValueChange)
|
||||
this.Add(this.layout.vertical)
|
||||
this.vertical = NewVerticalScrollbar()
|
||||
this.vertical.OnValueChange(this.handleValueChange)
|
||||
this.Add(this.vertical)
|
||||
}
|
||||
if sides.Horizontal() {
|
||||
this.layout.horizontal = NewHorizontalScrollbar()
|
||||
this.layout.horizontal.OnValueChange(this.handleValueChange)
|
||||
this.Add(this.layout.horizontal)
|
||||
this.horizontal = NewHorizontalScrollbar()
|
||||
this.horizontal.OnValueChange(this.handleValueChange)
|
||||
this.Add(this.horizontal)
|
||||
}
|
||||
this.CaptureScroll(true)
|
||||
this.OnScroll(this.handleScroll)
|
||||
this.SetRole(tomo.R("objects", "ScrollContainer", sides.String()))
|
||||
this.SetLayout(this.layout)
|
||||
this.OnKeyDown(this.handleKeyDown)
|
||||
this.OnKeyUp(this.handleKeyUp)
|
||||
this.SetRole(tomo.R("objects", "ScrollContainer"))
|
||||
this.SetTag(sides.String(), true)
|
||||
this.SetLayout(layouts.NewGrid(true, false)(true, false))
|
||||
return this
|
||||
}
|
||||
|
||||
@@ -75,9 +81,9 @@ func NewScrollContainer (sides ScrollSide) *ScrollContainer {
|
||||
// a time, and setting it will remove and unlink the current child if there is
|
||||
// one.
|
||||
func (this *ScrollContainer) SetRoot (root tomo.ContentObject) {
|
||||
if this.layout.root != nil {
|
||||
if this.root != nil {
|
||||
// remove root and close cookies
|
||||
this.Remove(this.layout.root)
|
||||
this.Remove(this.root)
|
||||
if this.horizontalCookie != nil {
|
||||
this.horizontalCookie.Close()
|
||||
this.horizontalCookie = nil
|
||||
@@ -87,24 +93,24 @@ func (this *ScrollContainer) SetRoot (root tomo.ContentObject) {
|
||||
this.verticalCookie = nil
|
||||
}
|
||||
}
|
||||
this.layout.root = root
|
||||
this.root = root
|
||||
if root != nil {
|
||||
// insert root at the beginning (for keynav)
|
||||
switch {
|
||||
case this.layout.vertical != nil:
|
||||
this.Insert(root, this.layout.vertical)
|
||||
case this.layout.horizontal != nil:
|
||||
this.Insert(root, this.layout.horizontal)
|
||||
case this.vertical != nil:
|
||||
this.Insert(root, this.vertical)
|
||||
case this.horizontal != nil:
|
||||
this.Insert(root, this.horizontal)
|
||||
default:
|
||||
this.Add(root)
|
||||
}
|
||||
|
||||
// link root and remember cookies
|
||||
if this.layout.horizontal != nil {
|
||||
this.horizontalCookie = this.layout.horizontal.Link(root)
|
||||
if this.horizontal != nil {
|
||||
this.horizontalCookie = this.horizontal.Link(root)
|
||||
}
|
||||
if this.layout.vertical != nil {
|
||||
this.verticalCookie = this.layout.vertical.Link(root)
|
||||
if this.vertical != nil {
|
||||
this.verticalCookie = this.vertical.Link(root)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,11 +118,11 @@ func (this *ScrollContainer) SetRoot (root tomo.ContentObject) {
|
||||
// Value returns the horizontal and vertical scrollbar values where 0 is all the
|
||||
// way to the left/top, and 1 is all the way to the right/bottom.
|
||||
func (this *ScrollContainer) Value () (x, y float64) {
|
||||
if this.layout.horizontal != nil {
|
||||
x = this.layout.horizontal.Value()
|
||||
if this.horizontal != nil {
|
||||
x = this.horizontal.Value()
|
||||
}
|
||||
if this.layout.vertical != nil {
|
||||
y = this.layout.vertical.Value()
|
||||
if this.vertical != nil {
|
||||
y = this.vertical.Value()
|
||||
}
|
||||
return x, y
|
||||
}
|
||||
@@ -124,11 +130,11 @@ func (this *ScrollContainer) Value () (x, y float64) {
|
||||
// SetValue sets the horizontal and vertical scrollbar values where 0 is all the
|
||||
// way to the left/top, and 1 is all the way to the right/bottom.
|
||||
func (this *ScrollContainer) SetValue (x, y float64) {
|
||||
if this.layout.horizontal != nil {
|
||||
this.layout.horizontal.SetValue(x)
|
||||
if this.horizontal != nil {
|
||||
this.horizontal.SetValue(x)
|
||||
}
|
||||
if this.layout.vertical != nil {
|
||||
this.layout.vertical.SetValue(y)
|
||||
if this.vertical != nil {
|
||||
this.vertical.SetValue(y)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,77 +144,74 @@ func (this *ScrollContainer) OnValueChange (callback func ()) event.Cookie {
|
||||
return this.on.valueChange.Connect(callback)
|
||||
}
|
||||
|
||||
// PageSize returns the scroll distance of a page.
|
||||
func (this *ScrollContainer) PageSize () image.Point {
|
||||
page := image.Point { }
|
||||
if this.horizontal != nil {
|
||||
page.X = this.horizontal.PageSize()
|
||||
}
|
||||
if this.vertical != nil {
|
||||
page.Y = this.vertical.PageSize()
|
||||
}
|
||||
return page
|
||||
}
|
||||
|
||||
// StepSize returns the scroll distance of a step.
|
||||
func (this *ScrollContainer) StepSize () image.Point {
|
||||
page := image.Point { }
|
||||
if this.horizontal != nil {
|
||||
page.X = this.horizontal.StepSize()
|
||||
}
|
||||
if this.vertical != nil {
|
||||
page.Y = this.vertical.StepSize()
|
||||
}
|
||||
return page
|
||||
}
|
||||
|
||||
func (this *ScrollContainer) handleValueChange () {
|
||||
this.on.valueChange.Broadcast()
|
||||
}
|
||||
|
||||
func (this *ScrollContainer) handleScroll (x, y float64) {
|
||||
if this.layout.root == nil { return }
|
||||
this.layout.root.ScrollTo (
|
||||
this.layout.root.ContentBounds().Min.
|
||||
Sub(image.Pt(int(x), int(y))))
|
||||
func (this *ScrollContainer) handleScroll (catch func (), x, y float64) {
|
||||
catch()
|
||||
if this.root == nil { return }
|
||||
this.scrollBy(image.Pt(int(x), int(y)))
|
||||
}
|
||||
|
||||
// TODO: remove this and replace it with something from the layouts package
|
||||
type scrollContainerLayout struct {
|
||||
root tomo.ContentObject
|
||||
horizontal *Scrollbar
|
||||
vertical *Scrollbar
|
||||
func (this *ScrollContainer) scrollBy (vector image.Point) {
|
||||
if this.root == nil { return }
|
||||
this.root.ScrollTo (
|
||||
this.root.ContentBounds().Min.
|
||||
Sub(vector))
|
||||
}
|
||||
|
||||
func (this *scrollContainerLayout) MinimumSize (hints tomo.LayoutHints, boxes []tomo.Box) image.Point {
|
||||
var minimum image.Point; if this.root != nil {
|
||||
minimum = this.root.GetBox().MinimumSize()
|
||||
func (this *ScrollContainer) handleKeyDown (catch func (), key input.Key, numpad bool) {
|
||||
modifiers := this.Window().Modifiers()
|
||||
vector := image.Point { }
|
||||
switch key {
|
||||
case input.KeyPageUp:
|
||||
catch()
|
||||
if modifiers.Shift {
|
||||
vector.X -= this.PageSize().X
|
||||
} else {
|
||||
vector.Y -= this.PageSize().Y
|
||||
}
|
||||
case input.KeyPageDown:
|
||||
catch()
|
||||
if modifiers.Shift {
|
||||
vector.X += this.PageSize().X
|
||||
} else {
|
||||
vector.Y += this.PageSize().Y
|
||||
}
|
||||
}
|
||||
if this.horizontal != nil {
|
||||
minimum.Y += this.horizontal.MinimumSize().Y
|
||||
}
|
||||
if this.vertical != nil {
|
||||
minimum.X += this.vertical.MinimumSize().X
|
||||
minimum.Y = max(minimum.Y, this.vertical.MinimumSize().Y)
|
||||
}
|
||||
if this.horizontal != nil {
|
||||
minimum.X = max(minimum.X, this.horizontal.MinimumSize().X)
|
||||
}
|
||||
return minimum
|
||||
}
|
||||
|
||||
func (this *scrollContainerLayout) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
|
||||
rootBounds := hints.Bounds
|
||||
if this.horizontal != nil {
|
||||
rootBounds.Max.Y -= this.horizontal.MinimumSize().Y
|
||||
}
|
||||
if this.vertical != nil {
|
||||
rootBounds.Max.X -= this.vertical.MinimumSize().X
|
||||
}
|
||||
if this.root != nil {
|
||||
this.root.GetBox().SetBounds(rootBounds)
|
||||
}
|
||||
if this.horizontal != nil {
|
||||
this.horizontal.SetBounds(image.Rect (
|
||||
hints.Bounds.Min.X,
|
||||
rootBounds.Max.Y,
|
||||
rootBounds.Max.X,
|
||||
hints.Bounds.Max.Y))
|
||||
}
|
||||
if this.vertical != nil {
|
||||
this.vertical.SetBounds(image.Rect (
|
||||
rootBounds.Max.X,
|
||||
hints.Bounds.Min.Y,
|
||||
hints.Bounds.Max.X,
|
||||
rootBounds.Max.Y))
|
||||
if vector != (image.Point { }) {
|
||||
this.scrollBy(vector)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *scrollContainerLayout) RecommendedHeight (hints tomo.LayoutHints, boxes []tomo.Box, width int) int {
|
||||
return this.MinimumSize(hints, boxes).X
|
||||
}
|
||||
|
||||
func (this *scrollContainerLayout) RecommendedWidth (hints tomo.LayoutHints, boxes []tomo.Box, height int) int {
|
||||
return this.MinimumSize(hints, boxes).Y
|
||||
}
|
||||
|
||||
func max (x, y int) int {
|
||||
if x > y { return x }
|
||||
return y
|
||||
func (this *ScrollContainer) handleKeyUp (catch func (), key input.Key, numpad bool) {
|
||||
switch key {
|
||||
case input.KeyPageUp: catch()
|
||||
case input.KeyPageDown: catch()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user