Documentation
¶
Index ¶
- Constants
- Variables
- func GetTerminalSize() (int, int)
- func NoteName(note uint8) string
- func ShowConfirm(app *Application, title, message string, style ButtonStyle, onConfirm func())
- func ShowFilePicker(app *Application, initialDir string, onSelect func(path string))
- func ShowTextEditor(app *Application, title, label, current string, onConfirm func(string))
- func ShowValueEditor(app *Application, title string, current, min, max float64, ...)
- func WriteGph(w io.Writer, img *GphImage) error
- type Application
- func (app *Application) CloseModal()
- func (app *Application) Invoke(fn func())
- func (app *Application) Locale() Locale
- func (app *Application) Quit()
- func (app *Application) Resume()
- func (app *Application) Run()
- func (app *Application) SetIdleCallback(cb func())
- func (app *Application) SetLocale(l Locale)
- func (app *Application) SetModal(mod *Window)
- func (app *Application) SetOnQuitRequested(fn func())
- func (app *Application) SetStatus(status string)
- func (app *Application) SetTheme(t Theme)
- func (app *Application) SetTranslations(locale Locale, catalog Catalog)
- func (app *Application) SetWindow(win *Window)
- func (app *Application) ShowMessage(title, message string, style ButtonStyle)
- func (app *Application) Suspend()
- func (app *Application) T(key string, args ...any) string
- type BaseWidget
- func (b *BaseWidget) CanFocus() bool
- func (b *BaseWidget) DrawOverlay(c *Canvas, oX, oY, pW, pH int)
- func (b *BaseWidget) DrawRelative(c *Canvas, offX, offY, pW, pH int)
- func (b *BaseWidget) GetChildren() []Widget
- func (b *BaseWidget) GetFixedH() int
- func (b *BaseWidget) GetFixedW() int
- func (b *BaseWidget) HandleEvent(ev Event)
- func (b *BaseWidget) HasFocus() bool
- func (b *BaseWidget) HitTest(mx, my int) bool
- func (b *BaseWidget) IsEnabled() bool
- func (b *BaseWidget) IsVisible() bool
- func (b *BaseWidget) SetEnabled(e bool)
- func (b *BaseWidget) SetFocus(f bool)
- func (b *BaseWidget) SetPercentLayout(x, y, w, h int)
- func (b *BaseWidget) SetPosition(x, y int)
- func (b *BaseWidget) SetVisible(v bool)
- type Button
- type ButtonStyle
- type Canvas
- func (c *Canvas) Clear()
- func (c *Canvas) DrawCell(x, y int, s string, bg, fg Color)
- func (c *Canvas) DrawText(x, y int, text string, bg, fg Color)
- func (c *Canvas) DrawTextBounded(x, y, maxW int, text string, bg, fg Color)
- func (c *Canvas) DrawTextWrapped(x, y, maxW int, text string, bg, fg Color) int
- func (c *Canvas) GetCellBg(x, y int) Color
- func (c *Canvas) Height() int
- func (c *Canvas) Render()
- func (c *Canvas) Resize(w, h int)
- func (c *Canvas) Theme() Theme
- func (c *Canvas) Width() int
- type Catalog
- type Cell
- type Checkbox
- type Color
- type ComboBox
- type Event
- type EventType
- type Fader
- type FaderTick
- type Flex
- type FlexDirection
- type GphImage
- type GphPixel
- type GroupBox
- type Image
- type InputBox
- type KeyCode
- type Label
- type ListBox
- type Locale
- type MenuCategory
- type MenuItem
- type MenuStrip
- type Panel
- type PianoOrientation
- type PianoRoll
- type PlaybackMode
- type ProgressBar
- type RawInputReceiver
- type Slider
- type Spinner
- type Tab
- type TabStyle
- type TabView
- type Terminal
- type TextArea
- type TextLine
- type Theme
- type TodoItem
- type TodoList
- type TodoState
- type Widget
- type Window
- type WindowChrome
Constants ¶
const ( KeyYes = "graphite.yes" KeyNo = "graphite.no" KeyOK = "graphite.ok" KeyCancel = "graphite.cancel" KeyValueRequired = "graphite.value_required" KeyOpen = "graphite.open" KeyDirLabel = "graphite.filepicker.dir_label" KeyFileNameLabel = "graphite.filepicker.filename_label" KeyColumnName = "graphite.filepicker.column_name" KeyColumnDate = "graphite.filepicker.column_date" KeyColumnType = "graphite.filepicker.column_type" KeyColumnSize = "graphite.filepicker.column_size" KeyFileFolder = "graphite.filepicker.file_folder" KeyFileGeneric = "graphite.filepicker.file_generic" KeyFilterAll = "graphite.filepicker.filter_all" KeyFilterGph = "graphite.filepicker.filter_gph" KeyFilterImage = "graphite.filepicker.filter_image" KeyFilterVideo = "graphite.filepicker.filter_video" KeyValuePrompt = "graphite.valueeditor.prompt" KeyValueRangeError = "graphite.valueeditor.range_error" )
Translation keys for every string the library's own built-in dialogs (dialogs.go, app.go's ShowMessage), file picker (filepicker.go), and value editor (fader.go's ShowValueEditor) display. A custom Catalog passed to Application.SetTranslations may reuse these keys to override a prepared translation, or define its own keys for a caller's own widget text — T resolves any key the same way (see Catalog).
Variables ¶
var GphMagic = []byte{'G', 'P', 'H', '\x01'}
GphMagic is the expected file signature for version 1 of the GPH format.
Functions ¶
func GetTerminalSize ¶
GetTerminalSize returns the current width and height of the terminal, or an 80x24 fallback if the size cannot be determined (e.g. stdout is not a terminal).
func NoteName ¶
NoteName formats a MIDI note number (0-127) as a pitch class plus octave number, e.g. NoteName(60) == "C4", using the widely used convention where note 60 (middle C) is octave 4.
func ShowConfirm ¶
func ShowConfirm(app *Application, title, message string, style ButtonStyle, onConfirm func())
ShowConfirm opens a modal titled title asking the user to confirm message with "Yes"/"No" buttons. onConfirm runs only if "Yes" is chosen; either button closes the modal. style colors the "Yes" button — pass BtnDanger for a destructive confirmation (e.g. delete), BtnDefault for a neutral one.
func ShowFilePicker ¶
func ShowFilePicker(app *Application, initialDir string, onSelect func(path string))
ShowFilePicker opens a modal dialog that lets the user browse the filesystem and select a file. The callback onSelect is invoked with the absolute path of the chosen file. If the user cancels, the modal is closed and onSelect is not called.
func ShowTextEditor ¶
func ShowTextEditor(app *Application, title, label, current string, onConfirm func(string))
ShowTextEditor opens a modal titled title prompting for a single line of free-form text via label, pre-filled with current. It is ShowValueEditor's non-numeric counterpart, for callers that need an arbitrary string (a file or directory name) rather than a bounded number.
Both the "OK" button and Enter inside the field (via InputBox.OnSubmit) confirm; a blank (whitespace-only) value shows an inline error and leaves the modal open instead of calling onConfirm, since every known caller (naming a file or directory) requires a non-blank result. "Cancel" closes without calling onConfirm.
func ShowValueEditor ¶
func ShowValueEditor(app *Application, title string, current, min, max float64, onConfirm func(float64))
ShowValueEditor opens a modal titled title with an input field pre-filled with current. If the user submits a valid number, the modal closes and onConfirm is called; otherwise, an error modal stacks on top of it.
Types ¶
type Application ¶
type Application struct {
// contains filtered or unexported fields
}
Application owns the terminal, the canvas, the active window and modal stack, and drives the main render/input loop via Run. It is the single composition root a program constructs: all state that would otherwise need to be global (terminal mode, color theme) lives on this struct instead.
func NewApplication ¶
func NewApplication() *Application
NewApplication creates an Application with an empty canvas using DefaultTheme and LocaleEnglish. Call SetTheme to customize colors, or SetLocale to change the language used by the library's own built-in dialogs, file picker, and value editor (see T).
func (*Application) CloseModal ¶
func (app *Application) CloseModal()
CloseModal closes the topmost modal, revealing the previous one (if any) or the active window.
func (*Application) Invoke ¶
func (app *Application) Invoke(fn func())
Invoke queues fn to run on the main loop just before the next frame is drawn. This is the only safe way to touch widget state from a background goroutine: mutating a widget's fields directly from another goroutine races with Run's render loop reading those same fields.
func (*Application) Locale ¶ added in v0.2.0
func (app *Application) Locale() Locale
Locale returns the Locale currently used by T, and therefore by every built-in dialog, the file picker, and the value editor. Defaults to LocaleEnglish.
func (*Application) Resume ¶
func (app *Application) Resume()
Resume switches the terminal back into raw/TUI mode and forces a full redraw, e.g. after an interactive subprocess launched via Suspend exits.
func (*Application) Run ¶
func (app *Application) Run()
Run initializes the terminal and drives the main loop: resize, drain queued Invoke callbacks, draw, render, poll for input, and route the resulting event, until Quit is called or the process is torn down. The terminal is always restored on return, including on panic.
func (*Application) SetIdleCallback ¶
func (app *Application) SetIdleCallback(cb func())
SetIdleCallback sets a function invoked repeatedly once 300ms have elapsed with no input, useful for polling background state (see components/erbe-3100-tester for an example).
func (*Application) SetLocale ¶ added in v0.2.0
func (app *Application) SetLocale(l Locale)
SetLocale changes the Locale T resolves against going forward. It does not itself redraw anything already on screen — a widget or dialog picks up the new locale the next time it calls T, e.g. the next time one of the Show* helpers opens a new modal.
func (*Application) SetModal ¶
func (app *Application) SetModal(mod *Window)
SetModal opens mod on top of the current modal stack, leaving any already-open modal in place beneath it. Also blurs whatever widget currently has keyboard focus one layer down (see Window.ClearFocus) — exactly one of activeWindow or the current top modal actually has a focused widget at any moment, so clearing all of them unconditionally is simpler than tracking which layer that is, the same reasoning ClearMouseCapture below it already follows.
func (*Application) SetOnQuitRequested ¶
func (app *Application) SetOnQuitRequested(fn func())
SetOnQuitRequested overrides what Escape does when no modal is open: instead of quitting immediately, Run calls fn and leaves the application running. fn is responsible for deciding whether to quit — typically by opening a ShowConfirm dialog whose "Yes" button calls Quit. Passing nil restores the default immediate-quit behavior.
func (*Application) SetStatus ¶
func (app *Application) SetStatus(status string)
SetStatus sets the text shown in the status bar along the bottom row.
func (*Application) SetTheme ¶
func (app *Application) SetTheme(t Theme)
SetTheme replaces the color palette used to render every widget and forces a full redraw so the change is visible on the next frame.
func (*Application) SetTranslations ¶ added in v0.2.0
func (app *Application) SetTranslations(locale Locale, catalog Catalog)
SetTranslations merges catalog into the Catalog T consults first for locale, before falling back to the library's own prepared Catalog (if any) and then to English. A key already registered for locale — from an earlier SetTranslations call, or from the library's own built-in Catalog — is overridden by catalog's entry; every other key registered earlier is kept. Calling it repeatedly is therefore how a program builds up one Locale's dictionary incrementally: once for a shared base, again per screen or module, again for a late override — nothing already registered is ever discarded except a key catalog itself redefines. To supply a full application translation, either make one SetTranslations call with every key, or split it across several calls (Catalog.Merge composes several Go-native Catalog values into one first, if you'd rather make a single call) however the codebase is organized.
func (*Application) SetWindow ¶
func (app *Application) SetWindow(win *Window)
SetWindow sets the non-modal window drawn behind any open modals.
func (*Application) ShowMessage ¶
func (app *Application) ShowMessage(title, message string, style ButtonStyle)
ShowMessage opens a modal dialog with a title, a message, and a single OK button styled per style. It is layered on SetModal, so it stacks on top of any modal already open rather than replacing it.
func (*Application) Suspend ¶
func (app *Application) Suspend()
Suspend restores the terminal to normal (cooked) mode, e.g. before shelling out to an interactive subprocess.
func (*Application) T ¶ added in v0.2.0
func (app *Application) T(key string, args ...any) string
T resolves key to display text for app's current Locale (see SetLocale), formatting it with args via fmt.Sprintf when any are given — so a translated string can carry the same %-verbs as the English source (KeyValuePrompt and KeyValueRangeError both take two %g values).
Resolution order: a Catalog registered for the current locale via SetTranslations, then the library's own prepared Catalog for that locale, then the same two steps for English, then key itself. A missing translation therefore degrades to readable English (or, for a caller's own custom key with no English entry either, to the key string) rather than an empty or garbled result.
type BaseWidget ¶
type BaseWidget struct {
X, Y, Width, Height int
PctX, PctY, PctW, PctH int
IsFocusable, IsFocused, Enabled, Visible bool
AbsX, AbsY, LastW, LastH int
}
BaseWidget implements the mechanical parts of Widget (layout resolution, focus/enabled/visible state) so concrete widgets only need to implement drawing and event handling.
func NewBaseWidget ¶
func NewBaseWidget(x, y, w, h int) BaseWidget
NewBaseWidget creates a BaseWidget at the given fixed position and size, enabled and visible by default. Percent-based layout, if wanted, is added afterwards via SetPercentLayout.
func (*BaseWidget) CanFocus ¶
func (b *BaseWidget) CanFocus() bool
CanFocus reports whether this widget is eligible to receive keyboard focus: it must be focusable by design, enabled, and visible.
func (*BaseWidget) DrawOverlay ¶
func (b *BaseWidget) DrawOverlay(c *Canvas, oX, oY, pW, pH int)
DrawOverlay draws content that must appear above sibling widgets (e.g. dropdown popups). The default implementation draws nothing.
func (*BaseWidget) DrawRelative ¶
func (b *BaseWidget) DrawRelative(c *Canvas, offX, offY, pW, pH int)
DrawRelative resolves the widget's absolute position and size (AbsX, AbsY, LastW, LastH) against the parent's content origin (offX, offY) and dimensions (pW, pH). It performs no drawing itself; concrete widgets call this first, then draw using the resolved fields.
func (*BaseWidget) GetChildren ¶
func (b *BaseWidget) GetChildren() []Widget
GetChildren returns nested widgets so Window can flatten containers (e.g. Panel) when building the focus order and hit-testing the tree. Leaf widgets have none.
func (*BaseWidget) GetFixedH ¶
func (b *BaseWidget) GetFixedH() int
GetFixedH returns the widget's configured height, or 1 if none was set. Containers that stack children vertically by their natural size (e.g. Flex) use this for children not given a proportional weight.
func (*BaseWidget) GetFixedW ¶
func (b *BaseWidget) GetFixedW() int
GetFixedW returns the widget's configured width, or 1 if none was set. Symmetric with GetFixedH, for containers (e.g. Flex) laying out children horizontally by their natural size.
func (*BaseWidget) HandleEvent ¶
func (b *BaseWidget) HandleEvent(ev Event)
HandleEvent processes an input event routed to this widget. The default implementation ignores all events.
func (*BaseWidget) HasFocus ¶
func (b *BaseWidget) HasFocus() bool
HasFocus reports whether this widget currently has keyboard focus.
func (*BaseWidget) HitTest ¶
func (b *BaseWidget) HitTest(mx, my int) bool
HitTest reports whether the screen coordinates (mx, my) fall within the widget's last resolved bounds.
func (*BaseWidget) IsEnabled ¶
func (b *BaseWidget) IsEnabled() bool
IsEnabled reports whether this widget currently accepts input.
func (*BaseWidget) IsVisible ¶
func (b *BaseWidget) IsVisible() bool
IsVisible reports whether this widget is currently visible.
func (*BaseWidget) SetEnabled ¶
func (b *BaseWidget) SetEnabled(e bool)
SetEnabled sets whether this widget accepts input. Window routes no events to a disabled widget, regardless of what HandleEvent does.
func (*BaseWidget) SetFocus ¶
func (b *BaseWidget) SetFocus(f bool)
SetFocus sets whether this widget currently has keyboard focus.
func (*BaseWidget) SetPercentLayout ¶
func (b *BaseWidget) SetPercentLayout(x, y, w, h int)
SetPercentLayout switches the widget to percentage-based positioning and sizing relative to its parent's content area. A value of 0 for any axis keeps the corresponding fixed X/Y/Width/Height instead.
func (*BaseWidget) SetPosition ¶
func (b *BaseWidget) SetPosition(x, y int)
SetPosition sets the widget's fixed X/Y offset used by DrawRelative.
func (*BaseWidget) SetVisible ¶
func (b *BaseWidget) SetVisible(v bool)
SetVisible sets whether this widget is drawn and eligible for focus/hit testing.
type Button ¶
type Button struct {
BaseWidget
Text string
Style ButtonStyle
OnClick func()
// BgColor/FgColor override the button's idle (enabled, unfocused,
// non-BtnDanger) colors; ColorNone (the default set by NewButton)
// uses theme.BgWidget/FgWindow instead, matching every Button's
// original appearance. Focused, disabled, and BtnDanger-while-
// unfocused rendering are unaffected — a caller wanting a button that
// reads as its own accent even when idle (e.g. a toolbar button that
// would otherwise blend into a plain list background) sets these
// instead of only being able to distinguish it once focused.
BgColor Color
FgColor Color
}
Button is a focusable, clickable action with a text label.
func NewButton ¶
func NewButton(x, y int, text string, style ButtonStyle, onClick func()) *Button
NewButton creates a Button at (x, y) that calls onClick when activated, with BgColor/FgColor left at their default (ColorNone, meaning "use the theme").
func (*Button) DrawRelative ¶
DrawRelative implements Widget.
func (*Button) HandleEvent ¶
HandleEvent implements Widget: Enter and mouse clicks both activate OnClick. Window.HandleEvent already withholds events from a disabled button, so no enabled check is needed here.
type ButtonStyle ¶
type ButtonStyle int
ButtonStyle selects a Button's accent color.
const ( BtnDefault ButtonStyle = iota BtnSuccess BtnDanger BtnWarning BtnInfo )
Supported button styles.
type Canvas ¶
type Canvas struct {
// contains filtered or unexported fields
}
Canvas is a double-buffered terminal grid. Widgets draw into the back buffer; Render diffs it against the front buffer and emits only the ANSI sequences needed to bring the terminal up to date.
func NewCanvas ¶
func NewCanvas() *Canvas
NewCanvas creates an empty Canvas using DefaultTheme. Call Resize before drawing to it; Application does this automatically on every frame.
func (*Canvas) Clear ¶
func (c *Canvas) Clear()
Clear resets every cell in the back buffer to the screen background, ready for the next frame's widgets to draw over it.
func (*Canvas) DrawCell ¶
DrawCell writes a single glyph at (x, y). Coordinates outside the canvas are silently ignored so widgets do not need to bounds-check every write. Passing ColorNone for bg or fg leaves that color unchanged. s is assumed to occupy exactly one terminal column — every direct caller in this package already passes single-column glyphs (box drawing, block elements); free-form text should go through DrawText instead, which accounts for double-width runes.
func (*Canvas) DrawText ¶
DrawText writes text starting at (x, y), advancing one column for a normal-width rune and two for a double-width one (e.g. CJK), so callers don't need to compute display width themselves.
func (*Canvas) DrawTextBounded ¶
DrawTextBounded writes text like DrawText, but truncates it and appends "…" if it would exceed maxW columns.
func (*Canvas) DrawTextWrapped ¶
DrawTextWrapped writes text, wrapping on whitespace if it exceeds maxW columns. Returns the number of lines drawn.
func (*Canvas) GetCellBg ¶
GetCellBg returns the background color at (x, y), or the theme's screen background for out-of-bounds coordinates. Widgets use this to blend decorations (e.g. window shadows) with whatever is already underneath.
func (*Canvas) Render ¶
func (c *Canvas) Render()
Render diffs the back buffer against what was last drawn to the terminal and writes only the changed cells, minimizing the bytes sent per frame. A resize or the first frame forces every cell to be rewritten.
func (*Canvas) Resize ¶
Resize changes the canvas dimensions, reallocating both buffers and forcing a full redraw on the next Render. It is a no-op when the dimensions are unchanged, since terminal size is polled every frame.
func (*Canvas) Theme ¶
Theme returns the color palette this Canvas currently renders with, so a custom widget defined outside package Graphite (see docs/custom-widgets.md) can read live theme colors in its own DrawRelative the same way every built-in widget reads c.theme — instead of only being able to capture colors once, at construction time, from whatever Theme its caller happened to have on hand.
type Catalog ¶ added in v0.2.0
Catalog maps a translation key to display text in one Locale. A key missing from a Catalog is not an error: Application.T falls back to the library's own built-in Catalog for that Locale, then to English, so a caller only needs to supply the keys it wants to override.
This is the same type — and the same key->text convention — an application uses to translate its own UI: define your own keys (see the Key* constants below for the library's own naming pattern; namespacing your own as "<yourapp>.<area>.<element>", e.g. "myapp.toolbar.save", avoids ever colliding with a "graphite.*" key), call Application.T with them exactly like the library's own code does, and supply a Catalog per Locale via SetTranslations. There is no separate mechanism for "the library's strings" versus "your program's strings" — one Application, one Locale, one T, resolving both through the same per-locale Catalog.
The recommended way to define one is a plain Go source file — a package- level Catalog literal, the same way builtinCatalogs (in this file) does it for the library's own strings — rather than a runtime-loaded data file: `go build`/`go vet` reject a duplicate key or a malformed literal before the program ever runs, the translation compiles straight into the binary with no separate file to ship or possibly go missing at runtime, and it cross-compiles for free along with everything else. See "Translating your own application" in docs/i18n.md for the recommended layout (one file per language under a locales package) and Merge below for composing several Catalog values into one.
func (Catalog) Merge ¶ added in v0.2.0
Merge returns a new Catalog containing c's entries with each of others applied on top, in the order given — a later Catalog's entry for a key overrides an earlier one's, including one of c's own. Neither c nor any of others is modified.
This is how several Go-native Catalog values — e.g. one per file under an application's locales package — compose into one dictionary before a single Application.SetTranslations call, entirely through ordinary Go values and function calls: a typo in a variable name or an accidental duplicate key inside one literal is a compile error, not something discovered by running the program.
type Cell ¶
type Cell struct {
Symbol string
BgColor Color
FgColor Color
// contains filtered or unexported fields
}
Cell is a single terminal character position: its glyph plus foreground and background color.
type Checkbox ¶
type Checkbox struct {
BaseWidget
Label string
Checked bool
OnChange func(checked bool)
}
Checkbox is a focusable boolean toggle with a label.
func NewCheckbox ¶
NewCheckbox creates a Checkbox at (x, y) with the given initial state.
func (*Checkbox) DrawRelative ¶
DrawRelative implements Widget.
func (*Checkbox) HandleEvent ¶
HandleEvent implements Widget: Space, Enter, and mouse clicks all toggle the checkbox.
type Color ¶
type Color int32
Color is a 24-bit truecolor value, packed as (R<<16)|(G<<8)|B. Canvas.Render emits it as a truecolor ANSI SGR sequence, which every terminal capable of running this library already supports (rendering here already depends on the alternate screen buffer and SGR mouse mode, both modern-terminal-only features — there is no legacy 16/256-color fallback path).
const ColorNone Color = -1
ColorNone means "leave the existing color unchanged" — passed to Canvas.DrawCell/DrawText for bg or fg to only touch the other one.
func Hex ¶
Hex parses a "#RRGGBB" or "RRGGBB" string into a Color. It panics on a malformed string, since a bad hex literal is a programming error to be caught at development time, not a runtime condition to recover from.
func (Color) Components ¶
Components unpacks the red, green, and blue bytes of c, for callers that need to inspect or recombine a color (e.g. picking a readable text color against an arbitrary background).
func (Color) ContrastText ¶
ContrastText returns black or white, whichever reads better as text on top of c, using perceived luminance (ITU-R BT.601: 0.299R + 0.587G + 0.114B). This is the exact computation showcase's own contrastText helper (see docs/custom-widgets.md) already duplicated locally; it lives here now so a widget that colors itself from an arbitrary or caller-supplied background — not just a fixed theme field — doesn't have to re-derive it.
func (Color) Darken ¶
Darken returns c scaled towards black by pct (0 keeps c unchanged, 1 returns black). It replaces arithmetic like "subtract 10 from an ANSI code", which has no equivalent once colors are RGB instead of palette indices — e.g. a button wants a dimmer variant of its Danger color when unfocused.
type ComboBox ¶
type ComboBox struct {
BaseWidget
Items []string
Selected int
IsOpen bool
OnSelect func(idx int, item string)
}
ComboBox is a focusable dropdown menu.
func NewComboBox ¶
NewComboBox creates a ComboBox at (x, y) with the given fixed width.
func (*ComboBox) DrawOverlay ¶
DrawOverlay draws the expanded dropdown list if IsOpen is true.
func (*ComboBox) DrawRelative ¶
DrawRelative draws the closed state of the ComboBox.
func (*ComboBox) HandleEvent ¶
HandleEvent processes input.
type Event ¶
Event is a single input notification delivered to the focused widget (for keyboard input) or to whichever widget is hit-tested under the pointer (for mouse input).
type EventType ¶
type EventType int
EventType discriminates the kind of input an Event carries.
const ( EventNone EventType = iota EventKey EventMouseDown // EventMouseDrag is a motion report with the left button held, deliv- // ered only to whichever widget was hit by the preceding EventMouseDown // (see Window's mouse capture), regardless of where the pointer moves. EventMouseDrag // EventMouseUp is a button release. Like EventMouseDrag, it goes to the EventMouseUp EventMouseScrollUp EventMouseScrollDown // EventMouseRightDown is a right-button press. Unlike EventMouseDown it // doesn't move focus or start a mouse capture (there's no corresponding // "right button held" drag or release to capture for) — it's simply // hit-tested and delivered once, the same as a scroll event, for a // widget that wants a secondary click-driven action (e.g. a // context-menu trigger, or a quick toggle) distinct from its primary // EventMouseDown behavior. EventMouseRightDown )
Supported event kinds.
type Fader ¶
type Fader struct {
BaseWidget
ChannelName string
LabelColor Color
Value float64 // 0-100, the fader's own gain position.
Level float64 // 0-100, independent live VU level; see SetLevel.
Clipping bool
ClipThreshold float64 // Level at/above which SetLevel latches Clipping. Zero means 100.
ShowMeter bool
ShowClip bool
ShowMute bool
ShowSolo bool
Muted bool
Soloed bool
Ticks []FaderTick
OnChange func(value float64)
OnMuteChange func(muted bool)
OnSoloChange func(soloed bool)
OnDoubleClick func()
// contains filtered or unexported fields
}
Fader is a vertical channel-strip control: a draggable, clickable gain fader (Value, 0-100), an optional independent VU meter (Level, set via SetLevel — distinct from Value, the way a real mixer's meter shows the actual signal while the fader only sets gain), an optional latching clip LED, and optional icon-only Mute/Solo buttons sharing one row, and a colored channel label. Height defaults to 0, so — like Panel — a Fader stretches to fill whatever vertical space its parent (e.g. Flex) offers; set Height explicitly for a fixed size instead.
func NewFader ¶
NewFader creates a Fader at (x, y) with the given width, channel name, and label color; Height starts at 0 (stretch to fill the parent — see the Fader doc comment). All optional sub-features (meter, clip LED, mute, solo) start enabled; Value starts at 80 (near the "0" mark on the default ticks, matching where a real fader normally sits — not pinned at the top).
func (*Fader) DrawRelative ¶
DrawRelative implements Widget.
func (*Fader) HandleEvent ¶
HandleEvent implements Widget: arrow keys nudge Value, a track click jumps to that position (or fires OnDoubleClick on a fast second click at the same spot), a drag continues updating Value the same way a click would — Window's mouse capture guarantees Fader keeps receiving EventMouseDrag even once the pointer leaves its own bounds — and clicks on the clip LED clear it, and clicks on the buttons row toggle Mute or Solo depending on which half was hit.
func (*Fader) SetLevel ¶
SetLevel sets the independent live VU level (0-100), clamped, and lights Clipping while it reaches ClipThreshold — by default, the same point the meter turns red (faderDangerZonePercent), not only a full 100% peak. Clipping turns off automatically when Level drops back down.
type FaderTick ¶
FaderTick is one labeled position along a Fader's scale. It is purely a visual label — this library has no real audio pipeline, so Percent is just where along the 0-100 track the label is drawn, not a dB conversion.
type Flex ¶
type Flex struct {
BaseWidget
Direction FlexDirection
// Gap is the number of columns/rows of empty space inserted between
// consecutive visible children.
Gap int
// contains filtered or unexported fields
}
Flex is a layout container that distributes space among its children along one axis, CSS-flexbox-style, instead of requiring the caller to compute fixed pixel or percentage offsets by hand. A child with Weight <= 0 gets its own natural size (GetFixedW for FlexRow, GetFixedH for FlexColumn); children with a positive weight split whatever space is left over, proportional to their weight relative to the other weighted children. The cross axis always stretches a child to the container's full size, matching Panel's existing behavior.
func NewFlex ¶
func NewFlex(x, y, w, h int, dir FlexDirection) *Flex
NewFlex creates an empty Flex container at (x, y) with the given size and direction.
func (*Flex) AddChild ¶
AddChild appends a child widget. weight <= 0 sizes it to its own natural size along the main axis; a positive weight instead claims that proportion of the space remaining after every fixed-size sibling.
The weighted share is the box Flex offers the child via DrawRelative — whether the child actually fills it follows the same rule every widget already follows: a widget with a positive fixed Width/Height keeps that size regardless of the offered box (e.g. Label sizes itself to its text), while one left at Width/Height <= 0, or using SetPercentLayout, stretches to fill it. Use Panel (or a nested Flex) as the weighted child when the content itself should grow to fill the allotted space.
func (*Flex) Clear ¶
func (f *Flex) Clear()
Clear removes every child, for containers that rebuild their contents at runtime (e.g. a dynamic list of channels) — clear and re-add is simpler and less error-prone than tracking individual child indices.
func (*Flex) DrawOverlay ¶
DrawOverlay implements Widget.
func (*Flex) DrawRelative ¶
DrawRelative implements Widget. Invisible children are skipped entirely — neither drawn nor given a share of space — so hiding a child closes the gap it would otherwise leave, matching CSS's `display: none`.
func (*Flex) GetChildren ¶
GetChildren implements Widget, letting Window descend into the container when building the focus order and hit-testing the tree.
type FlexDirection ¶
type FlexDirection int
FlexDirection selects the main axis a Flex container lays its children out along.
const ( // FlexRow arranges children left-to-right; each spans the container's // full height. FlexRow FlexDirection = iota // FlexColumn arranges children top-to-bottom; each spans the // container's full width. FlexColumn )
Supported flex directions.
type GphImage ¶
type GphImage struct {
Width int
Height int
Mode PlaybackMode
DelayMs uint16
Frames [][]GphPixel
}
GphImage contains the dimensions, playback metadata, and frames of a GPH file.
func LoadGphFile ¶
LoadGphFile is a convenience function to read a GPH image from the filesystem.
type GroupBox ¶
type GroupBox struct {
BaseWidget
Label string
Children []Widget
}
GroupBox is a Panel that draws a border and a label around its children. Children should be positioned at least at X=1, Y=1 (or Y=2 if they shouldn't overlap the top border).
func NewGroupBox ¶
NewGroupBox creates an empty GroupBox at (x, y) with the given size and label.
func (*GroupBox) DrawOverlay ¶
DrawOverlay implements Widget.
func (*GroupBox) DrawRelative ¶
DrawRelative implements Widget.
func (*GroupBox) GetChildren ¶
GetChildren implements Widget.
type Image ¶
type Image struct {
BaseWidget
Img *GphImage
AutoSize bool
OnFrameUpdate func()
// contains filtered or unexported fields
}
Image is a widget that renders a GphImage.
func NewImage ¶
NewImage creates an Image widget at (x, y) with the exact dimensions of the provided GphImage. If the image is nil, it creates a 1x1 empty widget.
func (*Image) DrawRelative ¶
DrawRelative implements Widget.
func (*Image) NextFrame ¶
func (img *Image) NextFrame()
NextFrame advances the animation to the next frame manually.
func (*Image) Play ¶
func (img *Image) Play(app *Application)
Play starts the animation loop if the image has multiple frames. It stops any currently running animation for this widget.
type InputBox ¶
type InputBox struct {
BaseWidget
Label string
Value string
CursorPos int
OnSubmit func(string)
// Masked renders every character of Value as "•" instead of itself —
// for a password or passphrase field — without changing anything
// about how Value, CursorPos, or editing actually work; HandleEvent
// still operates on the real string, it just never lets Ctrl+C/Ctrl+X
// put it on the OS clipboard (see HandleEvent).
Masked bool
}
InputBox is a single-line, focusable text field with a fixed label, horizontal scrolling, and a visible text cursor.
func NewInputBox ¶
NewInputBox creates an InputBox at (x, y) with the given width and label.
func NewPasswordBox ¶
NewPasswordBox creates an InputBox identical to NewInputBox except its contents render as "•" and never reach the OS clipboard via Ctrl+C/Ctrl+X — for a password or passphrase field.
func (*InputBox) DrawRelative ¶
DrawRelative implements Widget.
func (*InputBox) HandleEvent ¶
HandleEvent implements Widget: arrow keys move the cursor, Backspace and Delete remove the rune behind/under it, and any other printable character is inserted at the cursor. A mouse click moves the cursor to the clicked column, accounting for horizontal scroll.
type KeyCode ¶
type KeyCode int
KeyCode identifies a non-printable key reported by an Event.
const ( KeyNone KeyCode = 0 KeyTab KeyCode = 9 KeyEnter KeyCode = 10 KeyEscape KeyCode = 27 KeySpace KeyCode = 32 KeyBackspace KeyCode = 127 KeyUp KeyCode = 1001 KeyDown KeyCode = 1002 KeyLeft KeyCode = 1003 KeyRight KeyCode = 1004 KeyDelete KeyCode = 1005 KeyCtrlC KeyCode = 1006 KeyCtrlV KeyCode = 1007 KeyCtrlX KeyCode = 1008 KeyF1 KeyCode = 1009 KeyF2 KeyCode = 1010 KeyF3 KeyCode = 1011 KeyF4 KeyCode = 1012 KeyF5 KeyCode = 1013 KeyF6 KeyCode = 1014 KeyF7 KeyCode = 1015 KeyF8 KeyCode = 1016 KeyF9 KeyCode = 1017 KeyF10 KeyCode = 1018 KeyF11 KeyCode = 1019 KeyF12 KeyCode = 1020 KeyInsert KeyCode = 1021 )
Recognized non-printable key codes. Printable characters arrive via Event.CharCode instead, with Key left as KeyNone.
type Label ¶
type Label struct {
BaseWidget
Text string
}
Label draws a single line of static text.
func (*Label) DrawRelative ¶
DrawRelative implements Widget.
type ListBox ¶
type ListBox struct {
BaseWidget
Items []string
Selected int
Scroll int
OnSelect func(int, string)
OnDoubleClick func(int, string)
// contains filtered or unexported fields
}
ListBox is a focusable, scrollable, single-selection list.
func NewListBox ¶
NewListBox creates a ListBox at (x, y) listing items. onSelect, if non-nil, is called with the selected index and text on Enter or a mouse click on a row.
func (*ListBox) DrawRelative ¶
DrawRelative implements Widget.
func (*ListBox) HandleEvent ¶
HandleEvent implements Widget: Up/Down move the selection (scrolling to keep it visible), Enter and a mouse click on a row both fire OnSelect.
type Locale ¶ added in v0.2.0
type Locale string
Locale identifies a UI language as a BCP 47 language tag (e.g. "en", "uk", "pt"). It is a plain string, not a closed enum: SetTranslations accepts any Locale value, including one the library ships no prepared Catalog for, so a caller is never limited to the built-in languages.
const ( LocaleEnglish Locale = "en" LocaleUkrainian Locale = "uk" LocaleRussian Locale = "ru" LocaleGerman Locale = "de" LocaleFrench Locale = "fr" LocaleSpanish Locale = "es" LocalePortuguese Locale = "pt" LocaleItalian Locale = "it" LocalePolish Locale = "pl" LocaleDutch Locale = "nl" LocaleTurkish Locale = "tr" LocaleCzech Locale = "cs" LocaleJapanese Locale = "ja" LocaleChinese Locale = "zh" LocaleKorean Locale = "ko" )
Built-in locales the library ships a prepared Catalog for (see builtinCatalog). These constants exist for convenience and typo safety when selecting one of them; any other Locale value works too, given a Catalog registered via Application.SetTranslations.
type MenuCategory ¶
type MenuItem ¶
MenuItem is one row in a MenuStrip dropdown (or a nested SubItems flyout): a plain clickable item (Label+Action), a separator (Separator true; Label/Action/SubItems all ignored), or a submenu (SubItems non-empty; Action ignored, clicking instead opens a nested flyout of SubItems next to it). Only one level of nesting is supported — an item inside SubItems with its own SubItems is not opened.
type MenuStrip ¶
type MenuStrip struct {
BaseWidget
Categories []MenuCategory
OpenIdx int
// OpenSubIdx is the index within Categories[OpenIdx].Items whose
// SubItems flyout is currently open, or -1 if none is.
OpenSubIdx int
// BgColor overrides the strip's (and its open dropdown's) background;
// ColorNone (the default set by NewMenuStrip) uses the theme's
// BgWidget/BgWindow instead, matching the strip's original
// appearance. FgColor overrides the text color; ColorNone auto-picks
// black or white for contrast against BgColor (via Color.ContrastText)
// once BgColor is itself set, or falls back to the theme's FgWindow
// when neither is set.
BgColor Color
FgColor Color
}
MenuStrip is a top-level horizontal bar containing clickable categories that open dropdowns.
func NewMenuStrip ¶
func NewMenuStrip(categories []MenuCategory) *MenuStrip
NewMenuStrip creates a MenuStrip spanning the full width of whatever contains it, with BgColor/FgColor left at their default (ColorNone, meaning "use the theme").
func (*MenuStrip) DrawOverlay ¶
DrawOverlay implements Widget.
func (*MenuStrip) DrawRelative ¶
DrawRelative implements Widget.
func (*MenuStrip) HandleEvent ¶
HandleEvent implements Widget: clicking a category toggles its dropdown open/closed; clicking a plain item in an open dropdown (or submenu) runs its Action and closes everything; clicking a submenu item (one with SubItems) toggles that submenu instead, leaving the dropdown open; clicking a separator does nothing. Anything else — a click outside every open surface — closes everything, the dropdown's original dismiss-on-outside-click behavior.
type Panel ¶
type Panel struct {
BaseWidget
Children []Widget
FocusIdx int
}
Panel groups child widgets under a shared position and size (typically percentage-based) without being focusable itself; only its children are.
func (*Panel) DrawOverlay ¶
DrawOverlay implements Widget.
func (*Panel) DrawRelative ¶
DrawRelative implements Widget.
func (*Panel) GetChildren ¶
GetChildren implements Widget, letting Window descend into the panel when building the focus order and hit-testing the tree.
type PianoOrientation ¶
type PianoOrientation int
PianoOrientation selects which axis a PianoRoll lays its keys along.
const ( // PianoHorizontal lays keys left-to-right, lowest note on the left — // a conventional piano keyboard. PianoHorizontal PianoOrientation = iota // PianoVertical lays keys bottom-to-top, lowest note at the bottom — // matching the pitch axis of a piano-roll editor or a vertically // mounted keyboard controller. PianoVertical )
Supported PianoRoll orientations.
type PianoRoll ¶
type PianoRoll struct {
BaseWidget
Orientation PianoOrientation
// MinKeys is the minimum number of consecutive MIDI notes (white and
// black combined) always shown, starting at LowestNote — a floor, not
// a cap. If the widget is offered more space than MinKeys needs, more
// notes are added automatically, extending upward in pitch. 25, 37,
// 49, 61, 76, and 88 are the sizes real MIDI keyboard controllers
// ship in (2/3/4/5/6.5/7.25 octaves respectively); 25 is a sensible
// floor matching the smallest common controller.
MinKeys int
// LowestNote is the MIDI note number (0-127, 60 = middle C) of the
// leftmost (horizontal) or bottommost (vertical) key when exactly
// MinKeys are shown.
LowestNote uint8
// KeyMap maps a lowercased typed rune to a semitone offset from
// KeyboardOctaveBase. Defaults to defaultPianoKeyMap(); replace it
// for a different layout, or set entries to remap individual keys.
KeyMap map[rune]int
// KeyboardOctaveBase is the MIDI note KeyMap's offset 0 corresponds
// to. Defaults to LowestNote at construction.
KeyboardOctaveBase uint8
// Velocity is used for notes triggered by mouse or PC-keyboard, which
// have no natural velocity of their own (unlike a real MIDI
// controller, which reports how hard a key was struck).
Velocity uint8
// KeyReleaseTimeout is how long a PC-keyboard-triggered note keeps
// sounding after the last repeat event for its key, before being
// treated as released. Raw terminal input has no true key-up event —
// only a stream of key-down/repeat bytes — so this is a heuristic,
// not an exact measurement: the OS's keyboard repeat rate must be
// faster than this timeout for a held key to sustain correctly.
// Defaults to 150ms, which comfortably outlasts every common OS
// repeat rate without noticeably delaying release on key-up.
KeyReleaseTimeout time.Duration
// OnNoteOn fires the instant a note starts sounding from any source
// (mouse, keyboard, or a NoteOn call from outside, e.g. real MIDI
// input) — not once per source, so mousing down on a key already
// held via the keyboard does not re-trigger it.
OnNoteOn func(note uint8, velocity uint8)
// OnNoteOff fires the instant a note stops sounding from every
// source that was holding it.
OnNoteOff func(note uint8)
// contains filtered or unexported fields
}
PianoRoll is a piano-keyboard widget: it renders a standard white/black key pattern (horizontally or vertically), shows at least MinKeys notes and adds more automatically as its parent offers it more space, and can be played by mouse clicks, the PC keyboard, or driven programmatically — which is how a real MIDI input device is wired in (see the graphite/midi package). Sound is not part of this widget: wire OnNoteOn/OnNoteOff to a synth (see the graphite/audio package) or your own audio code.
func NewPianoRoll ¶
func NewPianoRoll(x, y, w, h int, orientation PianoOrientation, lowestNote uint8) *PianoRoll
NewPianoRoll creates a PianoRoll at (x, y) with the given width/height (either may be <= 0 to stretch — see layout.md), showing at least 25 keys starting at lowestNote.
func (*PianoRoll) DrawRelative ¶
DrawRelative implements Widget.
func (*PianoRoll) HandleEvent ¶
HandleEvent implements Widget: a mouse press/drag plays whichever key is under the pointer (dragging across keys glissandos, releasing the previous key first), a mapped keyboard character plays its note for as long as it keeps repeating (see KeyReleaseTimeout), and Left/Right nudge LowestNote by one semitone, transposing the whole keyboard.
func (*PianoRoll) NoteOff ¶
NoteOff releases note from the external source. See NoteOn for the goroutine-safety note.
func (*PianoRoll) NoteOn ¶
NoteOn marks note as sounding from an external source (e.g. a real MIDI input device — see the graphite/midi package) and highlights its key. Safe to call for a note already sounding from another source; safe to call from any goroutine only via Application.Invoke, like any other widget mutation (see architecture.md's concurrency section) — a MIDI driver's callback runs on its own goroutine, not the render loop's.
type PlaybackMode ¶
type PlaybackMode uint8
PlaybackMode defines how animation frames are played.
const ( PlaybackStatic PlaybackMode = 0 PlaybackLoop PlaybackMode = 1 PlaybackBoomerang PlaybackMode = 2 PlaybackOnce PlaybackMode = 3 )
type ProgressBar ¶
type ProgressBar struct {
BaseWidget
Label string
Progress float32
}
ProgressBar draws a labeled, filled bar showing completion from 0 to 100.
func NewProgressBar ¶
func NewProgressBar(x, y, w int, label string) *ProgressBar
NewProgressBar creates a ProgressBar at (x, y) starting at 0% progress.
func (*ProgressBar) DrawRelative ¶
func (pb *ProgressBar) DrawRelative(c *Canvas, offX, offY, pW, pH int)
DrawRelative implements Widget.
func (*ProgressBar) SetProgress ¶
func (pb *ProgressBar) SetProgress(p float32)
SetProgress sets the completion percentage, clamped to [0, 100].
type RawInputReceiver ¶
RawInputReceiver is implemented by a widget that needs terminal input as raw, undecoded bytes while it has focus — bypassing parseANSI's Event decoding entirely. Terminal (see terminal.go) is the only built-in widget that does: forwarding a shell's own keystrokes byte-for-byte is the whole point of an embedded terminal, and round-tripping them through graphite's own smaller KeyCode vocabulary first would lose anything that vocabulary doesn't happen to cover (application-cursor-mode arrows, exotic modifier combinations, ...).
type Slider ¶
type Slider struct {
BaseWidget
Label string
Min float64
Max float64
Value float64
OnChange func(value float64)
OnDoubleClick func()
// contains filtered or unexported fields
}
Slider is a horizontal draggable control for setting a value within a range.
func NewSlider ¶
NewSlider creates a Slider at (x, y) with the given width. Min and Max define the range of the slider. Value starts at Min.
func (*Slider) DrawRelative ¶
DrawRelative implements Widget.
type Spinner ¶
type Spinner struct {
BaseWidget
Label string
}
Spinner draws an animated braille-style busy indicator next to a label.
func NewSpinner ¶
NewSpinner creates a Spinner at (x, y) sized to fit label.
func (*Spinner) DrawRelative ¶
DrawRelative implements Widget.
type TabStyle ¶
type TabStyle int
TabStyle selects how a TabView renders and whether it accepts focus/input.
type TabView ¶
type TabView struct {
BaseWidget
Tabs []Tab
Active int
Style TabStyle
}
TabView switches between named pages of widgets, showing exactly one at a time.
func NewTabView ¶
NewTabView creates an empty TabView at (x, y) with the given width and style.
func (*TabView) AddTab ¶
AddTab appends a new page and refreshes widget visibility so only the active tab's widgets are shown.
func (*TabView) DrawRelative ¶
DrawRelative implements Widget.
func (*TabView) HandleEvent ¶
HandleEvent implements Widget: Left/Right switch the active tab. No-op for TabTimeline, which is display-only.
func (*TabView) UpdateVisibility ¶
func (tv *TabView) UpdateVisibility()
UpdateVisibility shows the active tab's widgets and hides every other tab's. Call this after changing Active directly.
type Terminal ¶
type Terminal struct {
BaseWidget
// OnExit, if set, is called (from the main loop, via Application.Invoke
// — never directly from readLoop's own goroutine) once the child
// process exits, so a host program can close the tab/pane hosting it.
OnExit func(err error)
// contains filtered or unexported fields
}
Terminal is a widget that runs a shell (or any interactive program) attached to a real pseudo-terminal and renders its output faithfully — including full-screen programs like vim or htop, which need real cursor control and an alternate screen buffer, not just scrolling text.
Getting there needs two things working together: startPTY (pty.go and its per-OS files) gives the child process an actual controlling terminal, and vtScreen (vt100.go) interprets whatever escape sequences it emits into a screen grid. Terminal's own job is gluing those to graphite — rendering the grid via DrawRelative, and forwarding keystrokes back to the child completely undistorted: it implements RawInputReceiver (see app.go) so Application.Run routes it raw bytes straight from the real terminal in front of the user, bypassing graphite's own Event-decoding entirely. Round-tripping through graphite's smaller KeyCode vocabulary first would lose anything that vocabulary doesn't cover — application-cursor-mode arrows, exotic modifier combinations — which is exactly the "distortion" an embedded terminal can't afford.
Known gaps: no scrollback (only the visible grid), and DEC line-drawing character sets aren't translated, so a program that leans on them for box-drawing borders may show the raw designator characters instead.
func NewTerminal ¶
NewTerminal spawns shell (with args) attached to a pseudo-terminal at (x, y) sized w×h — 0 or negative for either follows BaseWidget's usual "stretch to fill the parent" convention, exactly as any other widget's constructor does. The pty/screen themselves still need a real, positive starting size before the first layout pass ever runs, so they start at a sane placeholder (80×24) that DrawRelative immediately resizes to the widget's actually resolved size on the very first frame. app is used solely to deliver OnExit safely via Application.Invoke; Terminal does not otherwise reach into it.
func (*Terminal) Close ¶
Close releases the pty's own resources. It does not wait for or kill the child process — Wait (via Exited, or the pty itself) does that.
func (*Terminal) DrawRelative ¶
DrawRelative implements Widget: resizes the pty/screen to match this frame's resolved size before rendering, so the child sees an accurate terminal size (e.g. after the surrounding layout reflows), then paints every cell and, if the child left the cursor visible, a block cursor.
func (*Terminal) Exited ¶
Exited reports whether the child process has exited, and its result (nil on a clean exit) once it has.
func (*Terminal) HandleEvent ¶
HandleEvent implements Widget. A mouse click just focuses the terminal (Window's own click-to-focus handling does the rest) — no key event ever reaches here while focused, since Application.Run routes those through WriteRaw instead once this widget has focus.
type TextArea ¶
type TextArea struct {
BaseWidget
Text string
Scroll int
CursorPos int // Absolute rune index into Text, not a line-local offset.
}
TextArea is a focusable, scrollable, multi-line text editor with word wrap and a visible cursor.
func NewTextArea ¶
NewTextArea creates an empty TextArea at (x, y) with the given size.
func (*TextArea) DrawRelative ¶
DrawRelative implements Widget.
func (*TextArea) HandleEvent ¶
HandleEvent implements Widget: arrow keys move the cursor (Up/Down by visual line, preserving column where possible), Backspace/Delete/Enter edit the text, printable characters are inserted, and a mouse click moves the cursor to the clicked line and column.
type TextLine ¶
TextLine is one wrapped or newline-delimited line of a TextArea's text, with Start recording its offset (in runes) into the full text so cursor positions can be mapped back and forth between line-local and absolute coordinates.
type Theme ¶
type Theme struct {
BgScreen Color
BgWindow Color
FgWindow Color
BgWidget Color
BgFocused Color
FgFocused Color
Primary Color
Success Color
Danger Color
Warning Color
Disabled Color
FgDisabled Color
// Accent is a secondary accent distinct from Primary, for a program
// that needs to color two different things without one borrowing the
// other's meaning — e.g. Primary for focus/selection and Accent for a
// multi-selection tag marker. No built-in widget reads it; it exists
// for custom widgets (see docs/custom-widgets.md) that need a second
// accent of their own.
Accent Color
// Info is a third accent, distinct from both Primary and Accent, for a
// transient "here's a result" highlight — e.g. a search match — that
// would otherwise have to reuse a color already carrying a different
// meaning (focus, a tag marker). No built-in widget reads it; like
// Accent, it exists for a custom widget that needs its own.
Info Color
}
Theme is the color palette a Canvas renders widgets with.
func DefaultTheme ¶
func DefaultTheme() Theme
DefaultTheme returns the built-in color palette used by a new Canvas until Application.SetTheme overrides it: a GitHub-Dark-inspired scheme (near- black background, soft light-gray text, a blue accent, and green/red/amber semantic colors for success/danger/warning states).
type TodoList ¶
type TodoList struct {
BaseWidget
Items []TodoItem
Selected int
Scroll int
ReadOnly bool
}
TodoList is a scrollable checklist. In read-only mode it ignores input entirely and is meant to be driven programmatically via SetItemState (e.g. to reflect the progress of a background task).
func NewTodoList ¶
NewTodoList creates a TodoList at (x, y) from the given item labels, all starting in TodoPending state.
func (*TodoList) DrawRelative ¶
DrawRelative implements Widget.
func (*TodoList) HandleEvent ¶
HandleEvent implements Widget: Up/Down move the selection, Space/Enter and a mouse click on a row both toggle that row between TodoPending and TodoDone. No-op when ReadOnly.
func (*TodoList) SetItemState ¶
SetItemState sets the state of the item at idx, ignoring out-of-range indices so callers driving this from a background goroutine's progress loop don't need to bounds-check.
type Widget ¶
type Widget interface {
DrawRelative(c *Canvas, offX, offY, pW, pH int)
DrawOverlay(c *Canvas, offX, offY, pW, pH int)
HandleEvent(ev Event)
HitTest(mx, my int) bool
SetFocus(f bool)
CanFocus() bool
HasFocus() bool
GetChildren() []Widget
SetVisible(v bool)
IsVisible() bool
SetEnabled(e bool)
IsEnabled() bool
SetPosition(x, y int)
SetPercentLayout(pctX, pctY, pctW, pctH int)
GetFixedH() int
GetFixedW() int
}
Widget is the contract every UI element implements to participate in layout, drawing, focus, and event routing. Custom widgets are built by embedding BaseWidget and overriding the methods that need non-default behavior.
type Window ¶
type Window struct {
FixedW, FixedH, PctW, PctH int
Title string
Children []Widget
PaddingX, PaddingY int
Chrome WindowChrome
// contains filtered or unexported fields
}
Window is a titled container holding a flat list of top-level children (which may themselves be containers like Panel) and owning focus navigation and event routing for the whole subtree. By default (ChromeBordered) it draws a border, drop shadow, and title, centered on the canvas at a fixed or percentage size — see ChromeBorderless for a full-screen alternative.
func NewFullscreenWindow ¶
func NewFullscreenWindow() *Window
NewFullscreenWindow creates a Window with ChromeBorderless chrome and no padding — it fills the canvas exactly, edge to edge, with no border, shadow, or title bar. Call SetPercentLayout/SetPosition on individual children (or give the window PaddingX/PaddingY) for breathing room; the window itself adds none by default, unlike NewWindow's 4/2.
func NewWindow ¶
NewWindow creates a Window with a fixed size and title, and default padding around its content area.
func (*Window) AddWidget ¶
AddWidget appends widget as a top-level child. If no widget in the window currently has focus, the first focusable widget (including one nested inside widget, if it is a container) becomes focused.
func (*Window) ClearFocus ¶ added in v0.2.1
func (w *Window) ClearFocus()
ClearFocus blurs whichever widget in this window currently has keyboard focus, if any. Call it on a window/modal that's about to be covered by a new one opening on top of it — otherwise a still-focused widget with its own focused-state decoration (e.g. InputBox's cursor block, drawn unconditionally every frame while IsFocused is true) keeps rendering that decoration underneath the new modal, since nothing else about opening a modal touches the widget it steals input from. Application. SetModal calls this the same way it already calls ClearMouseCapture, for the same underlying reason: input routing moves to the new modal, but a widget's own visual state doesn't know that on its own.
func (*Window) ClearMouseCapture ¶
func (w *Window) ClearMouseCapture()
ClearMouseCapture forcefully releases any active mouse capture in this window, preventing mouse up/drag events from being routed to the widget that triggered a modal open.
func (*Window) Draw ¶
Draw renders the window, then its children within the resulting padded content area. With ChromeBorderless (see NewFullscreenWindow), that's the whole canvas with no decoration; the default ChromeBordered instead draws a frame, drop shadow, and title centered on c at a fixed or percentage size.
func (*Window) HandleEvent ¶
HandleEvent routes a mouse or keyboard event to the appropriate widget: a mouse press goes to the deepest widget hit-tested under the pointer and captures the mouse, so the resulting drag/release events go straight to that same widget regardless of where the pointer moves next; a scroll or right-click event is hit-tested and delivered the same way but without moving focus or starting a capture, since neither has a drag/release to capture for; Tab advances focus through the flattened focus order; all other key events go to whichever widget currently has focus. Disabled widgets never receive an event, regardless of what their own HandleEvent does.
func (*Window) HasMouseCapture ¶
HasMouseCapture reports whether a mouse gesture is still in flight — EventMouseDown has hit some widget but the matching EventMouseUp hasn't arrived yet. Application.Run checks this before switching a focused RawInputReceiver's raw-passthrough on: if a gesture that started before focus changed (e.g. a click on a menu item that itself creates and focuses a new Terminal tab) is still open, its trailing EventMouseUp needs to reach the widget that captured it — normally decoded and routed — rather than being redirected to the newly focused widget as raw bytes.
func (*Window) SetPercentSize ¶
SetPercentSize switches the window to a size relative to the canvas instead of FixedW/FixedH.
type WindowChrome ¶
type WindowChrome int
WindowChrome selects how much decoration Window.Draw paints around a window's content.
const ( // ChromeBordered draws a titled border and drop shadow, centered on // the canvas at the window's fixed/percentage size. Window's original // behavior, and still the default (the zero value), so every existing // window is completely unaffected by ChromeBorderless's addition. ChromeBordered WindowChrome = iota // ChromeBorderless fills the entire canvas with no border, shadow, or // title bar — for a full-screen application's main window (e.g. a // commander-style file manager) rather than a floating dialog. // FixedW/FixedH/PctW/PctH are ignored in this mode: the window is // always exactly the canvas size. ChromeBorderless )
Supported chrome modes.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Command showcase exercises every widget Graphite ships, its Flex layout container, and a custom theme, in a single tabbed window.
|
Command showcase exercises every widget Graphite ships, its Flex layout container, and a custom theme, in a single tabbed window. |
