Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e102c032cb | |||
| d35b0532a1 | |||
| dffe766328 | |||
| c1d77028b4 | |||
| 83b2c3c665 | |||
| 89307e0dd6 | |||
| 5d9c584743 | |||
| fd7d2b7ead | |||
| ca4d3e62c4 | |||
| d587e39506 | |||
| f0c092be8a | |||
| 06f45c80e2 | |||
| 71171d762c |
11
backend.go
11
backend.go
@@ -33,6 +33,17 @@ type Backend interface {
|
||||
// must reject any canvas that was not made by it.
|
||||
NewCanvas (image.Rectangle) canvas.CanvasCloser
|
||||
|
||||
// SetStyle sets the style that will be used on objects. The backend is
|
||||
// in charge of applying the style to objects. When this method is
|
||||
// called, it must propagate a StyleChange event to all boxes it is
|
||||
// keeping track of.
|
||||
SetStyle (Style)
|
||||
|
||||
// SetIcons sets the icon set that icons will be pulled from. When this
|
||||
// method is called, it must propagate an IconChange event to all boxes
|
||||
// it is keeping track of.
|
||||
SetIcons (Icons)
|
||||
|
||||
// Run runs the event loop until Stop() is called, or the backend
|
||||
// experiences a fatal error.
|
||||
Run () error
|
||||
|
||||
40
icon.go
40
icon.go
@@ -382,12 +382,44 @@ const (
|
||||
|
||||
// Texture returns a texture of the corresponding icon ID.
|
||||
func (id Icon) Texture (size IconSize) canvas.Texture {
|
||||
if theme == nil { return nil }
|
||||
return theme.Icon(id, size)
|
||||
if icons == nil { return nil }
|
||||
return icons.Icon(id, size)
|
||||
}
|
||||
|
||||
// MimeIcon returns an icon corresponding to a MIME type.
|
||||
func MimeIcon (mime data.Mime, size IconSize) canvas.Texture {
|
||||
if theme == nil { return nil }
|
||||
return theme.MimeIcon(mime, size)
|
||||
if icons == nil { return nil }
|
||||
return icons.MimeIcon(mime, size)
|
||||
}
|
||||
|
||||
// Icons holds a set of icon textures.
|
||||
type Icons interface {
|
||||
// A word on textures:
|
||||
//
|
||||
// Because textures can be linked to some resource that is outside of
|
||||
// the control of Go's garbage collector, methods of Icons must not
|
||||
// allocate new copies of a texture each time they are called. It is
|
||||
// fine to lazily load textures and save them for later use, but the
|
||||
// same texture must never be allocated multiple times as this could
|
||||
// cause a memory leak.
|
||||
//
|
||||
// As such, textures returned by these methods must be protected.
|
||||
|
||||
// Icon returns a texture of the corresponding icon ID. If there is no
|
||||
// suitable option, it should return nil.
|
||||
Icon (Icon, IconSize) canvas.Texture
|
||||
|
||||
// MimeIcon returns a texture of an icon corresponding to a MIME type.
|
||||
// If there is no suitable specific option, it should return a more
|
||||
// generic icon or a plain file icon.
|
||||
MimeIcon (data.Mime, IconSize) canvas.Texture
|
||||
}
|
||||
|
||||
var icons Icons
|
||||
|
||||
// SetIcons sets the icon set.
|
||||
func SetIcons (icns Icons) {
|
||||
assertBackend()
|
||||
icons = icns
|
||||
backend.SetIcons(icns)
|
||||
}
|
||||
|
||||
123
object.go
123
object.go
@@ -9,98 +9,6 @@ import "git.tebibyte.media/tomo/tomo/event"
|
||||
import "git.tebibyte.media/tomo/tomo/input"
|
||||
import "git.tebibyte.media/tomo/tomo/canvas"
|
||||
|
||||
// Side represents one side of a rectangle.
|
||||
type Side int; const (
|
||||
SideTop Side = iota
|
||||
SideRight
|
||||
SideBottom
|
||||
SideLeft
|
||||
)
|
||||
|
||||
// Inset represents a rectangle inset that can have a different value for each
|
||||
// side.
|
||||
type Inset [4]int
|
||||
|
||||
// I allows you to create an inset in a CSS-ish way:
|
||||
//
|
||||
// - One argument: all sides are set to this value
|
||||
// - Two arguments: the top and bottom sides are set to the first value, and
|
||||
// the left and right sides are set to the second value.
|
||||
// - Three arguments: the top side is set by the first value, the left and
|
||||
// right sides are set by the second vaue, and the bottom side is set by the
|
||||
// third value.
|
||||
// - Four arguments: each value corresponds to a side.
|
||||
//
|
||||
// This function will panic if an argument count that isn't one of these is
|
||||
// given.
|
||||
func I (sides ...int) Inset {
|
||||
switch len(sides) {
|
||||
case 1: return Inset { sides[0], sides[0], sides[0], sides[0] }
|
||||
case 2: return Inset { sides[0], sides[1], sides[0], sides[1] }
|
||||
case 3: return Inset { sides[0], sides[1], sides[2], sides[1] }
|
||||
case 4: return Inset { sides[0], sides[1], sides[2], sides[3] }
|
||||
default: panic("I: illegal argument count.")
|
||||
}
|
||||
}
|
||||
|
||||
// Apply returns the given rectangle, shrunk on all four sides by the given
|
||||
// inset. If a measurment of the inset is negative, that side will instead be
|
||||
// expanded outward. If the rectangle's dimensions cannot be reduced any
|
||||
// further, an empty rectangle near its center will be returned.
|
||||
func (inset Inset) Apply (bigger image.Rectangle) (smaller image.Rectangle) {
|
||||
smaller = bigger
|
||||
if smaller.Dx() < inset[3] + inset[1] {
|
||||
smaller.Min.X = (smaller.Min.X + smaller.Max.X) / 2
|
||||
smaller.Max.X = smaller.Min.X
|
||||
} else {
|
||||
smaller.Min.X += inset[3]
|
||||
smaller.Max.X -= inset[1]
|
||||
}
|
||||
|
||||
if smaller.Dy() < inset[0] + inset[2] {
|
||||
smaller.Min.Y = (smaller.Min.Y + smaller.Max.Y) / 2
|
||||
smaller.Max.Y = smaller.Min.Y
|
||||
} else {
|
||||
smaller.Min.Y += inset[0]
|
||||
smaller.Max.Y -= inset[2]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Inverse returns a negated version of the inset.
|
||||
func (inset Inset) Inverse () (prime Inset) {
|
||||
return Inset {
|
||||
inset[0] * -1,
|
||||
inset[1] * -1,
|
||||
inset[2] * -1,
|
||||
inset[3] * -1,
|
||||
}
|
||||
}
|
||||
|
||||
// Horizontal returns the sum of SideRight and SideLeft.
|
||||
func (inset Inset) Horizontal () int {
|
||||
return inset[SideRight] + inset[SideLeft]
|
||||
}
|
||||
|
||||
// Vertical returns the sum of SideTop and SideBottom.
|
||||
func (inset Inset) Vertical () int {
|
||||
return inset[SideTop] + inset[SideBottom]
|
||||
}
|
||||
|
||||
// Border represents a single border of a box.
|
||||
type Border struct {
|
||||
Width Inset
|
||||
Color [4]color.Color
|
||||
}
|
||||
|
||||
// Align lists basic alignment types.
|
||||
type Align int; const (
|
||||
AlignStart Align = iota // similar to left-aligned text
|
||||
AlignMiddle // similar to center-aligned text
|
||||
AlignEnd // similar to right-aligned text
|
||||
AlignEven // similar to justified text
|
||||
)
|
||||
|
||||
// Object is any onscreen object that is linked to a box (or is that box).
|
||||
// Unlike the Box interface and associated interfaces, Object implementations
|
||||
// may originate from anywhere.
|
||||
@@ -216,6 +124,8 @@ type Box interface {
|
||||
OnScroll (func (deltaX, deltaY float64)) event.Cookie
|
||||
OnKeyDown (func (key input.Key, numberPad bool)) event.Cookie
|
||||
OnKeyUp (func (key input.Key, numberPad bool)) event.Cookie
|
||||
OnStyleChange (func ()) event.Cookie
|
||||
OnIconsChange (func ()) event.Cookie
|
||||
}
|
||||
|
||||
// CanvasBox is a box that can be drawn to.
|
||||
@@ -275,6 +185,14 @@ type ContentBox interface {
|
||||
// ContentBounds returns the bounds of the inner content of the Box
|
||||
// relative to the Box's InnerBounds.
|
||||
ContentBounds () image.Rectangle
|
||||
// RecommendedHeight returns the recommended height for a given width,
|
||||
// if supported by the current content or layout. Otherwise, it should
|
||||
// just return the minimum height.
|
||||
RecommendedHeight (width int) int
|
||||
// RecommendedWidth returns the recommended width for a given height, if
|
||||
// supported by the current content or layout. Otherwise, it should just
|
||||
// return the minimum width.
|
||||
RecommendedWidth (height int) int
|
||||
// ScrollTo shifts the origin of the Box's content to the origin of the
|
||||
// Box's InnerBounds, offset by the given point.
|
||||
ScrollTo (image.Point)
|
||||
@@ -371,9 +289,21 @@ type Layout interface {
|
||||
MinimumSize (LayoutHints, []Box) image.Point
|
||||
// Arrange arranges child boxes according to the given LayoutHints.
|
||||
Arrange (LayoutHints, []Box)
|
||||
// RecommendedHeight returns the recommended height for a given width,
|
||||
// if supported. Otherwise, it should just return the minimum height.
|
||||
// The result of this behavior may or may not be respected, depending on
|
||||
// the situation.
|
||||
RecommendedHeight (LayoutHints, []Box, int) int
|
||||
// RecommendedWidth returns the recommended width for a given height, if
|
||||
// supported. Otherwise, it should just return the minimum width. The
|
||||
// result of this behavior may or may not be respected, depending on the
|
||||
// situation.
|
||||
RecommendedWidth (LayoutHints, []Box, int) int
|
||||
}
|
||||
|
||||
// Window is an operating system window. It can contain one object.
|
||||
// Window is an operating system window. It can contain one object. Windows
|
||||
// themselves are completely transparent, and become opaque once an opaque
|
||||
// object is added as their root.
|
||||
type Window interface {
|
||||
// SetRoot sets the root child of the window. There can only be one at
|
||||
// a time, and setting it will remove the current child if there is one.
|
||||
@@ -383,6 +313,13 @@ type Window interface {
|
||||
// SetIcon sets the icon of the window. When multiple icon sizes are
|
||||
// provided, the best fitting one is chosen for display.
|
||||
SetIcon (... canvas.Texture)
|
||||
// SetResizable sets whether the window can be resized by the user in
|
||||
// the X and Y directions. If one or both axes are false, the ones that
|
||||
// are will be shrunk to the window's minimum size.
|
||||
SetResizable (x, y bool)
|
||||
// SetBounds sets this window's bounds. This may or may not have any
|
||||
// effect on the window's position on screen depending on the platform.
|
||||
SetBounds (image.Rectangle)
|
||||
// Widget returns a window representing a smaller iconified form of this
|
||||
// window. How exactly this window is used depends on the platform.
|
||||
// Subsequent calls to this method on the same window will return the
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package tomo
|
||||
|
||||
import "fmt"
|
||||
import "git.tebibyte.media/tomo/tomo/data"
|
||||
import "git.tebibyte.media/tomo/tomo/event"
|
||||
import "git.tebibyte.media/tomo/tomo/canvas"
|
||||
|
||||
// Role describes the role of an object.
|
||||
type Role struct {
|
||||
@@ -60,23 +58,12 @@ func (c Color) String () string {
|
||||
|
||||
// RGBA satisfies the color.Color interface.
|
||||
func (id Color) RGBA () (r, g, b, a uint32) {
|
||||
if theme == nil { return }
|
||||
return theme.RGBA(id)
|
||||
if style == nil { return }
|
||||
return style.RGBA(id)
|
||||
}
|
||||
|
||||
// Theme can apply a visual style to different objects.
|
||||
type Theme interface {
|
||||
// A word on textures:
|
||||
//
|
||||
// Because textures can be linked to some resource that is outside of
|
||||
// the control of Go's garbage collector, methods of Theme must not
|
||||
// allocate new copies of a texture each time they are called. It is
|
||||
// fine to lazily load textures and save them for later use, but the
|
||||
// same texture must never be allocated multiple times as this could
|
||||
// cause a memory leak.
|
||||
//
|
||||
// As such, textures returned by these methods must be protected.
|
||||
|
||||
// Style can apply a visual style to different objects.
|
||||
type Style interface {
|
||||
// Apply applies the theme to the given object, according to its role.
|
||||
// This may register event listeners with the given object; closing the
|
||||
// returned cookie must remove them.
|
||||
@@ -84,28 +71,13 @@ type Theme interface {
|
||||
|
||||
// RGBA returns the RGBA values of the corresponding color ID.
|
||||
RGBA (Color) (r, g, b, a uint32)
|
||||
|
||||
// Icon returns a texture of the corresponding icon ID. If there is no
|
||||
// suitable option, it should return nil.
|
||||
Icon (Icon, IconSize) canvas.Texture
|
||||
|
||||
// MimeIcon returns a texture of an icon corresponding to a MIME type.
|
||||
// If there is no suitable specific option, it should return a more
|
||||
// generic icon or a plain file icon.
|
||||
MimeIcon (data.Mime, IconSize) canvas.Texture
|
||||
}
|
||||
|
||||
var theme Theme
|
||||
var style Style
|
||||
|
||||
// SetTheme sets the theme.
|
||||
func SetTheme (them Theme) {
|
||||
theme = them
|
||||
}
|
||||
|
||||
// Apply applies the current theme to the given object, according its role. This
|
||||
// may register event listeners with the given object; closing the returned
|
||||
// cookie will remove them.
|
||||
func Apply (object Object) event.Cookie {
|
||||
if theme == nil { return event.NoCookie { } }
|
||||
return theme.Apply(object)
|
||||
// SetStyle sets the style.
|
||||
func SetStyle (sty Style) {
|
||||
assertBackend()
|
||||
style = sty
|
||||
backend.SetStyle(sty)
|
||||
}
|
||||
96
unit.go
Normal file
96
unit.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package tomo
|
||||
|
||||
import "image"
|
||||
import "image/color"
|
||||
|
||||
// Side represents one side of a rectangle.
|
||||
type Side int; const (
|
||||
SideTop Side = iota
|
||||
SideRight
|
||||
SideBottom
|
||||
SideLeft
|
||||
)
|
||||
|
||||
// Inset represents a rectangle inset that can have a different value for each
|
||||
// side.
|
||||
type Inset [4]int
|
||||
|
||||
// I allows you to create an inset in a CSS-ish way:
|
||||
//
|
||||
// - One argument: all sides are set to this value
|
||||
// - Two arguments: the top and bottom sides are set to the first value, and
|
||||
// the left and right sides are set to the second value.
|
||||
// - Three arguments: the top side is set by the first value, the left and
|
||||
// right sides are set by the second vaue, and the bottom side is set by the
|
||||
// third value.
|
||||
// - Four arguments: each value corresponds to a side.
|
||||
//
|
||||
// This function will panic if an argument count that isn't one of these is
|
||||
// given.
|
||||
func I (sides ...int) Inset {
|
||||
switch len(sides) {
|
||||
case 1: return Inset { sides[0], sides[0], sides[0], sides[0] }
|
||||
case 2: return Inset { sides[0], sides[1], sides[0], sides[1] }
|
||||
case 3: return Inset { sides[0], sides[1], sides[2], sides[1] }
|
||||
case 4: return Inset { sides[0], sides[1], sides[2], sides[3] }
|
||||
default: panic("I: illegal argument count.")
|
||||
}
|
||||
}
|
||||
|
||||
// Apply returns the given rectangle, shrunk on all four sides by the given
|
||||
// inset. If a measurment of the inset is negative, that side will instead be
|
||||
// expanded outward. If the rectangle's dimensions cannot be reduced any
|
||||
// further, an empty rectangle near its center will be returned.
|
||||
func (inset Inset) Apply (bigger image.Rectangle) (smaller image.Rectangle) {
|
||||
smaller = bigger
|
||||
if smaller.Dx() < inset[3] + inset[1] {
|
||||
smaller.Min.X = (smaller.Min.X + smaller.Max.X) / 2
|
||||
smaller.Max.X = smaller.Min.X
|
||||
} else {
|
||||
smaller.Min.X += inset[3]
|
||||
smaller.Max.X -= inset[1]
|
||||
}
|
||||
|
||||
if smaller.Dy() < inset[0] + inset[2] {
|
||||
smaller.Min.Y = (smaller.Min.Y + smaller.Max.Y) / 2
|
||||
smaller.Max.Y = smaller.Min.Y
|
||||
} else {
|
||||
smaller.Min.Y += inset[0]
|
||||
smaller.Max.Y -= inset[2]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Inverse returns a negated version of the inset.
|
||||
func (inset Inset) Inverse () (prime Inset) {
|
||||
return Inset {
|
||||
inset[0] * -1,
|
||||
inset[1] * -1,
|
||||
inset[2] * -1,
|
||||
inset[3] * -1,
|
||||
}
|
||||
}
|
||||
|
||||
// Horizontal returns the sum of SideRight and SideLeft.
|
||||
func (inset Inset) Horizontal () int {
|
||||
return inset[SideRight] + inset[SideLeft]
|
||||
}
|
||||
|
||||
// Vertical returns the sum of SideTop and SideBottom.
|
||||
func (inset Inset) Vertical () int {
|
||||
return inset[SideTop] + inset[SideBottom]
|
||||
}
|
||||
|
||||
// Border represents a single border of a box.
|
||||
type Border struct {
|
||||
Width Inset
|
||||
Color [4]color.Color
|
||||
}
|
||||
|
||||
// Align lists basic alignment types.
|
||||
type Align int; const (
|
||||
AlignStart Align = iota // similar to left-aligned text
|
||||
AlignMiddle // similar to center-aligned text
|
||||
AlignEnd // similar to right-aligned text
|
||||
AlignEven // similar to justified text
|
||||
)
|
||||
Reference in New Issue
Block a user