13 Commits

24 changed files with 333 additions and 296 deletions

View File

@@ -5,9 +5,9 @@ import "git.tebibyte.media/tomo/tomo/input"
import "git.tebibyte.media/tomo/tomo/event"
import "git.tebibyte.media/tomo/objects/layouts"
var buttonLayout = layouts.NewGrid([]bool { true }, []bool { true })
var iconButtonLayout = layouts.NewGrid([]bool { true }, []bool { true })
var bothButtonLayout = layouts.NewGrid([]bool { false, true }, []bool { true })
var buttonLayout = layouts.Row { true }
var iconButtonLayout = layouts.Row { true }
var bothButtonLayout = layouts.Row { false, true }
// Button is a clickable button.
type Button struct {
@@ -29,7 +29,6 @@ func NewButton (text string) *Button {
label: NewLabel(text),
}
box.SetRole(tomo.R("objects", "Button", ""))
tomo.Apply(box)
box.label.SetAlign(tomo.AlignMiddle, tomo.AlignMiddle)
box.SetLayout(buttonLayout)
box.SetText(text)

View File

@@ -19,7 +19,6 @@ func NewCheckbox (value bool) *Checkbox {
Box: tomo.NewBox(),
}
box.SetRole(tomo.R("objects", "Checkbox", ""))
tomo.Apply(box)
box.SetValue(false)
box.OnMouseUp(box.handleMouseUp)

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
}

2
go.mod
View File

@@ -2,6 +2,6 @@ module git.tebibyte.media/tomo/objects
go 1.20
require git.tebibyte.media/tomo/tomo v0.36.0
require git.tebibyte.media/tomo/tomo v0.38.0
require golang.org/x/image v0.11.0 // indirect

4
go.sum
View File

@@ -1,5 +1,5 @@
git.tebibyte.media/tomo/tomo v0.36.0 h1:V9vyPYb4kpUceBhcDF/XyLDACzE5lY8kYEGHAkIsqs0=
git.tebibyte.media/tomo/tomo v0.36.0/go.mod h1:C9EzepS9wjkTJjnZaPBh22YvVPyA4hbBAJVU20Rdmps=
git.tebibyte.media/tomo/tomo v0.38.0 h1:K5TP67RxnszudeNfmGZiU5cFTRjFueXiI3NCsgw+05U=
git.tebibyte.media/tomo/tomo v0.38.0/go.mod h1:C9EzepS9wjkTJjnZaPBh22YvVPyA4hbBAJVU20Rdmps=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=

View File

@@ -16,7 +16,6 @@ func NewHeading (level int, text string) *Heading {
if level > 2 { level = 2 }
this := &Heading { TextBox: tomo.NewTextBox() }
this.SetRole(tomo.R("objects", "Heading", fmt.Sprint(level)))
tomo.Apply(this)
this.SetText(text)
return this
}

View File

@@ -16,7 +16,6 @@ func NewIcon (id tomo.Icon, size tomo.IconSize) *Icon {
Box: tomo.NewBox(),
}
this.SetRole(tomo.R("objects", "Icon", size.String()))
tomo.Apply(this)
this.SetTexture(id.Texture(size))
return this
}
@@ -27,7 +26,6 @@ func NewMimeIcon (mime data.Mime, size tomo.IconSize) *Icon {
Box: tomo.NewBox(),
}
this.SetRole(tomo.R("objects", "Icon", size.String()))
tomo.Apply(this)
this.SetTexture(tomo.MimeIcon(mime, size))
return this
}

View File

@@ -11,7 +11,6 @@ type Label struct {
func NewLabel (text string) *Label {
this := &Label { TextBox: tomo.NewTextBox() }
this.SetRole(tomo.R("objects", "Label", ""))
tomo.Apply(this)
this.SetText(text)
return this
}

View File

@@ -21,7 +21,6 @@ func NewLabelCheckbox (value bool, text string) *LabelCheckbox {
label: NewLabel(text),
}
box.SetRole(tomo.R("objects", "LabelCheckbox", ""))
tomo.Apply(box)
box.label.SetAlign(tomo.AlignStart, tomo.AlignMiddle)
box.Add(box.checkbox)
box.Add(box.label)

40
layouts/contract.go Normal file
View File

@@ -0,0 +1,40 @@
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
// ContractVertical is a vertical contracted layout.
const ContractVertical Contract = true
// ContractHorizontal is a horizontal contracted layout.
const ContractHorizontal Contract = false
func (contract Contract) MinimumSize (hints tomo.LayoutHints, boxes []tomo.Box) image.Point {
return contract.fallback().MinimumSize(hints, boxes)
}
func (contract Contract) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
contract.fallback().Arrange(hints, boxes)
}
func (contract Contract) RecommendedHeight (hints tomo.LayoutHints, boxes []tomo.Box, width int) int {
return contract.fallback().RecommendedHeight(hints, boxes, width)
}
func (contract Contract) RecommendedWidth (hints tomo.LayoutHints, boxes []tomo.Box, height int) int {
return contract.fallback().RecommendedWidth(hints, boxes, height)
}
func (contract Contract) fallback () tomo.Layout {
if contract == ContractVertical {
return Column { }
} else {
return Row { }
}
}

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

@@ -1,95 +0,0 @@
package layouts
import "image"
import "git.tebibyte.media/tomo/tomo"
// Contract is a layout that arranges boxes in a simple row or column according
// to their minimum sizes.
type Contract bool
// ContractVertical is a vertical contracted layout.
const ContractVertical Contract = true
// ContractHorizontal is a horizontal contracted layout.
const ContractHorizontal Contract = false
func (contract Contract) MinimumSize (hints tomo.LayoutHints, boxes []tomo.Box) image.Point {
if contract.v() {
dot := image.Point { }
for _, box := range boxes {
minimum := box.MinimumSize()
dot.Y += minimum.Y
if dot.X < minimum.X {
dot.X = minimum.X
}
}
dot.Y += hints.Gap.Y * (len(boxes) - 1)
return dot
} else {
dot := image.Point { }
for _, box := range boxes {
minimum := box.MinimumSize()
dot.X += minimum.X
if dot.Y < minimum.Y {
dot.Y = minimum.Y
}
}
dot.X += hints.Gap.X * (len(boxes) - 1)
return dot
}
}
func (contract Contract) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
if contract.v() {
dot := hints.Bounds.Min
for index, box := range boxes {
if index > 0 { dot.Y += hints.Gap.Y }
minimum := box.MinimumSize()
box.SetBounds(image.Rectangle {
Min: dot,
Max: dot.Add(image.Pt(hints.Bounds.Dx(), minimum.Y)),
})
dot.Y += minimum.Y
}
height := dot.Y - hints.Bounds.Min.Y
offset := 0
switch hints.AlignY {
case tomo.AlignMiddle:
offset = (hints.Bounds.Dy() - height) / 2
case tomo.AlignEnd:
offset = hints.Bounds.Dy() - height
}
for _, box := range boxes {
box.SetBounds(box.Bounds().Add(image.Pt(0, offset)))
}
} else {
dot := hints.Bounds.Min
for index, box := range boxes {
if index > 0 { dot.X += hints.Gap.X }
minimum := box.MinimumSize()
box.SetBounds(image.Rectangle {
Min: dot,
Max: dot.Add(image.Pt(minimum.X, hints.Bounds.Dy())),
})
dot.X += minimum.X
}
width := dot.X - hints.Bounds.Min.X
offset := 0
switch hints.AlignX {
case tomo.AlignMiddle:
offset = (hints.Bounds.Dx() - width) / 2
case tomo.AlignEnd:
offset = hints.Bounds.Dx() - width
}
for _, box := range boxes {
box.SetBounds(box.Bounds().Add(image.Pt(offset, 0)))
}
}
}
func (contract Contract) v () bool { return contract == ContractVertical }
func (contract Contract) h () bool { return contract == ContractHorizontal }

238
layouts/rowcol.go Normal file
View File

@@ -0,0 +1,238 @@
package layouts
import "image"
import "git.tebibyte.media/tomo/tomo"
var _ tomo.Layout = ContractVertical
// Row arranges boxes in a row. Boxes that share an index with a true value will
// expand, and others will contract.
type Row []bool
// Column arranges boxes in a column. Boxes that share an index with a true
// value will expand, and others will contract.
type Column []bool
func (column Column) MinimumSize (hints tomo.LayoutHints, boxes []tomo.Box) image.Point {
dot := image.Point { }
for _, box := range boxes {
minimum := box.MinimumSize()
dot.Y += minimum.Y
if dot.X < minimum.X {
dot.X = minimum.X
}
}
dot.Y += hints.Gap.Y * (len(boxes) - 1)
return dot
}
func (row Row) MinimumSize (hints tomo.LayoutHints, boxes []tomo.Box) image.Point {
dot := image.Point { }
for _, box := range boxes {
minimum := box.MinimumSize()
dot.X += minimum.X
if dot.Y < minimum.Y {
dot.Y = minimum.Y
}
}
dot.X += hints.Gap.X * (len(boxes) - 1)
return dot
}
func (column Column) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
expands := func (index int) bool {
if index >= len(column) { return false }
return column[index]
}
// determine expanding box size
expandingSize := 0.0
if !hints.OverflowY {
gaps := len(boxes) - 1
freeSpace := float64(hints.Bounds.Dy() - hints.Gap.Y * gaps)
nExpanding := 0; for index, box := range boxes {
if expands(index) {
nExpanding ++
} else {
freeSpace -= float64(box.MinimumSize().Y)
}
}
expandingSize = freeSpace / float64(nExpanding)
}
// determine width
width := 0
if hints.OverflowX {
for _, box := range boxes {
minimum := box.MinimumSize()
if width < minimum.X { width = minimum.X }
}
} else {
width = hints.Bounds.Dx()
}
// arrange
dot := hints.Bounds.Min
for index, box := range boxes {
if index > 0 { dot.Y += hints.Gap.Y }
// determine height
height := box.MinimumSize().Y
if hints.OverflowY {
if box, ok := box.(tomo.ContentBox); ok {
height = box.RecommendedHeight(width)
}
} else {
if expands(index) {
height = int(expandingSize)
}
}
// set bounds
box.SetBounds(image.Rectangle {
Min: dot,
Max: dot.Add(image.Pt(width, height)),
})
dot.Y += height
}
height := dot.Y - hints.Bounds.Min.Y
offset := 0
switch hints.AlignY {
case tomo.AlignMiddle:
offset = (hints.Bounds.Dy() - height) / 2
case tomo.AlignEnd:
offset = hints.Bounds.Dy() - height
}
for _, box := range boxes {
box.SetBounds(box.Bounds().Add(image.Pt(0, offset)))
}
}
func (row Row) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
expands := func (index int) bool {
if index >= len(row) { return false }
return row[index]
}
// determine expanding box size
expandingSize := 0.0
if !hints.OverflowY {
gaps := len(boxes) - 1
freeSpace := float64(hints.Bounds.Dx() - hints.Gap.X * gaps)
nExpanding := 0; for index, box := range boxes {
if expands(index) {
nExpanding ++
} else {
freeSpace -= float64(box.MinimumSize().X)
}
}
expandingSize = freeSpace / float64(nExpanding)
}
// determine height
height := 0
if hints.OverflowY {
for _, box := range boxes {
minimum := box.MinimumSize()
if height < minimum.Y { height = minimum.Y }
}
} else {
height = hints.Bounds.Dy()
}
// arrange
dot := hints.Bounds.Min
for index, box := range boxes {
if index > 0 { dot.X += hints.Gap.X }
// determine width
width := box.MinimumSize().X
if hints.OverflowY {
if box, ok := box.(tomo.ContentBox); ok {
width = box.RecommendedHeight(height)
}
} else {
if expands(index) {
width = int(expandingSize)
}
}
// set bounds
box.SetBounds(image.Rectangle {
Min: dot,
Max: dot.Add(image.Pt(width, height)),
})
dot.X += width
}
width := dot.X - hints.Bounds.Min.X
offset := 0
switch hints.AlignX {
case tomo.AlignMiddle:
offset = (hints.Bounds.Dx() - width) / 2
case tomo.AlignEnd:
offset = hints.Bounds.Dx() - width
}
for _, box := range boxes {
box.SetBounds(box.Bounds().Add(image.Pt(offset, 0)))
}
}
func (column Column) RecommendedHeight (hints tomo.LayoutHints, boxes []tomo.Box, width int) int {
height := 0
for _, box := range boxes {
if box, ok := box.(tomo.ContentBox); ok {
height += box.RecommendedHeight(width)
} else {
height += box.MinimumSize().Y
}
}
height += hints.Gap.Y * (len(boxes) - 1)
return height
}
func (row Row) RecommendedHeight (hints tomo.LayoutHints, boxes []tomo.Box, width int) int {
height := 0
for _, box := range boxes {
minimum := box.MinimumSize()
boxHeight := 0
if box, ok := box.(tomo.ContentBox); ok {
boxHeight = box.RecommendedHeight(minimum.X)
} else {
boxHeight = minimum.Y
}
if boxHeight > height { height = boxHeight }
}
return height
}
func (column Column) RecommendedWidth (hints tomo.LayoutHints, boxes []tomo.Box, height int) int {
width := 0
for _, box := range boxes {
minimum := box.MinimumSize()
boxWidth := 0
if box, ok := box.(tomo.ContentBox); ok {
boxWidth = box.RecommendedHeight(minimum.Y)
} else {
boxWidth = minimum.X
}
if boxWidth > width { width = boxWidth }
}
return width
}
func (row Row) RecommendedWidth (hints tomo.LayoutHints, boxes []tomo.Box, height int) int {
width := 0
for _, box := range boxes {
if box, ok := box.(tomo.ContentBox); ok {
width += box.RecommendedWidth(height)
} else {
width += box.MinimumSize().X
}
}
width += hints.Gap.X * (len(boxes) - 1)
return width
}

View File

@@ -41,7 +41,6 @@ func NewMenu (anchor tomo.Object, items ...tomo.Object) (*Menu, error) {
if !menu.torn {
menu.tearLine = tomo.NewBox()
menu.tearLine.SetRole(tomo.R("objects", "TearLine", ""))
tomo.Apply(menu.tearLine)
menu.tearLine.SetFocusable(true)
menu.tearLine.OnKeyUp(func (key input.Key, numberPad bool) {
if key != input.KeyEnter && key != input.Key(' ') { return }
@@ -67,7 +66,6 @@ func NewMenu (anchor tomo.Object, items ...tomo.Object) (*Menu, error) {
}
}
menu.rootContainer.SetRole(tomo.R("objects", "Container", "menu"))
tomo.Apply(menu.rootContainer)
menu.Window.SetRoot(menu.rootContainer)
return menu, nil

View File

@@ -26,7 +26,6 @@ func NewMenuItem (text string) *MenuItem {
icon: NewIcon("", tomo.IconSizeSmall),
}
box.SetRole(tomo.R("objects", "MenuItem", ""))
tomo.Apply(box)
box.label.SetAlign(tomo.AlignStart, tomo.AlignMiddle)
box.SetLayout(layouts.NewGrid([]bool { false, true }, []bool { true }))

View File

@@ -29,7 +29,6 @@ func NewNumberInput (value float64) *NumberInput {
decrement: NewButton(""),
}
box.SetRole(tomo.R("objects", "NumberInput", ""))
tomo.Apply(box)
box.Add(box.input)
box.Add(box.decrement)
box.Add(box.increment)

View File

@@ -47,9 +47,7 @@ func newScrollbar (orient string) *Scrollbar {
this.OnScroll(this.handleScroll)
this.handle.SetRole(tomo.R("objects", "SliderHandle", orient))
tomo.Apply(this.handle)
this.SetRole(tomo.R("objects", "Slider", orient))
tomo.Apply(this)
return this
}
@@ -337,6 +335,14 @@ func (this scrollbarLayout) Arrange (hints tomo.LayoutHints, boxes []tomo.Box) {
}
func (this scrollbarLayout) RecommendedHeight (hints tomo.LayoutHints, boxes []tomo.Box, width int) int {
return this.MinimumSize(hints, boxes).X
}
func (this scrollbarLayout) RecommendedWidth (hints tomo.LayoutHints, boxes []tomo.Box, height int) int {
return this.MinimumSize(hints, boxes).Y
}
func (this scrollbarLayout) viewportContentRatio () float64 {
if this.linked == nil { return 0 }
return this.viewportLength() / this.contentLength()

View File

@@ -61,7 +61,6 @@ func NewScrollContainer (sides ScrollSide) *ScrollContainer {
this.CaptureScroll(true)
this.OnScroll(this.handleScroll)
this.SetRole(tomo.R("objects", "ScrollContainer", sides.String()))
tomo.Apply(this)
this.SetLayout(this.layout)
return this
}
@@ -134,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
@@ -184,6 +184,14 @@ func (this *scrollContainerLayout) Arrange (hints tomo.LayoutHints, boxes []tomo
}
}
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

View File

@@ -13,6 +13,5 @@ func NewSeparator () *Separator {
Box: tomo.NewBox(),
}
this.SetRole(tomo.R("objects", "Separator", ""))
tomo.Apply(this)
return this
}

View File

@@ -53,9 +53,7 @@ func newSlider (orient string, value float64) *Slider {
this.OnScroll(this.handleScroll)
this.handle.SetRole(tomo.R("objects", "SliderHandle", orient))
tomo.Apply(this.handle)
this.SetRole(tomo.R("objects", "Slider", orient))
tomo.Apply(this)
return this
}
@@ -240,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
}

View File

@@ -20,7 +20,6 @@ type TextInput struct {
func NewTextInput (text string) *TextInput {
this := &TextInput { TextBox: tomo.NewTextBox() }
this.SetRole(tomo.R("objects", "TextInput", ""))
tomo.Apply(this)
this.SetAlign(tomo.AlignStart, tomo.AlignMiddle)
this.SetText(text)
this.SetFocusable(true)

View File

@@ -12,7 +12,6 @@ type TextView struct {
func NewTextView (text string) *TextView {
this := &TextView { TextBox: tomo.NewTextBox() }
this.SetRole(tomo.R("objects", "TextView", ""))
tomo.Apply(this)
this.SetFocusable(true)
this.SetSelectable(true)
this.SetText(text)