Compare commits
No commits in common. "1efb94695365eaff3b0e4926b574dd4b6e263e00" and "d01d39569be1f1427dbde6b4c31cb7d1d7cefb99" have entirely different histories.
1efb946953
...
d01d39569b
@ -19,7 +19,7 @@ func NewCheckbox (value bool) *Checkbox {
|
|||||||
Box: tomo.NewBox(),
|
Box: tomo.NewBox(),
|
||||||
}
|
}
|
||||||
box.SetRole(tomo.R("objects", "Checkbox", ""))
|
box.SetRole(tomo.R("objects", "Checkbox", ""))
|
||||||
box.SetValue(value)
|
box.SetValue(false)
|
||||||
|
|
||||||
box.OnMouseUp(box.handleMouseUp)
|
box.OnMouseUp(box.handleMouseUp)
|
||||||
box.OnKeyUp(box.handleKeyUp)
|
box.OnKeyUp(box.handleKeyUp)
|
||||||
|
@ -1,106 +0,0 @@
|
|||||||
package internal
|
|
||||||
|
|
||||||
type HSVA struct {
|
|
||||||
H float64
|
|
||||||
S float64
|
|
||||||
V float64
|
|
||||||
A uint8
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hsva HSVA) RGBA () (r, g, b, a uint32) {
|
|
||||||
// Adapted from:
|
|
||||||
// https://www.cs.rit.edu/~ncs/color/t_convert.html
|
|
||||||
|
|
||||||
component := func (x float64) uint32 {
|
|
||||||
return uint32(float64(0xFFFF) * x)
|
|
||||||
}
|
|
||||||
|
|
||||||
ca := uint32(hsva.A) << 8
|
|
||||||
s := clamp01(hsva.S)
|
|
||||||
v := clamp01(hsva.V)
|
|
||||||
if s == 0 {
|
|
||||||
light := component(v)
|
|
||||||
return light, light, light, ca
|
|
||||||
}
|
|
||||||
|
|
||||||
h := clamp01(hsva.H) * 360
|
|
||||||
sector := int(h / 60)
|
|
||||||
offset := (h / 60) - float64(sector)
|
|
||||||
|
|
||||||
fac := float64(hsva.A) / 255
|
|
||||||
p := component(fac * v * (1 - s))
|
|
||||||
q := component(fac * v * (1 - s * offset))
|
|
||||||
t := component(fac * v * (1 - s * (1 - offset)))
|
|
||||||
va := component(v)
|
|
||||||
|
|
||||||
switch sector {
|
|
||||||
case 0: return va, t, p, ca
|
|
||||||
case 1: return q, va, p, ca
|
|
||||||
case 2: return p, va, t, ca
|
|
||||||
case 3: return p, q, va, ca
|
|
||||||
case 4: return t, p, va, ca
|
|
||||||
default: return va, p, q, ca
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Canon returns the color but with the H, S, and V fields are constrained to
|
|
||||||
// the range 0.0-1.0
|
|
||||||
func (hsva HSVA) Canon () HSVA {
|
|
||||||
hsva.H = clamp01(hsva.H)
|
|
||||||
hsva.S = clamp01(hsva.S)
|
|
||||||
hsva.V = clamp01(hsva.V)
|
|
||||||
return hsva
|
|
||||||
}
|
|
||||||
|
|
||||||
func clamp01 (x float64) float64 {
|
|
||||||
if x > 1.0 { return 1.0 }
|
|
||||||
if x < 0.0 { return 0.0 }
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
func RGBAToHSVA (r, g, b, a uint32) HSVA {
|
|
||||||
// Adapted from:
|
|
||||||
// https://www.cs.rit.edu/~ncs/color/t_convert.html
|
|
||||||
|
|
||||||
// FIXME: this does not always work!
|
|
||||||
|
|
||||||
component := func (x uint32) float64 {
|
|
||||||
return clamp01(float64(x) / 0xFFFF)
|
|
||||||
}
|
|
||||||
cr := component(r)
|
|
||||||
cg := component(g)
|
|
||||||
cb := component(b)
|
|
||||||
|
|
||||||
var maxComponent float64
|
|
||||||
if cr > maxComponent { maxComponent = cr }
|
|
||||||
if cg > maxComponent { maxComponent = cg }
|
|
||||||
if cb > maxComponent { maxComponent = cb }
|
|
||||||
var minComponent = 1.0
|
|
||||||
if cr < minComponent { minComponent = cr }
|
|
||||||
if cg < minComponent { minComponent = cg }
|
|
||||||
if cb < minComponent { minComponent = cb }
|
|
||||||
|
|
||||||
hsva := HSVA {
|
|
||||||
V: maxComponent,
|
|
||||||
A: uint8(a >> 8),
|
|
||||||
}
|
|
||||||
|
|
||||||
delta := maxComponent - minComponent
|
|
||||||
if maxComponent == 0 {
|
|
||||||
// hsva.S is undefined, so hue doesn't matter
|
|
||||||
return hsva
|
|
||||||
}
|
|
||||||
hsva.S = delta / maxComponent
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case cr == maxComponent: hsva.H = (cg - cb) / delta
|
|
||||||
case cg == maxComponent: hsva.H = 2 + (cb - cr) / delta
|
|
||||||
case cb == maxComponent: hsva.H = 4 + (cr - cg) / delta
|
|
||||||
}
|
|
||||||
|
|
||||||
hsva.H *= 60
|
|
||||||
if hsva.H < 0 { hsva.H += 360 }
|
|
||||||
hsva.H /= 360
|
|
||||||
|
|
||||||
return hsva
|
|
||||||
}
|
|
@ -106,14 +106,15 @@ func expand (hints tomo.LayoutHints, sizes []int, space int, expands func (int)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ceilDiv (x, y int) int {
|
func ceilDiv (x, y int) int {
|
||||||
if y == 0 { return 0 }
|
|
||||||
return int(math.Ceil(float64(x) / float64(y)))
|
return int(math.Ceil(float64(x) / float64(y)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Grid) RecommendedHeight (hints tomo.LayoutHints, boxes []tomo.Box, width int) int {
|
func (this *Grid) RecommendedHeight (hints tomo.LayoutHints, boxes []tomo.Box, width int) int {
|
||||||
return this.MinimumSize(hints, boxes).Y
|
// TODO
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Grid) RecommendedWidth (hints tomo.LayoutHints, boxes []tomo.Box, height int) int {
|
func (this *Grid) RecommendedWidth (hints tomo.LayoutHints, boxes []tomo.Box, height int) int {
|
||||||
return this.MinimumSize(hints, boxes).X
|
// TODO
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
@ -1,126 +0,0 @@
|
|||||||
package objects
|
|
||||||
|
|
||||||
import "git.tebibyte.media/tomo/tomo"
|
|
||||||
import "git.tebibyte.media/tomo/tomo/input"
|
|
||||||
import "git.tebibyte.media/tomo/objects/layouts"
|
|
||||||
|
|
||||||
type TabbedContainer struct {
|
|
||||||
tomo.ContainerBox
|
|
||||||
|
|
||||||
leftSpacer tomo.Box
|
|
||||||
rightSpacer tomo.Box
|
|
||||||
tabsRow tomo.ContainerBox
|
|
||||||
active string
|
|
||||||
tabs []*tab
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewTabbedContainer () *TabbedContainer {
|
|
||||||
container := &TabbedContainer {
|
|
||||||
ContainerBox: tomo.NewContainerBox(),
|
|
||||||
}
|
|
||||||
container.SetRole(tomo.R("objects", "TabbedContainer", ""))
|
|
||||||
container.SetLayout(layouts.Column { false, true } )
|
|
||||||
|
|
||||||
container.tabsRow = tomo.NewContainerBox()
|
|
||||||
container.tabsRow.SetRole(tomo.R("objects", "TabRow", ""))
|
|
||||||
container.Add(container.tabsRow)
|
|
||||||
|
|
||||||
container.leftSpacer = tomo.NewBox()
|
|
||||||
container.leftSpacer.SetRole(tomo.R("objects", "TabSpacer", "left"))
|
|
||||||
container.rightSpacer = tomo.NewBox()
|
|
||||||
container.rightSpacer.SetRole(tomo.R("objects", "TabSpacer", "right"))
|
|
||||||
|
|
||||||
container.ClearTabs()
|
|
||||||
container.setTabRowLayout()
|
|
||||||
return container
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *TabbedContainer) Activate (name string) {
|
|
||||||
if _, tab := this.findTab(this.active); tab != nil {
|
|
||||||
tab.setActive(false)
|
|
||||||
this.Remove(tab.root)
|
|
||||||
}
|
|
||||||
if _, tab := this.findTab(name); tab != nil {
|
|
||||||
tab.setActive(true)
|
|
||||||
this.Add(tab.root)
|
|
||||||
} else {
|
|
||||||
name = ""
|
|
||||||
}
|
|
||||||
this.active = name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *TabbedContainer) AddTab (name string, root tomo.Object) {
|
|
||||||
tab := &tab {
|
|
||||||
TextBox: tomo.NewTextBox(),
|
|
||||||
name: name,
|
|
||||||
root: root,
|
|
||||||
}
|
|
||||||
tab.SetRole(tomo.R("objects", "Tab", ""))
|
|
||||||
tab.SetText(name)
|
|
||||||
tab.OnMouseDown(func (button input.Button) {
|
|
||||||
if button != input.ButtonLeft { return }
|
|
||||||
this.Activate(name)
|
|
||||||
})
|
|
||||||
|
|
||||||
this.tabs = append(this.tabs, tab)
|
|
||||||
this.tabsRow.Insert(tab, this.rightSpacer)
|
|
||||||
this.setTabRowLayout()
|
|
||||||
|
|
||||||
// if the row was empty before, activate this tab
|
|
||||||
if len(this.tabs) == 1 {
|
|
||||||
this.Activate(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *TabbedContainer) RemoveTab (name string) {
|
|
||||||
index, tab := this.findTab(name)
|
|
||||||
if index < 0 { return }
|
|
||||||
nextIndex := index - 1
|
|
||||||
|
|
||||||
this.tabsRow.Remove(tab)
|
|
||||||
this.tabs = append(this.tabs[:index], this.tabs[index - 1:]...)
|
|
||||||
this.setTabRowLayout()
|
|
||||||
|
|
||||||
if nextIndex < 0 { nextIndex = 0 }
|
|
||||||
if nextIndex >= len(this.tabs) { nextIndex = len(this.tabs) - 1 }
|
|
||||||
if nextIndex < 0 {
|
|
||||||
this.Activate("")
|
|
||||||
} else {
|
|
||||||
this.Activate(this.tabs[nextIndex].name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *TabbedContainer) ClearTabs () {
|
|
||||||
this.tabs = nil
|
|
||||||
this.tabsRow.Clear()
|
|
||||||
this.tabsRow.Add(this.leftSpacer)
|
|
||||||
this.tabsRow.Add(this.rightSpacer)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *TabbedContainer) setTabRowLayout () {
|
|
||||||
row := make(layouts.Row, 1 + len(this.tabs) + 1)
|
|
||||||
row[len(row) - 1] = true
|
|
||||||
this.tabsRow.SetLayout(row)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *TabbedContainer) findTab (name string) (int, *tab) {
|
|
||||||
for index, tab := range this.tabs {
|
|
||||||
if tab.name == name { return index, tab }
|
|
||||||
}
|
|
||||||
return -1, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type tab struct {
|
|
||||||
tomo.TextBox
|
|
||||||
name string
|
|
||||||
root tomo.Object
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *tab) setActive (active bool) {
|
|
||||||
if active {
|
|
||||||
this.SetRole(tomo.R("objects", "Tab", "active"))
|
|
||||||
} else {
|
|
||||||
this.SetRole(tomo.R("objects", "Tab", ""))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user