139 lines
7.1 KiB
Plaintext
139 lines
7.1 KiB
Plaintext
USING: help gadgets gadgets-buttons opengl freetype timers
|
|
models ;
|
|
|
|
ARTICLE: "new-gadgets" "Implementing new gadgets"
|
|
"One of the goals of the Factor UI is to minimize the need to implement new types of gadgets by offering a highly reusable, orthogonal set of building blocks. However, in some cases implementing a new type of gadget is necessary, for example when writing a graphical visualization."
|
|
$terpri
|
|
"Bare gadgets can be constructed directly, which is useful if all you need is a custom appearance with no further behavior (see " { $link "ui-pen-protocol" } "):"
|
|
{ $subsection <gadget> }
|
|
"You can define a new tuple which delegates to a bare gadget:"
|
|
{ $subsection delegate>gadget }
|
|
"Further topics:"
|
|
{ $subsection "ui-gestures" }
|
|
{ $subsection "ui-paint" }
|
|
{ $subsection "ui-control-impl" }
|
|
{ $subsection "clipboard-protocol" }
|
|
{ $subsection "timers" }
|
|
{ $see-also "ui-layout-impl" } ;
|
|
|
|
ARTICLE: "ui-paint" "Customizing gadget appearance"
|
|
"The UI carries out the following steps when drawing a gadget:"
|
|
{ $list
|
|
{ "The " { $link draw-interior } " generic word is called on the value of the " { $link gadget-interior } " slot." }
|
|
{ "The " { $link draw-gadget* } " generic word is called on the gadget." }
|
|
{ "The gadget's visible children are drawn, determined by calling " { $link visible-children } " on the gadget." }
|
|
{ "The " { $link draw-boundary } " generic word is called on the value of the " { $link gadget-boundary } " slot." }
|
|
}
|
|
"Now, each one of these steps will be covered in detail."
|
|
{ $subsection "ui-pen-protocol" }
|
|
{ $subsection "ui-paint-custom" } ;
|
|
|
|
ARTICLE: "ui-pen-protocol" "UI pen protocol"
|
|
"The " { $link gadget-interior } " and " { $link gadget-boundary } " slots of a gadget facilitate easy factoring and sharing of drawing logic. Objects stored in these slots must implement the pen protocol:"
|
|
{ $subsection draw-interior }
|
|
{ $subsection draw-boundary }
|
|
"The default value of these slots is the " { $link f } " singleton, which implements the above protocol by doing nothing."
|
|
$terpri
|
|
"Some other pre-defined implementations:"
|
|
{ $subsection solid }
|
|
{ $subsection gradient }
|
|
{ $subsection button-paint }
|
|
{ $subsection polygon }
|
|
"Custom implementations must follow the guidelines set forth in " { $link "ui-paint-custom" } "." ;
|
|
|
|
ARTICLE: "ui-paint-custom" "Implementing custom drawing logic"
|
|
"The UI uses OpenGL to render gadgets. Custom rendering logic can be plugged in with the " { $link "ui-pen-protocol" } ", or by implementing a generic word:"
|
|
{ $subsection draw-gadget* }
|
|
"Custom drawing code has access to the full OpenGL API in the " { $vocab-link "opengl" } " vocabulary."
|
|
$terpri
|
|
"The UI uses a co-ordinate system where the y axis is oriented down. The OpenGL " { $link GL_MODELVIEW } " matrix is not saved or restored when rendering a gadget. Instead, the origin of the gadget relative to the OpenGL context is stored in a variable:"
|
|
{ $subsection origin }
|
|
"Custom drawing implementations can translate co-ordinates manually, or save and restore the " { $link GL_MODELVIEW } " matrix."
|
|
$terpri
|
|
"OpenGL state must not be altered as a result of drawing a gadget, so any flags which were enabled should be disabled, and vice versa."
|
|
$terpri
|
|
"Gadgets must not draw outside of their bounding box, however clipping is not enforced by default, for performance reasons. This can be changed by setting the " { $link gadget-clipped? } " slot to " { $link t } " in the gadget's constructor."
|
|
$terpri
|
|
"Saving the " { $link GL_MODELVIEW } " matrix and enabling/disabling flags can be done in a clean way using the combinators documented in the following section."
|
|
{ $subsection "gl-utilities" }
|
|
{ $subsection "freetype-utilities" } ;
|
|
|
|
ARTICLE: "gl-utilities" "OpenGL utility words"
|
|
"In addition to the full OpenGL API, the " { $vocab-link "opengl" } " vocabulary includes some utility words to give OpenGL a more Factor-like feel."
|
|
$terpri
|
|
"Wrappers:"
|
|
{ $subsection gl-color }
|
|
{ $subsection gl-vertex }
|
|
{ $subsection gl-translate }
|
|
"Combinators:"
|
|
{ $subsection do-state }
|
|
{ $subsection do-enabled }
|
|
{ $subsection do-attribs }
|
|
{ $subsection do-matrix }
|
|
{ $subsection with-translation }
|
|
{ $subsection make-dlist }
|
|
"Rendering geometric shapes:"
|
|
{ $subsection gl-line }
|
|
{ $subsection gl-fill-rect }
|
|
{ $subsection gl-rect }
|
|
{ $subsection gl-fill-poly }
|
|
{ $subsection gl-poly }
|
|
{ $subsection gl-gradient } ;
|
|
|
|
ARTICLE: "freetype-utilities" "Rendering text"
|
|
"Unlike OpenGL, Factor's FreeType binding only includes the bare essentials, and there is rarely any need to directly call words in the " { $vocab-link "freetype" } " vocabulary directly. Instead, the UI provides high-level wrappers."
|
|
$terpri
|
|
"Fonts are represented by instances of a class:"
|
|
{ $subsection font }
|
|
"Font objects are never constructed directly, and instead are obtained by calling a word:"
|
|
{ $subsection open-font }
|
|
"Measuring text:"
|
|
{ $subsection text-dim }
|
|
{ $subsection string-width }
|
|
{ $subsection char-width }
|
|
"Rendering text:"
|
|
{ $subsection draw-string }
|
|
{ $subsection draw-text } ;
|
|
|
|
ARTICLE: "ui-control-impl" "Implementing controls"
|
|
"A control is a gadget which is linked to an underlying " { $link model } "."
|
|
{ $subsection control }
|
|
"There are two ways to implement a new control. First, an existing gadget can be wrapped in a control:"
|
|
{ $subsection <control> }
|
|
"Second, a new tuple class can be defined, whose instances delegate to controls:"
|
|
{ $subsection delegate>control }
|
|
"Some utility words useful in control implementations:"
|
|
{ $subsection control-model }
|
|
{ $subsection control-value }
|
|
{ $subsection set-control-value }
|
|
{ $see-also "models" } ;
|
|
|
|
ARTICLE: "clipboard-protocol" "Clipboard protocol"
|
|
"Custom gadgets that wish to interact with the clipboard must use the following two generic words to read and write clipboard contents:"
|
|
{ $subsection paste-clipboard }
|
|
{ $subsection copy-clipboard }
|
|
"UI backends can either implement the above two words in the case of an asynchronous clipboard model (for example, X11). If direct access to the clipboard is provided (Windows, Mac OS X), the following two generic words may be implemented instead:"
|
|
{ $subsection clipboard-contents }
|
|
{ $subsection set-clipboard-contents }
|
|
"However, gadgets should not call these words, since they will fail if only the asynchronous method of clipboard access is supported by the backend in use."
|
|
$terpri
|
|
"Access to two clipboards is provided:"
|
|
{ $subsection clipboard }
|
|
{ $subsection selection }
|
|
"These variables may contain clipboard protocol implementations which transfer data to and from the native system clipboard. However an UI backend may leave one or both of these variables in their default state, which is a trivial clipboard implementation internal to the Factor UI." ;
|
|
|
|
ARTICLE: "timers" "Timers"
|
|
"Timers can be added and removed:"
|
|
{ $subsection add-timer }
|
|
{ $subsection remove-timer }
|
|
"Classes must implement a generic word so that their instances can handle timer ticks:"
|
|
{ $subsection tick }
|
|
"Timer gadgets reduce the amount of work required for the common use-case:"
|
|
{ $subsection timer-gadget }
|
|
{ $subsection <timer-gadget> }
|
|
{ $subsection start-timer-gadget }
|
|
{ $subsection stop-timer-gadget }
|
|
"Timers can be used outside of the UI, however they must be initialized with an explicit call, and fired manually:"
|
|
{ $subsection init-timers }
|
|
{ $subsection do-timers } ;
|