or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

apidiff.mdconstraints.mdebnf.mderrors.mdevent.mdgorelease.mdindex.mdio-i2c.mdio-spi.mdjsonrpc2.mdmaps.mdmmap.mdmodgraphviz.mdrand.mdshiny.mdslices.mdslog.mdstats.mdsumdb.mdtrace.mdtxtar.mdtypeparams.mdutf8string.md
tile.json

shiny.mddocs/

Shiny - Experimental Portable GUI Framework

Shiny is an experimental, portable GUI framework for Go that provides a platform-independent abstraction for creating graphical user interfaces. It supports multiple platforms including Linux (X11, OpenGL driver), Windows, and mobile systems through a consistent API. Shiny offers low-level screen and drawing primitives, high-level widget components, and comprehensive input event handling for building desktop applications.

Package Information

  • Package Name: golang.org/x/exp/shiny
  • Package Type: Go module (golang.org/x/exp)
  • Language: Go
  • Installation: go get golang.org/x/exp/shiny@latest
  • Status: Experimental - API may change
  • Multi-Platform Support: Linux (X11, OpenGL), Windows, mobile platforms

Core Imports

import (
	"golang.org/x/exp/shiny/driver"
	"golang.org/x/exp/shiny/screen"
	"golang.org/x/exp/shiny/widget"
	"golang.org/x/exp/shiny/gesture"
	"golang.org/x/mobile/event/lifecycle"
)

Basic Usage

package main

import (
	"golang.org/x/exp/shiny/driver"
	"golang.org/x/exp/shiny/screen"
	"golang.org/x/mobile/event/lifecycle"
	"image"
	"image/color"
)

func main() {
	driver.Main(func(s screen.Screen) {
		w, err := s.NewWindow(nil)
		if err != nil {
			panic(err)
		}
		defer w.Release()

		for {
			switch e := w.NextEvent().(type) {
			case lifecycle.Event:
				if e.To == lifecycle.StageDead {
					return
				}
			}
		}
	})
}

Architecture

Shiny's architecture is built on several key layers:

  • Driver Layer: Platform-specific implementations (X11, Windows, OpenGL) that provide Screen implementations
  • Screen Layer: Core abstraction for windows, buffers, and textures
  • Widget Layer: High-level UI components for building user interfaces
  • Event System: Unified event handling across platforms through mobile/event packages
  • Drawing Primitives: Buffer and Texture types for 2D graphics operations
  • Text Rendering: Text layout and measurement capabilities

Capabilities

Screen Management

The screen package provides low-level access to graphics buffers and windows, forming the foundation of Shiny's graphics operations.

type Screen interface {
	// NewBuffer returns a new Buffer for this screen.
	NewBuffer(size image.Point) (Buffer, error)

	// NewTexture returns a new Texture for this screen.
	NewTexture(size image.Point) (Texture, error)

	// NewWindow returns a new Window for this screen.
	// A nil opts is valid and means to use the default option values.
	NewWindow(opts *NewWindowOptions) (Window, error)
}

Screen Types

type Buffer interface {
	// Release releases the Buffer's resources.
	Release()

	// Size returns the size of the Buffer's image.
	Size() image.Point

	// Bounds returns the bounds of the Buffer's image.
	Bounds() image.Rectangle

	// RGBA returns the pixel buffer as an *image.RGBA.
	RGBA() *image.RGBA
}

type Texture interface {
	// Release releases the Texture's resources.
	Release()

	// Size returns the size of the Texture's image.
	Size() image.Point

	// Bounds returns the bounds of the Texture's image.
	Bounds() image.Rectangle

	Uploader
}

type Uploader interface {
	// Upload uploads the sub-Buffer defined by src and sr to the destination.
	Upload(dp image.Point, src Buffer, sr image.Rectangle)

	// Fill fills that part of the destination with the given color.
	Fill(dr image.Rectangle, src color.Color, op draw.Op)
}

type Drawer interface {
	// Draw draws the sub-Texture defined by src and sr to the destination.
	Draw(src2dst f64.Aff3, src Texture, sr image.Rectangle, op draw.Op, opts *DrawOptions)

	// DrawUniform is like Draw except that the src is a uniform color instead of a Texture.
	DrawUniform(src2dst f64.Aff3, src color.Color, sr image.Rectangle, op draw.Op, opts *DrawOptions)

	// Copy copies the sub-Texture defined by src and sr to the destination.
	Copy(dp image.Point, src Texture, sr image.Rectangle, op draw.Op, opts *DrawOptions)

	// Scale scales the sub-Texture defined by src and sr to the destination.
	Scale(dr image.Rectangle, src Texture, sr image.Rectangle, op draw.Op, opts *DrawOptions)
}

type Window interface {
	Release()
	EventDeque
	Uploader
	Drawer
	Publish() PublishResult
}

type EventDeque interface {
	// Send adds an event to the end of the deque.
	Send(event interface{})

	// SendFirst adds an event to the start of the deque.
	SendFirst(event interface{})

	// NextEvent returns the next event in the deque.
	// Typical event types include lifecycle.Event, size.Event, paint.Event, key.Event, mouse.Event, touch.Event.
	NextEvent() interface{}
}

type NewWindowOptions struct {
	// Width and Height specify the dimensions of the new window.
	Width, Height int

	// Title specifies the window title.
	Title string
}

type PublishResult struct {
	// BackBufferPreserved is whether the contents of the back buffer was preserved.
	BackBufferPreserved bool
}

type DrawOptions struct {
}

Screen Management

Driver Management

The driver package provides the entry point for Shiny applications and platform-specific implementations.

// Main is called by the program's main function to run the graphical application.
// It calls f on the Screen, possibly in a separate goroutine, as some OS-specific
// libraries require being on 'the main thread'. It returns when f returns.
func Main(f func(screen.Screen))

Platform-Specific Drivers

Windows Driver (golang.org/x/exp/shiny/driver/windriver):

package windriver

// Main provides the Windows driver for accessing a screen.
func Main(f func(screen.Screen))

X11 Driver (golang.org/x/exp/shiny/driver/x11driver):

package x11driver

// Main provides the X11 driver for accessing a screen.
func Main(f func(screen.Screen))

OpenGL Driver (golang.org/x/exp/shiny/driver/gldriver):

package gldriver

// Main provides an OpenGL driver for accessing a screen.
func Main(f func(screen.Screen))

// NewContext creates an OpenGL ES context with a dedicated processing thread.
func NewContext() (gl.Context, error)

Driver Management

Gesture Recognition

The gesture package provides higher-level gesture events derived from lower-level mouse and touch events.

type Event struct {
	// Type is the gesture type.
	Type Type

	// Drag, LongPress and DoublePress are set when the gesture is recognized.
	Drag        bool
	LongPress   bool
	DoublePress bool

	// InitialPos is the initial position of the button press or touch.
	InitialPos Point

	// CurrentPos is the current position of the button or touch event.
	CurrentPos Point

	// Time is the event's time.
	Time time.Time
}

type EventFilter struct {
	EventDeque screen.EventDeque
}

// Filter filters the event from lower-level events, generating gesture events.
func (f *EventFilter) Filter(e interface{}) interface{}

type Point struct {
	X, Y float32
}

type Type uint8

const (
	// TypeStart and TypeEnd are the start and end of a gesture.
	TypeStart Type = 0
	TypeEnd   Type = 1

	// TypeIsLongPress, TypeIsDoublePress, TypeIsDrag indicate gesture recognition.
	TypeIsLongPress   Type = 10
	TypeIsDoublePress Type = 11
	TypeIsDrag        Type = 12

	// TypeTap and TypeDrag are tap and drag events.
	TypeTap  Type = 20
	TypeDrag Type = 21
)

Gesture Recognition

Widget System

The widget package provides high-level GUI components for building user interfaces. Widgets are organized in a tree structure and support layout, measurement, and event handling.

// RunWindow creates a new window for s, with the given widget tree, and runs its event loop.
func RunWindow(s screen.Screen, root node.Node, opts *RunWindowOptions) error

// WithLayoutData returns the given node after setting its embedded LayoutData field.
func WithLayoutData(n node.Node, layoutData interface{}) node.Node

type Axis uint8

const (
	AxisNone       = Axis(0)
	AxisHorizontal = Axis(1)
	AxisVertical   = Axis(2)
	AxisBoth       = Axis(3) // AxisHorizontal | AxisVertical
)

type RunWindowOptions struct {
	NewWindowOptions screen.NewWindowOptions
	Theme            theme.Theme
}

Basic Widgets

type Flow struct {
	node.ContainerEmbed
	Axis Axis
}

// NewFlow returns a new Flow widget containing the given children.
func NewFlow(a Axis, children ...node.Node) *Flow

type Label struct {
	node.LeafEmbed
	Text       string
	ThemeColor theme.Color
}

// NewLabel returns a new Label widget.
func NewLabel(text string) *Label

type Image struct {
	node.LeafEmbed
	Src     image.Image
	SrcRect image.Rectangle
}

// NewImage returns a new Image widget for the part of a source image.
func NewImage(src image.Image, srcRect image.Rectangle) *Image

type Space struct {
	node.LeafEmbed
}

// NewSpace returns a new Space widget.
func NewSpace() *Space

type Text struct {
	node.LeafEmbed
}

// NewText returns a new Text widget.
func NewText(text string) *Text

Layout and Styling Widgets

type Padder struct {
	node.ShellEmbed
	Axis   Axis
	Margin unit.Value
}

// NewPadder returns a new Padder widget.
func NewPadder(a Axis, margin unit.Value, inner node.Node) *Padder

type Sizer struct {
	node.ShellEmbed
	NaturalWidth  unit.Value
	NaturalHeight unit.Value
}

// NewSizer returns a new Sizer widget of the given natural size.
func NewSizer(naturalWidth, naturalHeight unit.Value, inner node.Node) *Sizer

type Uniform struct {
	node.ShellEmbed
	ThemeColor theme.Color
}

// NewUniform returns a new Uniform widget of the given color.
func NewUniform(c theme.Color, inner node.Node) *Uniform

type Sheet struct {
	node.ShellEmbed
}

// NewSheet returns a new Sheet widget.
func NewSheet(inner node.Node) *Sheet

Layout Data

type FlowLayoutData struct {
	// AlongWeight is the relative weight for distributing space along the Flow's axis.
	AlongWeight int

	// ExpandAlong controls if the child should expand along the Flow's axis.
	ExpandAlong bool

	// ShrinkAlong controls if the child should shrink along the Flow's axis.
	ShrinkAlong bool

	// ExpandAcross controls if the child should expand along the cross-axis.
	ExpandAcross bool

	// ShrinkAcross controls if the child should shrink along the cross-axis.
	ShrinkAcross bool
}

Widget System

Flex Layout

The widget/flex package provides CSS flexbox-inspired layout for complex UI arrangements.

type Flex struct {
	node.ContainerEmbed

	Direction    Direction
	Wrap         FlexWrap
	Justify      Justify
	AlignItems   AlignItem
	AlignContent AlignContent
}

// NewFlex returns a new Flex widget containing the given children.
func NewFlex(children ...node.Node) *Flex

type Direction uint8

const (
	Row Direction = iota
	RowReverse
	Column
	ColumnReverse
)

type FlexWrap uint8

const (
	NoWrap FlexWrap = iota
	Wrap
	WrapReverse
)

type Justify uint8

const (
	JustifyStart        Justify = iota
	JustifyEnd
	JustifyCenter
	JustifySpaceBetween
	JustifySpaceAround
)

type AlignItem uint8

const (
	AlignItemAuto AlignItem = iota
	AlignItemStart
	AlignItemEnd
	AlignItemCenter
	AlignItemBaseline
	AlignItemStretch
)

type AlignContent uint8

const (
	AlignContentStretch AlignContent = iota
	AlignContentStart
	AlignContentEnd
	AlignContentCenter
	AlignContentSpaceBetween
	AlignContentSpaceAround
)

type Basis uint8

const (
	Auto Basis = iota
	Definite
)

type LayoutData struct {
	MinSize image.Point
	MaxSize *image.Point

	// Grow determines how much a node will grow relative to its siblings.
	Grow float64

	// Shrink determines how much a node will shrink relative to its siblings.
	Shrink *float64

	// Basis determines the initial size of the node on the main axis.
	Basis   Basis
	BasisPx int

	Align AlignItem

	// BreakAfter forces the next node onto the next flex line.
	BreakAfter bool
}

Flex Layout

Widget Node System

The widget/node package provides the foundational structure for building custom widgets through a composition-based approach.

type Node interface {
	Measure(t *theme.Theme, widthHint, heightHint int)
	Layout(t *theme.Theme)
	Paint(ctx *PaintContext, origin image.Point) error
	PaintBase(ctx *PaintBaseContext, origin image.Point) error
	OnChildMarked(child Node, newMarks Marks)
	OnInputEvent(e interface{}, origin image.Point) EventHandled
	OnLifecycleEvent(e lifecycle.Event)
	FirstChild() Node
	LastChild() Node
	Parent() Node
}

type Embed struct {
	// Wrapper is the outer type that wraps (embeds) this type.
	Wrapper Node

	// Parent, FirstChild, LastChild, PrevSibling and NextSibling describe the widget tree structure.
	Parent, FirstChild, LastChild, PrevSibling, NextSibling *Embed

	// LayoutData is layout-specific data for this node.
	LayoutData interface{}

	// MeasuredSize is the widget's natural size, in pixels.
	MeasuredSize image.Point

	// Rect is the widget's position and actual size, in pixels.
	Rect image.Rectangle

	// Marks are a bitfield of node state.
	Marks Marks
}

type ContainerEmbed struct { Embed }
type LeafEmbed struct { Embed }
type ShellEmbed struct { Embed }

type EventHandled bool

const (
	NotHandled = EventHandled(false)
	Handled    = EventHandled(true)
)

type Marks uint8

const (
	// MarkNeedsMeasureLayout marks this node as needing Measure and Layout calls.
	MarkNeedsMeasureLayout = Marks(1 << 0)

	// MarkNeedsPaint marks this node as needing a Paint call.
	MarkNeedsPaint = Marks(1 << 1)

	// MarkNeedsPaintBase marks this node as needing a PaintBase call.
	MarkNeedsPaintBase = Marks(1 << 2)
)

const NoHint = -1

Widget Node System

GL Widgets

The widget/glwidget package provides OpenGL rendering capabilities within the widget system.

type GL struct {
	node.LeafEmbed

	Ctx gl.Context
}

// NewGL creates a GL widget with a Draw function called when painted.
func NewGL(drawFunc func(*GL)) *GL

// Publish renders the default framebuffer of Ctx onto the area of the window occupied by the widget.
func (w *GL) Publish()

GL Widgets

Theming

The widget/theme package provides theme management for consistent styling across widgets.

type Theme struct {
	// Has unexported fields
}

type Color interface {
	Color(*Theme) color.Color
	Uniform(*Theme) *image.Uniform
}

// StaticColor adapts a color.Color to a theme Color.
func StaticColor(c color.Color) Color

type FontFaceCatalog interface {
	AcquireFontFace(FontFaceOptions) font.Face
	ReleaseFontFace(FontFaceOptions, font.Face)
}

type FontFaceOptions struct {
	Style  font.Style
	Weight font.Weight
}

type Palette [PaletteLen]image.Uniform

const (
	Light      = PaletteIndex(0)
	Neutral    = PaletteIndex(1)
	Dark       = PaletteIndex(2)
	Accent     = PaletteIndex(3)
	Foreground = PaletteIndex(4)
	Background = PaletteIndex(5)
	PaletteLen = 6
)

const DefaultDPI = 72.0

var DefaultFontFaceCatalog FontFaceCatalog
var DefaultPalette Palette
var Default *Theme

Theming

Unit System

The unit package provides flexible unit conversion for graphics measurements.

type Unit uint8

const (
	// Px is a physical pixel, regardless of the DPI resolution.
	Px Unit = iota

	// Dp is 1 density independent pixel: 1/160th of an inch.
	Dp

	// Pt is 1 point: 1/72nd of an inch.
	Pt

	// Mm is 1 millimetre: 1/25.4th of an inch.
	Mm

	// In is 1 inch.
	In

	// Em is the height of the active font face.
	Em

	// Ex is the x-height of the active font face.
	Ex

	// Ch is the character width of the numeral zero glyph.
	Ch
)

type Value struct {
	F float64
	U Unit
}

// Constructor functions for values in different units
func Pixels(f float64) Value
func DIPs(f float64) Value
func Points(f float64) Value
func Millimetres(f float64) Value
func Inches(f float64) Value
func Ems(f float64) Value
func Exs(f float64) Value
func Chs(f float64) Value

type Converter interface {
	// Convert converts v to the given unit.
	Convert(v Value, to Unit) Value

	// Pixels converts v to a 26.6 fixed-point number of physical pixels.
	Pixels(v Value) fixed.Int26_6
}

const (
	DensityIndependentPixelsPerInch = 160
	MillimetresPerInch              = 25.4
	PointsPerInch                   = 72
)

Unit System

Text Layout

The text package provides paragraph text layout and manipulation capabilities.

type Frame struct {
	// Has unexported fields
}

// NewCaret returns a new Caret at the start of this Frame.
func (f *Frame) NewCaret() *Caret

// Height returns the height in pixels of this Frame.
func (f *Frame) Height() int

// Len returns the number of bytes in the Frame's text.
func (f *Frame) Len() int

// LineCount returns the number of Lines in this Frame.
func (f *Frame) LineCount() int

// ParagraphCount returns the number of Paragraphs in this Frame.
func (f *Frame) ParagraphCount() int

// FirstParagraph returns the first paragraph of this frame.
func (f *Frame) FirstParagraph() *Paragraph

// SetFace sets the font face for measuring text.
func (f *Frame) SetFace(face font.Face)

// SetMaxWidth sets the target maximum width of a Line of text.
func (f *Frame) SetMaxWidth(m fixed.Int26_6)

type Caret struct {
	// Has unexported fields
}

// Read satisfies the io.Reader interface.
func (c *Caret) Read(buf []byte) (n int, err error)

// ReadByte returns the next byte after the Caret and increments the Caret.
func (c *Caret) ReadByte() (x byte, err error)

// ReadRune returns the next rune after the Caret and increments the Caret.
func (c *Caret) ReadRune() (r rune, size int, err error)

// Write inserts s into the Frame's text at the Caret and increments the Caret.
func (c *Caret) Write(s []byte) (n int, err error)

// WriteByte inserts x into the Frame's text at the Caret and increments the Caret.
func (c *Caret) WriteByte(x byte) error

// WriteRune inserts r into the Frame's text at the Caret and increments the Caret.
func (c *Caret) WriteRune(r rune) (size int, err error)

// WriteString inserts s into the Frame's text at the Caret and increments the Caret.
func (c *Caret) WriteString(s string) (n int, err error)

// Seek satisfies the io.Seeker interface.
func (c *Caret) Seek(offset int64, whence int) (int64, error)

// Delete deletes nBytes bytes in the specified direction from the Caret's location.
func (c *Caret) Delete(dir Direction, nBytes int) (dBytes int)

// DeleteRunes deletes nRunes runes in the specified direction.
func (c *Caret) DeleteRunes(dir Direction, nRunes int) (dRunes, dBytes int)

// Close closes the Caret.
func (c *Caret) Close() error

type Paragraph struct {
	// Has unexported fields
}

// FirstLine returns the first Line of this Paragraph.
func (p *Paragraph) FirstLine(f *Frame) *Line

// Next returns the next Paragraph after this one.
func (p *Paragraph) Next(f *Frame) *Paragraph

type Line struct {
	// Has unexported fields
}

// FirstBox returns the first Box of this Line.
func (l *Line) FirstBox(f *Frame) *Box

// Height returns the height in pixels of this Line.
func (l *Line) Height(f *Frame) int

// Next returns the next Line after this one in the Paragraph.
func (l *Line) Next(f *Frame) *Line

type Box struct {
	// Has unexported fields
}

// Text returns the Box's text.
func (b *Box) Text(f *Frame) []byte

// TrimmedText returns the Box's text, trimmed right of any white space if last Box in Line.
func (b *Box) TrimmedText(f *Frame) []byte

// Next returns the next Box after this one in the Line.
func (b *Box) Next(f *Frame) *Box

type Direction bool

const (
	Forwards  Direction = false
	Backwards Direction = true
)

const (
	SeekSet int = 0
	SeekCur int = 1
	SeekEnd int = 2
)

Text Layout

Icon Vector Graphics

The iconvg package provides support for compact binary vector graphics format, useful for icons and logos.

// Decode decodes an IconVG graphic.
func Decode(dst Destination, src []byte, opts *DecodeOptions) error

// UpgradeToFileFormatVersion1 upgrades IconVG data from version 0 to version 1.
func UpgradeToFileFormatVersion1(v0 []byte, opts *UpgradeToFileFormatVersion1Options) (v1 []byte, retErr error)

type Destination interface {
	Reset(m Metadata)

	SetCSel(cSel uint8)
	SetNSel(nSel uint8)
	SetCReg(adj uint8, incr bool, c Color)
	SetNReg(adj uint8, incr bool, f float32)
	SetLOD(lod0, lod1 float32)

	StartPath(adj uint8, x, y float32)
	ClosePathEndPath()
	ClosePathAbsMoveTo(x, y float32)
	ClosePathRelMoveTo(x, y float32)

	AbsHLineTo(x float32)
	RelHLineTo(x float32)
	AbsVLineTo(y float32)
	RelVLineTo(y float32)
	AbsLineTo(x, y float32)
	RelLineTo(x, y float32)
	AbsSmoothQuadTo(x, y float32)
	RelSmoothQuadTo(x, y float32)
	AbsQuadTo(x1, y1, x, y float32)
	RelQuadTo(x1, y1, x, y float32)
	AbsSmoothCubeTo(x2, y2, x, y float32)
	RelSmoothCubeTo(x2, y2, x, y float32)
	AbsCubeTo(x1, y1, x2, y2, x, y float32)
	RelCubeTo(x1, y1, x2, y2, x, y float32)
	AbsArcTo(rx, ry, xAxisRotation float32, largeArc, sweep bool, x, y float32)
	RelArcTo(rx, ry, xAxisRotation float32, largeArc, sweep bool, x, y float32)
}

type Color struct {
	// Has unexported fields
}

// RGBAColor returns a direct Color.
func RGBAColor(c color.RGBA) Color

// PaletteIndexColor returns an indirect Color referring to a palette index.
func PaletteIndexColor(i uint8) Color

// CRegColor returns an indirect Color referring to a color register.
func CRegColor(i uint8) Color

// BlendColor returns an indirect Color that blends two other Colors.
func BlendColor(t, c0, c1 uint8) Color

// Resolve resolves the Color's RGBA value.
func (c Color) Resolve(pal *Palette, cReg *[64]color.RGBA) color.RGBA

type ColorType uint8

const (
	ColorTypeRGBA ColorType = iota
	ColorTypePaletteIndex
	ColorTypeCReg
	ColorTypeBlend
)

type Encoder struct {
	// HighResolutionCoordinates is whether coordinates should be encoded at best resolution.
	HighResolutionCoordinates bool
}

// Reset resets the Encoder for the given Metadata.
func (e *Encoder) Reset(m Metadata)

// Bytes returns the encoded form.
func (e *Encoder) Bytes() ([]byte, error)

// Encoder drawing methods: AbsLineTo, RelLineTo, etc.
func (e *Encoder) AbsLineTo(x, y float32)
func (e *Encoder) RelLineTo(x, y float32)
// ... additional drawing methods

type DecodeOptions struct {
	// Palette is an optional 64 color palette.
	Palette *Palette
}

type Palette [64]color.RGBA

var DefaultPalette Palette
var DefaultViewBox Rectangle

Icon Vector Graphics

Image Utilities

The imageutil package provides utility functions for image manipulation.

// Border returns four rectangles that together contain those points between r and r.Inset(inset).
func Border(r image.Rectangle, inset int) [4]image.Rectangle

Image Utilities

Material Design Colors

The materialdesign/colornames package provides named colors from the Material Design specification.

// Extensive set of named color variables following Material Design guidelines
var (
	Red50, Red100, Red200, ... color.RGBA
	Pink50, Pink100, Pink200, ... color.RGBA
	Purple50, Purple100, ... color.RGBA
	// ... and many more color palettes

	// Neutral colors
	Grey50, Grey100, ... Grey900 color.RGBA
	BlueGrey50, BlueGrey100, ... BlueGrey900 color.RGBA
	Black, White color.RGBA
)

// Map provides string-to-color lookup
var Map map[string]color.RGBA

Material Design Colors

Complete Example: Building a GUI Application

package main

import (
	"fmt"
	"golang.org/x/exp/shiny/driver"
	"golang.org/x/exp/shiny/screen"
	"golang.org/x/exp/shiny/widget"
	"golang.org/x/exp/shiny/widget/node"
	"golang.org/x/mobile/event/lifecycle"
	"image/color"
)

func main() {
	driver.Main(func(s screen.Screen) {
		// Create a simple label widget
		label := widget.NewLabel("Hello, Shiny!")

		// Create a flow layout with vertical axis
		root := widget.NewFlow(widget.AxisVertical, label)

		// Run the window with the widget tree
		err := widget.RunWindow(s, root, &widget.RunWindowOptions{
			NewWindowOptions: screen.NewWindowOptions{
				Width:  400,
				Height: 300,
				Title:  "Shiny App",
			},
		})

		if err != nil {
			fmt.Println("Error:", err)
		}
	})
}

Key Concepts

Windows and Buffers

  • Window: A platform-specific window on the screen that receives events and displays content
  • Buffer: An in-memory RGBA pixel buffer that can be modified and uploaded to textures
  • Texture: A GPU-resident pixel buffer that can be drawn to windows and other textures
  • Uploader: Interface for uploading buffers to textures or windows

Drawing Operations

  • Drawer: Interface for drawing textures and uniform colors with transformations
  • Draw Operations: Support for standard image composition operators (Over, Src)
  • Affine Transformations: Support for translations, scales, rotations via f64.Aff3 matrices

Event Handling

  • EventDeque: FIFO+LIFO queue for events (push and inject capabilities)
  • Gesture Recognition: High-level gesture events (tap, drag, long-press, double-press)
  • Lifecycle Events: Window lifecycle management (create, focus, dead)
  • Input Events: Keyboard, mouse, and touch events from mobile/event packages

Widget System

  • Node-based Architecture: Heterogeneous widget tree with custom layout and paint
  • Measurement/Layout Cycle: Two-phase layout: measure natural size, then layout at actual size
  • Theme Support: Consistent styling through theme system with colors and fonts
  • Marks System: Efficient invalidation of UI elements needing remeasure or repaint

Platform Support

  • Multi-platform Drivers: Different implementations for X11, Windows, and OpenGL
  • Experimental Status: API may change; monitor releases for breaking changes
  • Cross-platform Abstraction: Unified API across all supported platforms

Important Notes

  • Shiny is experimental and part of golang.org/x/exp, meaning the API may change between releases
  • Some OS-specific libraries require execution on the "main thread", which driver.Main handles
  • Buffer pixel contents should not be accessed while uploading; buffers are reusable once uploads complete
  • Windows must call Publish() to display changes; updates only appear after publication
  • Multiple Carets in text.Frame can be used interleaved but not concurrently
  • All drawing coordinates use fixed-point or float64 precision for accuracy
  • Widget tree modifications can cause re-layout; pointer values should not be held over such changes