component

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 28, 2022 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package component features a framework, inspired by React and Redux, that allows you to extend the basic ui package with custom Components on top of plain ui Elements.

Index

Constants

This section is empty.

Variables

View Source
var Element = Define(func(props Properties) Instance {
	var element *ui.Element

	UseState(func() interface{} {
		return uiCtx.CreateElement()
	}).Inject(&element)

	Defer(func() {
		element.Destroy()
	})

	var data ElementData
	props.InjectData(&data)

	element.SetEssence(data.Essence)
	if data.Enabled.Specified {
		element.SetEnabled(data.Enabled.Value)
	}
	if data.Visible.Specified {
		element.SetVisible(data.Visible.Value)
	}
	if data.Focusable.Specified {
		element.SetFocusable(data.Focusable.Value)
	}
	if data.IdealSize.Specified {
		element.SetIdealSize(data.IdealSize.Value)
	}
	element.SetLayout(data.Layout)
	element.SetPadding(data.Padding)
	element.SetLayoutConfig(props.LayoutData())

	return Instance{
		element:  element,
		children: props.Children(),
	}
})

Element represents the most basic component, which is translated to an ui Element. All higher-order components will eventually boil down to an Element.

View Source
var StoreProvider = Define(func(props Properties) Instance {
	var (
		data   StoreProviderData
		stores []*Store
	)
	props.InjectData(&data)

	UseState(func() interface{} {
		result := make([]*Store, len(data.Entries))
		for i, entry := range data.Entries {
			result[i] = CreateStore(entry.Reducer, entry.InitialValue)
		}
		return result
	}).Inject(&stores)

	Defer(func() {
		for _, store := range stores {
			store.Destroy()
		}
	})

	return New(Element, func() {
		WithData(ElementData{
			Layout: ui.NewFillLayout(),
		})
		WithChildren(props.children)
	})
})

StoreProvider is a convenience component that manages the lifecycle of a set of Stores.

Using StoreProvider can be used as an optimization, since the lifecycle of the Stores is determined by the lifecycle of the given StoreProvider. If certain Store should be available only in the context of a given component hierarchy (e.g. a wizard dialog) it might make sense to wrap that hierarchy with such a StoreProvider.

Should you go down this route, however, make sure that only nested components try to access Stores that are managed by this StoreProvider.

Functions

func After

func After(duration time.Duration, fn func())

After will schedule a closure function to be run after the specified amount of time. The closure is guaranteed to run on the UI thread and the framework ensures that the closure will not be called if the component had been destroyed in the meantime.

Normally, you would use this function within a Once block or as a result of a callback. Not doing so would cause the closure function to be scheduled on every rendering of the component. As the framework is free to render a component at any time it deems necessary, it is unlikely that a user would like to have a function scheduled in an undeterministic way.

func CreateImage added in v0.3.0

func CreateImage(img image.Image) *ui.Image

CreateImage delegates to the UI window context to create the specified image.

func Defer

func Defer(fn func())

Defer can be used to perform a cleanup action. The framework will issue one final render of a component before it gets destroyed. During that final render all closure functions specified via the Defer function will be invoked in the respective order.

Similar to Once, Defer can be used multiple times within a component's render function.

func Dispatch

func Dispatch(action interface{})

Dispatch is the mechanism through which Stores get modified. An action is provided and all Reducers attempt to process the action. Should a reducer change it's Store's value then all connected components are reconciled.

func GetFont

func GetFont(family, style string) *ui.Font

GetFont retrieves the font with the specified family and style.

Keep in mind that the necessary fonts should have been loaded via OpenFontCollection beforehand, otherwise this method will panic if it is unable to find the requested font.

func Initialize

func Initialize(window *ui.Window, instance Instance)

Initialize wires the framework to the specified ui Window. The specified instance will be the root component used.

func InjectContext

func InjectContext(target interface{})

InjectContext retrieves the appropriate context and assigns it to target.

The specified target must be a pointer to the type that was used in RegisterContext.

func InjectStore

func InjectStore(target interface{})

InjectStore is a helper function that allows one to discover and access and arbitrary Store's value.

The function uses the type of the referenced value by the target pointer to determine which Store should be used.

func IsEqualData added in v0.3.0

func IsEqualData(old, new interface{}) bool

IsEqualData compares if the two data objects are equal

func Once

func Once(fn func())

Once can be used to perform an initialization action in a component's render function. During subsequent renders for the same component instance, the specified closure function will not be called.

You can use Once multiple times within a component's render function and all closure functions will be called in the respective order.

func OpenFontCollection

func OpenFontCollection(uri string)

OpenFontCollection delegates to the UI window context to open the specified font collection.

func OpenImage

func OpenImage(uri string) *ui.Image

OpenImage delegates to the UI window context to open the specified image.

func RegisterContext

func RegisterContext(value interface{})

RegisterContext registers a data structure that will be accessible from all components.

If used, this method should be use during bootstrapping and should not be called from within components.

The context is stored according to its type and there can be only one call per struct type. Once a context is set it is persisted for the whole lifecycle of the framework.

Contexts should be used only for global configurations that will not change, like graphics handles or translation functions.

func Schedule

func Schedule(fn func())

Schedule will schedule a closure function to run as soon as possible on the UI thread.

Normally this would be used when a certain processing is being performed on a separate go routine and the result needs to be passed back to the UI thread.

The framework ensures that the closure will not be called if the component had been destroyed in the meantime.

func UseLifecycle added in v0.3.0

func UseLifecycle(constructor func(handle LifecycleHandle) Lifecycle, target ...interface{})

func Window

func Window() *ui.Window

Window returns the underlying ui Window object.

func WithCallbackData

func WithCallbackData(callbackData interface{})

WithCallbackData specifies the callback data to be passed to the component during instantiation.

Callback data is a mechanism for one component to listen for events on instanced components.

As callback data is expected to be a struct of function fields, they are not comparable in Go and as such cannot follow the lifecycle of data or layout data.

func WithChild

func WithChild(key string, instance Instance)

WithChild adds a child to the given component. The child is appended to all previously registered children via the same method.

The key property is important. If in a subsequent render a component's child changes key or component type, the old one will be destroyed and a new one will be created. As such, to maintain a more optimized rendering and to prevent state loss, children should have a key assigned to them.

func WithChildren

func WithChildren(children []Instance)

WithChildren sets the children for the given component. Keep in mind that any former children assigned via WithChild are replaced.

func WithContext

func WithContext(context interface{})

WithContext can be used during the instantiation of an Application in order to configure a context object.

This is a helper function in place of RegisterContext. While currently not enforced, you should use this function during the instantiation of your root component. Using it at a later point during the lifecycle of your application could indicate an improper usage of contexts. You may consider using reducers and global state instead.

func WithData

func WithData(data interface{})

WithData specifies the data to be passed to the component during instantiation.

Your data should be comparable in order to enable optimizations done by the framework. If you'd like to pass functions, in case of callbacks, they can be passed through callback data.

func WithLayoutData

func WithLayoutData(layoutData interface{})

WithLayoutData specifies the layout data to be passed to the component during instantiation.

LayoutData is kept separate by the framework as it is expected to have a different lifecycle (changes might be rare) and as such can be optimized.

Your layout data should be comparable in order to enable optimizations done by the framework.

Types

type BaseController added in v0.3.0

type BaseController struct {
	// contains filtered or unexported fields
}

func (*BaseController) Alter added in v0.3.0

func (c *BaseController) Alter(fn func() error) error

func (*BaseController) NotifyChanged added in v0.3.0

func (c *BaseController) NotifyChanged()

func (*BaseController) Subscribe added in v0.3.0

type BaseLifecycle added in v0.3.0

type BaseLifecycle struct {
}

func (*BaseLifecycle) OnCreate added in v0.3.0

func (l *BaseLifecycle) OnCreate(props Properties)

func (*BaseLifecycle) OnDestroy added in v0.3.0

func (l *BaseLifecycle) OnDestroy()

func (*BaseLifecycle) OnUpdate added in v0.3.0

func (l *BaseLifecycle) OnUpdate(props Properties)

type CallbackMapFunc

type CallbackMapFunc func(props Properties) interface{}

CallbackMapFunc controls how a connected component's data is calculated.

type Component

type Component struct {
	// contains filtered or unexported fields
}

Component represents a definition for a component.

func Connect

func Connect(delegate Component, mapping ConnectMapping) Component

Connect is the mechanism through which a Component gets wired to the global Stores. A connected component will get invalidated when one of the Stores gets changed.

The Connect method is used to wrap an existing Component and the mapping configuration can be used to adjust the delegate component's data and callback data based on the Store state.

func Controlled added in v0.3.0

func Controlled(delegate Component) Component

func Define

func Define(fn ComponentFunc) Component

Define can be used to describe a new component. The provided component function (or render function) will be called by the framework to initialize, reconcicle, or destroy a component instance.

func ShallowCached

func ShallowCached(delegate Component) Component

ShallowCached can be used to wrap a component and optimize reconciliation by avoiding the rerendering of the component if the data and layout data are equal to their previous values when shallowly (==) compared.

type ComponentFunc

type ComponentFunc func(props Properties) Instance

ComponentFunc holds the logic and layouting of the component.

type ConnectMapping

type ConnectMapping struct {

	// Data, if specified, controls the data to be passed to the
	// delegate component. If nil, then the original data is passed through.
	Data DataMapFunc

	// Callback, if specified, controls the callback data to be passed to the
	// delegate component. If nil, then the original callback data is passed
	// through.
	Callback CallbackMapFunc
}

ConnectMapping is a configuration mechanism to wire a connected component to its delegate.

type Controller added in v0.3.0

type Controller interface {
	Subscribe(callback ControllerCallback) ControllerSubscription
	Alter(func() error) error
	NotifyChanged()
}

func NewBaseController added in v0.3.0

func NewBaseController() Controller

type ControllerCallback added in v0.3.0

type ControllerCallback func(controller Controller)

type ControllerSubscription added in v0.3.0

type ControllerSubscription interface {
	Unsubscribe()
}

type DataMapFunc

type DataMapFunc func(props Properties) interface{}

DataMapFunc controls how a connected component's data is calculated.

type ElementData

type ElementData struct {
	Essence   ui.Essence
	Enabled   optional.Bool
	Visible   optional.Bool
	Focusable optional.Bool
	IdealSize optional.Size
	Padding   ui.Spacing
	Layout    ui.Layout
}

ElementData is the struct that should be used when configuring an Element component's data.

type Instance

type Instance struct {
	// contains filtered or unexported fields
}

Instance represents the instantiation of a given Component.

func New

func New(component Component, setupFn func()) Instance

New instantiates the specified component. The setup function is used to apply configurations to the component in a user-friendly manner.

Note: creating an instance with New does not necessarily mean that a component will be freshly instantiated. If this occurs during rendering the framework will reuse former instances when possible.

func (Instance) Key added in v0.3.0

func (i Instance) Key() string

Key returns the child key that is registered for this Instance in case the Instance was created as part of a WithChild directive.

type Lifecycle added in v0.3.0

type Lifecycle interface {
	OnCreate(props Properties)
	OnUpdate(props Properties)
	OnDestroy()
}

func NewBaseLifecycle added in v0.3.0

func NewBaseLifecycle() Lifecycle

type LifecycleHandle added in v0.3.0

type LifecycleHandle struct {
	// contains filtered or unexported fields
}

func (LifecycleHandle) NotifyChanged added in v0.3.0

func (h LifecycleHandle) NotifyChanged()

type Overlay added in v0.3.0

type Overlay struct {
	// contains filtered or unexported fields
}

func OpenOverlay added in v0.3.0

func OpenOverlay(instance Instance) Overlay

func (*Overlay) Close added in v0.3.0

func (o *Overlay) Close()

type Properties

type Properties struct {
	// contains filtered or unexported fields
}

Properties is a holder for all data necessary to render a component.

func (Properties) CallbackData

func (p Properties) CallbackData() interface{}

CallbackData returns the callback data that can be used by the component to notify its instantiator regarding key events.

func (Properties) Children

func (p Properties) Children() []Instance

Children returns all the child instances that this component should host.

func (Properties) Data

func (p Properties) Data() interface{}

Data returns the configuration data needed to render the component.

func (Properties) InjectCallbackData

func (p Properties) InjectCallbackData(target interface{})

InjectCallbackData is a helper function that injects the CallbackData into the specified target, which should be a pointer to the correct type.

func (Properties) InjectData

func (p Properties) InjectData(target interface{})

InjectData is a helper function that injects the Data into the specified target, which should be a pointer to the correct type.

func (Properties) InjectLayoutData

func (p Properties) InjectLayoutData(target interface{})

InjectLayoutData is a helper function that injects the LayoutData into the specified target, which should be a pointer to the correct type.

func (Properties) InjectOptionalCallbackData

func (p Properties) InjectOptionalCallbackData(target, defaultValue interface{})

InjectOptionalCallbackData is a helper function that injects the CallbackData into the specified target, which should be a pointer to the correct type or if there is no callback data, it injects the default one.

func (Properties) InjectOptionalData

func (p Properties) InjectOptionalData(target, defaultValue interface{})

InjectOptionalData is a helper function that injects the Data into the specified target, which should be a pointer to the correct type of if there is no data, it injects the default one.

func (Properties) InjectOptionalLayoutData

func (p Properties) InjectOptionalLayoutData(target, defaultValue interface{})

InjectOptionalLayoutData is a helper function that injects the LayoutData into the specified target, which should be a pointer to the correct type or if there is no layout data, it injects the default one.

func (Properties) LayoutData

func (p Properties) LayoutData() interface{}

LayoutData returns the layout data needed to layout the component.

type Reducer

type Reducer func(store *Store, action interface{}) interface{}

Reducer is a mechanism through which a Store's value is changed. It is sent actions and is required to return the changed value according to the specified action. If the Reducer returns the old state of the Store, then it is considered that the action is not applicable for this Reducer.

type State

type State struct {
	// contains filtered or unexported fields
}

State represents a persistent state of a component. Every render operation for a component would return the same sequence of states.

func UseState

func UseState(fn func() interface{}) *State

UseState registers a new State object to the given component.

During component initialization, the closure function will be called to retrieve an initial value to be assigned to the state.

The order in which this function is called inside a component's render function is important. As such, every component render should issue exactly the same UseState calls and in the exacly the same order.

func (*State) Get

func (s *State) Get() interface{}

Ge returns the current value stored in this State.

func (*State) Inject

func (s *State) Inject(target interface{}) *State

Inject is a helper function that can be used to inject the value of this state to a variable of the correct type. The specified target needs to be a pointer to the type of the value that was stored.

func (*State) Set

func (s *State) Set(value interface{})

Set changes the value stored in this State. Using this function will force the component to be scheduled for reconciliation.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store represents a state that can cross component boundaries, which allows multiple components to share the same source of truth.

func CreateStore

func CreateStore(reducer Reducer, initialValue interface{}) *Store

CreateStore creates a new Store instance.

The specified reducer will be responsible for handling dispatched actions and adjusting the store's state.

The initialValue should be of the same type that the reducer will operate on and can be used to initialize the Store.

Note that similarly to Contexts, there can only be one Store instance per value type. Unlike Contexts, however, Stores are intended to have their value change throughout the lifecycle of the application.

func (*Store) Destroy

func (s *Store) Destroy()

Destroy releases this Store and the value that it manages. A destroyed store will no longer be discoverable.

func (*Store) Get

func (s *Store) Get() interface{}

Get returns the value stored in the Store.

func (*Store) Inject

func (s *Store) Inject(target interface{})

Inject is a helper function that allows one to inject the Store's value directly into a variable referenced via the target pointer.

type StoreProviderData

type StoreProviderData struct {

	// Entries contains the definition of all Stores that should be managed
	// by the given StoreProvider.
	Entries []StoreProviderEntry
}

StoreProviderData is the data necessary to instantiate a StoreProvider.

Note that the StoreProvider caches the Stores it creates and a reconciliation with a different data will be ignored.

type StoreProviderEntry

type StoreProviderEntry struct {

	// Reducer specifies the Reducer that will be passed to CreateStore.
	Reducer Reducer

	// InitialValue specifies the initialValue that will be passed to CreateStore.
	InitialValue interface{}
}

StoreProviderEntry represents a single Store instance.

func NewStoreProviderEntry

func NewStoreProviderEntry(reducer Reducer, initialValue interface{}) StoreProviderEntry

NewStoreProviderEntry is a helper function to quickly create a StoreProviderEntry value.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL