]> gitweb.factorcode.org Git - factor.git/blob - basis/ui/ui-docs.factor
d8c816d71750a76fb8954e783adece8ba573244e
[factor.git] / basis / ui / ui-docs.factor
1 USING: help.markup help.syntax strings quotations debugger
2 io.styles namespaces ui.backend ui.gadgets ui.gadgets.worlds
3 ui.gadgets.tracks ui.gadgets.packs ui.gadgets.grids math.geometry.rect ;
4 IN: ui
5
6 HELP: windows
7 { $var-description "Global variable holding an association list mapping native window handles to " { $link world } " instances." } ;
8
9 { windows open-window find-window } related-words
10
11 HELP: open-window
12 { $values { "gadget" gadget } { "title" string } }
13 { $description "Opens a native window with the specified title." } ;
14
15 HELP: set-fullscreen?
16 { $values { "?" "a boolean" } { "gadget" gadget } }
17 { $description "Sets and unsets fullscreen mode for the gadget's world." } ;
18
19 HELP: fullscreen?
20 { $values { "gadget" gadget } { "?" "a boolean" } }
21 { $description "Queries the gadget's world to see if it is running in fullscreen mode." } ;
22
23 { fullscreen? set-fullscreen? } related-words
24
25 HELP: find-window
26 { $values { "quot" "a quotation with stack effect " { $snippet "( world -- ? )" } } { "world" "a " { $link world } " or " { $link f } } }
27 { $description "Finds a native window such that the gadget passed to " { $link open-window } " satisfies the quotation, outputting " { $link f } " if no such gadget could be found. The front-most native window is checked first." } ;
28
29 HELP: register-window
30 { $values { "world" world } { "handle" "a baackend-specific handle" } }
31 { $description "Adds a window to the global " { $link windows } " variable." }
32 { $notes "This word should only be called by the UI backend.  User code can open new windows with " { $link open-window } "." } ;
33
34 HELP: unregister-window
35 { $values { "handle" "a baackend-specific handle" } }
36 { $description "Removes a window from the global " { $link windows } " variable." }
37 { $notes "This word should only be called only by the UI backend, and not user code." } ;
38
39 HELP: ui
40 { $description "Starts the Factor UI." } ;
41
42 HELP: start-ui
43 { $description "Called by the UI backend to initialize the platform-independent parts of UI. This word should be called after the backend is ready to start displaying new windows, and before the event loop starts." } ;
44
45 HELP: (open-window)
46 { $values { "world" world } }
47 { $description "Opens a native window containing the given world. This grafts the world by calling " { $link graft } ". Each world can only be displayed in one top-level window at a time." }
48 { $notes "This word should not be called directly by user code. Instead, use " { $link open-window } "." } ;
49
50 HELP: ui-try
51 { $values { "quot" quotation } }
52 { $description "Calls the quotation. If it throws an error, opens a window with the error and restores the data stack." }
53 { $notes "This is essentially a graphical variant of " { $link try } "." } ;
54
55 ARTICLE: "ui-glossary" "UI glossary"
56 { $table
57     { "color specifier"
58         { "an array of four elements, all numbers between 0 and 1:"
59             { $list
60                 "red"
61                 "green"
62                 "blue"
63                 "alpha - 0 is completely transparent, 1 is completely opaque"
64             }
65         }
66     }
67     { "dimension" "a pair of integers denoting pixel size on screen" }
68     { "font specifier"
69         { "an array of three elements:"
70             { $list
71                 { "font family - one of " { $snippet "serif" } ", " { $snippet "sans-serif" } " or " { $snippet "monospace" } }
72                 { "font style - one of " { $link plain } ", " { $link bold } ", " { $link italic } " or " { $link bold-italic } }
73                 "font size in points"
74             }
75         }
76     }
77     { "gadget" { "a graphical element which responds to user input. Gadgets are tuples which (directly or indirectly) inherit from " { $link gadget } "." } }
78     { "label specifier" { "a string, " { $link f } " or a gadget. See " { $link "ui.gadgets.buttons" } } }
79     { "orientation specifier" { "one of " { $snippet "{ 0 1 }" } " or " { $snippet "{ 1 0 }" } ", with the former denoting vertical orientation and the latter denoting horizontal. Using a vector instead of symbolic constants allows these values to be directly useful in co-ordinate calculations" } }
80     { "point" "a pair of integers denoting a pixel location on screen" }
81 } ;
82
83 ARTICLE: "building-ui" "Building user interfaces"
84 "A gadget is a graphical element which responds to user input. Gadgets are implemented as tuples which (directly or indirectly) inherit from " { $link gadget } ", which in turn inherits from " { $link rect } "."
85 { $subsection gadget }
86 "Gadgets are arranged in a hierarchy, and all visible gadgets except for instances of " { $link world } " are contained in a parent gadget, stored in the " { $snippet "parent" } " slot."
87 { $subsection "ui-geometry" }
88 { $subsection "ui-layouts" }
89 { $subsection "gadgets" }
90 { $subsection "ui-windows" }
91 { $see-also "models" } ;
92
93 ARTICLE: "gadgets" "Pre-made UI gadgets"
94 { $subsection "ui.gadgets.labels" }
95 { $subsection "gadgets-polygons" }
96 { $subsection "ui.gadgets.borders" }
97 { $subsection "ui.gadgets.labelled" }
98 { $subsection "ui.gadgets.buttons" }
99 { $subsection "ui.gadgets.sliders" }
100 { $subsection "ui.gadgets.scrollers" }
101 { $subsection "gadgets-editors" }
102 { $subsection "ui.gadgets.panes" }
103 { $subsection "ui.gadgets.presentations" }
104 { $subsection "ui.gadgets.lists" } ;
105
106 ARTICLE: "ui-geometry" "Gadget geometry"
107 "The " { $link gadget } " class inherits from the " { $link rect } " class, and thus all gadgets have a bounding box:"
108 { $subsection rect }
109 "Rectangles can be taken apart:"
110 { $subsection rect-loc }
111 { $subsection rect-dim }
112 { $subsection rect-bounds }
113 { $subsection rect-extent }
114 "New rectangles can be created:"
115 { $subsection <zero-rect> }
116 { $subsection <rect> }
117 { $subsection <extent-rect> }
118 "More utility words for working with rectangles:"
119 { $subsection offset-rect }
120 { $subsection rect-intersect }
121 { $subsection intersects? }
122
123 ! "A gadget's bounding box is always relative to its parent. "
124 ! { $subsection gadget-parent }
125
126 "Word for converting from a child gadget's co-ordinate system to a parent's:"
127 { $subsection relative-loc }
128 { $subsection screen-loc }
129 "Hit testing:"
130 { $subsection pick-up }
131 { $subsection children-on } ;
132
133 ARTICLE: "ui-windows" "Top-level windows"
134 "Opening a top-level window:"
135 { $subsection open-window }
136 "Finding top-level windows:"
137 { $subsection find-window }
138 "Top-level windows are stored in a global variable:"
139 { $subsection windows }
140 "When a gadget is displayed in a top-level window, or added to a parent which is already showing in a top-level window, a generic word is called allowing the gadget to perform initialization tasks:"
141 { $subsection graft* }
142 "When the gadget is removed from a parent shown in a top-level window, or when the top-level window is closed, a corresponding generic word is called to clean up:"
143 { $subsection ungraft* }
144 "The root of the gadget hierarchy in a window is a special gadget which is rarely operated on directly, but it is helpful to know it exists:"
145 { $subsection world } ;
146
147 ARTICLE: "ui-backend" "Developing UI backends"
148 "None of the words documented in this section should be called directly by user code. They are only of interest when developing new UI backends."
149 { $subsection "ui-backend-init" }
150 { $subsection "ui-backend-windows" }
151 "UI backends may implement the " { $link "clipboard-protocol" } "." ;
152
153 ARTICLE: "ui-backend-init" "UI initialization and the event loop"
154 "An UI backend is required to define a word to start the UI:"
155 { $subsection ui }
156 "This word should contain backend initialization, together with some boilerplate:"
157 { $code
158     "IN: shells"
159     ""
160     ": ui"
161     "    ... backend-specific initialization ..."
162     "    start-ui"
163     "    ... more backend-specific initialization ..."
164     "    ... start event loop here ... ;"
165 }
166 "The above word must call the following:"
167 { $subsection start-ui }
168 "The " { $link ui } " word must not return until the event loop has stopped and the UI has been shut down."
169 $nl
170 "The event loop must not block, since otherwise other Factor threads and I/O will not run. Instead, it should poll for pending events, then call " { $link ui-wait } "." ;
171
172 ARTICLE: "ui-backend-windows" "UI backend window management"
173 "The high-level " { $link open-window } " word eventually calls a low-level word which you must implement:"
174 { $subsection open-world-window }
175 "This word should create a native window, store some kind of handle in the " { $snippet "handle" } " slot, then call two words:"
176 { $subsection register-window }
177 "The following words must also be implemented:"
178 { $subsection set-title }
179 { $subsection raise-window }
180 "When a world needs to be redrawn, the UI will call a word automatically:"
181 { $subsection draw-world }
182 "This word can also be called directly if the UI backend is notified by the window system that window contents have been invalidated. Before and after drawing, two words are called, which the UI backend must implement:"
183 { $subsection select-gl-context }
184 { $subsection flush-gl-context }
185 "If the user clicks the window's close box, you must call the following word:"
186 { $subsection close-window } ;
187
188 HELP: raise-window
189 { $values { "gadget" gadget } }
190 { $description "Makes the native window containing the given gadget the front-most window." } ;
191
192 ARTICLE: "ui-layouts" "Gadget hierarchy and layouts"
193 "A layout gadget is a gadget whose sole purpose is to contain other gadgets. Layout gadgets position and resize children according to a certain policy, taking the preferred size of the children into account. Gadget hierarchies are constructed by building up nested layouts."
194 { $subsection "ui-layout-basics" }
195 "Common layout gadgets:"
196 { $subsection "ui-pack-layout" }
197 { $subsection "ui-track-layout" }
198 { $subsection "ui-grid-layout" }
199 { $subsection "ui-frame-layout" }
200 { $subsection "ui-book-layout" }
201 "Advanced topics:"
202 { $subsection "ui-null-layout" }
203 { $subsection "ui-incremental-layout" }
204 { $subsection "ui-layout-impl" }
205 { $see-also "ui.gadgets.borders" } ;
206
207 ARTICLE: "ui-layout-basics" "Layout basics"
208 "Gadgets are arranged in a hierarchy, and all visible gadgets except for instances of " { $link world } " are contained in a parent gadget."
209 $nl
210 "Managing the gadget hierarchy:"
211 { $subsection add-gadget }
212 { $subsection unparent }
213 { $subsection add-gadgets }
214 { $subsection clear-gadget }
215 "The children of a gadget are available via the "
216 { $snippet "children" } " slot. " "Working with gadget children:"
217 { $subsection gadget-child }
218 { $subsection nth-gadget }
219 { $subsection each-child }
220 { $subsection child? }
221 "Working with gadget parents:"
222 { $subsection parents }
223 { $subsection each-parent }
224 { $subsection find-parent }
225 "Adding children, removing children and performing certain other operations initiates relayout requests automatically. In other cases, relayout may have to be triggered explicitly. There is no harm from doing this several times in a row as consecutive relayout requests are coalesced."
226 { $subsection relayout }
227 { $subsection relayout-1 }
228 "Gadgets implement a generic word to inform their parents of their preferred size:"
229 { $subsection pref-dim* }
230 "To get a gadget's preferred size, do not call the above word, instead use " { $link pref-dim  } ",  which caches the result." ;
231
232 ARTICLE: "ui-null-layout" "Manual layouts"
233 "When automatic layout is not appropriate, gadgets can be added to a parent with no layout policy, and then positioned and sized manually by setting the " { $snippet "loc" } " field." ;
234
235 ARTICLE: "ui-layout-impl" "Implementing layout gadgets"
236 "The relayout process proceeds top-down, with parents laying out their children, which in turn lay out their children. Custom layout policy is implemented by defining a method on a generic word:"
237 { $subsection layout* }
238 "When a " { $link layout* } " method is called, the size and location of the gadget has already been determined by its parent, and the method's job is to lay out the gadget's children. Children can be positioned and resized by setting a pair of slots, " { $snippet "loc" } " and " { $snippet "dim" } "." $nl
239 "Some assorted utility words which are useful for implementing layout logic:"
240 { $subsection pref-dim }
241 { $subsection pref-dims }
242 { $subsection prefer }
243 { $subsection max-dim }
244 { $subsection dim-sum }
245 { $warning
246     "When implementing the " { $link layout* } " generic word for a gadget which inherits from another layout, the " { $link children-on } " word might have to be re-implemented as well."
247     $nl
248     "For example, suppose you want a " { $link grid } " layout which also displays a popup gadget on top. The implementation of " { $link children-on } " for the " { $link grid } " class determines which children of the grid are visible at one time, and this will never include your popup, so it will not be rendered, nor will it respond to gestures. The solution is to re-implement " { $link children-on } " on your class."
249 } ;
250
251 ARTICLE: "new-gadgets" "Implementing new gadgets"
252 "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."
253 $nl
254 "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" } "):"
255 { $subsection <gadget> }
256 "New gadgets are defined as subclasses of an existing gadget type, perhaps even " { $link gadget } " itself. A parametrized constructor should be used to construct subclasses:"
257 { $subsection new-gadget }
258 "Further topics:"
259 { $subsection "ui-gestures" }
260 { $subsection "ui-paint" }
261 { $subsection "ui-control-impl" }
262 { $subsection "clipboard-protocol" }
263 { $see-also "ui-layout-impl" } ;
264
265 ARTICLE: "ui" "UI framework"
266 { $subsection "ui-glossary" }
267 { $subsection "building-ui" }
268 { $subsection "new-gadgets" }
269 { $subsection "ui-backend" } ;
270
271 ABOUT: "ui"