Compare commits

..

4 Commits

Author SHA1 Message Date
1596d54834 Fix up objects code 2024-06-11 17:17:11 -04:00
95d3dc3288 Add placeholder methods for recommended sizes 2024-06-11 17:12:18 -04:00
1069ae6455 Removed cut layout
Not a very good implementation
2024-06-11 16:58:38 -04:00
5c8358fc4a Add blank vars to ensure layouts satisfy tomo.Layout 2024-06-11 16:46:04 -04:00
8 changed files with 62 additions and 176 deletions

View File

@ -28,7 +28,6 @@ func newContainer (layout tomo.Layout, children ...tomo.Object) *Container {
func NewOuterContainer (layout tomo.Layout, children ...tomo.Object) *Container {
this := newContainer(layout, children...)
this.SetRole(tomo.R("objects", "Container", "outer"))
tomo.Apply(this)
return this
}
@ -37,7 +36,6 @@ func NewOuterContainer (layout tomo.Layout, children ...tomo.Object) *Container
func NewSunkenContainer (layout tomo.Layout, children ...tomo.Object) *Container {
this := newContainer(layout, children...)
this.SetRole(tomo.R("objects", "Container", "sunken"))
tomo.Apply(this)
return this
}
@ -45,7 +43,6 @@ func NewSunkenContainer (layout tomo.Layout, children ...tomo.Object) *Container
func NewInnerContainer (layout tomo.Layout, children ...tomo.Object) *Container {
this := newContainer(layout, children...)
this.SetRole(tomo.R("objects", "Container", "inner"))
tomo.Apply(this)
return this
}

View File

@ -3,6 +3,8 @@ package layouts
import "image"
import "git.tebibyte.media/tomo/tomo"
var _ tomo.Layout = ContractVertical
// Contract is a layout that arranges boxes in a simple row or column according
// to their minimum sizes.
type Contract bool
@ -40,6 +42,7 @@ func (contract Contract) MinimumSize (hints tomo.LayoutHints, boxes []tomo.Box)
}
func (contract Contract) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
// TODO if we overflow in a direction, respect the reccomended size
if contract.v() {
dot := hints.Bounds.Min
for index, box := range boxes {
@ -91,5 +94,15 @@ func (contract Contract) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
}
}
func (contract Contract) RecommendedHeight (hints tomo.LayoutHints, boxes []tomo.Box, width int) int {
// TODO
return 0
}
func (contract Contract) RecommendedWidth (hints tomo.LayoutHints, boxes []tomo.Box, height int) int {
// TODO
return 0
}
func (contract Contract) v () bool { return contract == ContractVertical }
func (contract Contract) h () bool { return contract == ContractHorizontal }

View File

@ -1,173 +0,0 @@
package layouts
import "image"
import "git.tebibyte.media/tomo/tomo"
// Cut is a layout that can be divided into smaller and smaller sections.
type Cut struct {
branches []*Cut
expand []bool
vertical bool
}
// NewCut creates and returns a new Cut layout.
func NewCut () *Cut {
return new(Cut)
}
// Vertical divides the layout vertically. Sections are specified using
// booleans. If a section is true, it will expand. If false, it will contract.
func (this *Cut) Vertical (expand ...bool) {
this.expand = expand
this.vertical = true
this.fill()
}
// Horizontal divides the layout horizontally. Sections are specified using
// booleans. If a section is true, it will expand. If false, it will contract.
func (this *Cut) Horizontal (expand ...bool) {
this.expand = expand
this.vertical = false
this.fill()
}
// At returns the section of this layout at the specified index.
func (this *Cut) At (index int) *Cut {
return this.branches[index]
}
func (this *Cut) real () bool {
return this != nil && this.branches != nil
}
func (this *Cut) fill () {
this.branches = make([]*Cut, len(this.expand))
for index := range this.branches {
this.branches[index] = new(Cut)
}
}
func (this *Cut) MinimumSize (hints tomo.LayoutHints, boxes []tomo.Box) image.Point {
size, _ := this.minimumSize(hints, boxes)
return size
}
func (this *Cut) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
this.arrange(hints, boxes)
}
func (this *Cut) minimumSize (hints tomo.LayoutHints, boxes []tomo.Box) (image.Point, []tomo.Box) {
size := image.Point { }
for index, branch := range this.branches {
if len(boxes) == 0 { break }
var point image.Point
if branch.real() {
point, boxes = branch.minimumSize(hints, boxes)
} else {
point = boxes[0].MinimumSize()
boxes = boxes[1:]
}
if this.vertical {
if point.X > size.X { size.X = point.X }
if index > 0 { size.Y += hints.Gap.Y }
size.Y += point.Y
} else {
if point.Y > size.Y { size.Y = point.Y }
if index > 0 { size.X += hints.Gap.X }
size.X += point.X
}
}
return size, boxes
}
func (this *Cut) arrange (hints tomo.LayoutHints, boxes []tomo.Box) []tomo.Box {
nChildren := len(this.branches)
// collect minimum sizes and physical endpoints
var minimums = make([]image.Point, nChildren)
var leaves = make([]tomo.Box, nChildren)
var nBranches int
remaining := boxes
for index, branch := range this.branches {
if branch.real() {
minimums[index], remaining = branch.minimumSize(hints, remaining)
} else {
if len(remaining) == 0 { break }
leaves[index] = remaining[0]
minimums[index] = remaining[0].MinimumSize()
remaining = remaining[1:]
}
nBranches ++
}
// determine the amount of space to divide among expanding branches
gaps := nBranches - 1
var freeSpace float64; if this.vertical {
freeSpace = float64(hints.Bounds.Dy() - hints.Gap.Y * gaps)
} else {
freeSpace = float64(hints.Bounds.Dx() - hints.Gap.X * gaps)
}
var nExpanding float64
for index, minimum := range minimums {
if this.expand[index] {
nExpanding ++
} else if this.vertical {
freeSpace -= float64(minimum.Y)
} else {
freeSpace -= float64(minimum.X)
}
}
expandingSize := freeSpace / nExpanding
// calculate the size and position of branches
var bounds = make([]image.Rectangle, nChildren)
x := float64(hints.Bounds.Min.X)
y := float64(hints.Bounds.Min.Y)
for index, minimum := range minimums {
// get size along significant axis
var size float64; if this.expand[index] {
size = expandingSize
} else if this.vertical {
size = float64(minimum.Y)
} else {
size = float64(minimum.X)
}
// figure out bounds from size
if this.vertical {
bounds[index].Max = image.Pt (
int(hints.Bounds.Dx()),
int(size))
} else {
bounds[index].Max = image.Pt (
int(size),
int(hints.Bounds.Dy()))
}
bounds[index] = bounds[index].Add(image.Pt(int(x), int(y)))
// move along
if this.vertical {
y += float64(hints.Gap.Y) + size
} else {
x += float64(hints.Gap.X) + size
}
}
// apply the size and position
for index, bound := range bounds {
if leaves[index] != nil {
leaves[index].SetBounds(bound)
boxes = boxes[1:]
} else if this.branches[index] != nil {
newHints := hints
newHints.Bounds = bound
boxes = this.branches[index].arrange(newHints, boxes)
}
}
return boxes
}

View File

@ -3,6 +3,8 @@ package layouts
import "image"
import "git.tebibyte.media/tomo/tomo"
var _ tomo.Layout = FlowVertical
// Flow is a grid layout where the number of rows and columns changes depending
// on the size of the container. It is designed to be used with an overflowing
// container. If the container does not overflow in the correct direction, the
@ -121,3 +123,13 @@ func (flow Flow) deltaMinor (rectangle image.Rectangle) int {
func (flow Flow) fallback () tomo.Layout {
return Contract(flow)
}
func (flow Flow) RecommendedHeight (hints tomo.LayoutHints, boxes []tomo.Box, width int) int {
// TODO
return 0
}
func (flow Flow) RecommendedWidth (hints tomo.LayoutHints, boxes []tomo.Box, height int) int {
// TODO
return 0
}

View File

@ -4,6 +4,8 @@ import "math"
import "image"
import "git.tebibyte.media/tomo/tomo"
var _ tomo.Layout = new(Grid)
// Grid is a layout that arranges boxes in a grid formation with distinct rows
// and columns. It is great for creating forms.
type Grid struct {
@ -106,3 +108,13 @@ func expand (hints tomo.LayoutHints, sizes []int, space int, expands func (int)
func ceilDiv (x, y int) int {
return int(math.Ceil(float64(x) / float64(y)))
}
func (this *Grid) RecommendedHeight (hints tomo.LayoutHints, boxes []tomo.Box, width int) int {
// TODO
return 0
}
func (this *Grid) RecommendedWidth (hints tomo.LayoutHints, boxes []tomo.Box, height int) int {
// TODO
return 0
}

View File

@ -335,6 +335,14 @@ func (this scrollbarLayout) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
}
func (this scrollbarLayout) RecommendedHeight (tomo.LayoutHints, []tomo.Box, int) int {
return 0
}
func (this scrollbarLayout) RecommendedWidth (tomo.LayoutHints, []tomo.Box, int) int {
return 0
}
func (this scrollbarLayout) viewportContentRatio () float64 {
if this.linked == nil { return 0 }
return this.viewportLength() / this.contentLength()

View File

@ -133,6 +133,7 @@ func (this *ScrollContainer) handleScroll (x, y float64) {
Sub(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
@ -183,6 +184,14 @@ func (this *scrollContainerLayout) Arrange (hints tomo.LayoutHints, boxes []tomo
}
}
func (this *scrollContainerLayout) RecommendedHeight (tomo.LayoutHints, []tomo.Box, int) int {
return 0
}
func (this *scrollContainerLayout) RecommendedWidth (tomo.LayoutHints, []tomo.Box, int) int {
return 0
}
func max (x, y int) int {
if x > y { return x }
return y

View File

@ -238,3 +238,11 @@ func (this sliderLayout) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
Add(gutter.Min))
}
}
func (this sliderLayout) RecommendedHeight (tomo.LayoutHints, []tomo.Box, int) int {
return 0
}
func (this sliderLayout) RecommendedWidth (tomo.LayoutHints, []tomo.Box, int) int {
return 0
}