]> gitweb.factorcode.org Git - factor.git/blob - basis/ui/ui-docs.factor
ui.tools.listener.completion: change history completion popup to preserve newlines
[factor.git] / basis / ui / ui-docs.factor
1 USING: classes colors debugger fonts help.markup help.syntax kernel
2 math.rectangles namespaces quotations sequences strings ui.backend
3 ui.gadgets ui.gadgets.books ui.gadgets.grids ui.gadgets.packs
4 ui.gadgets.private ui.gadgets.tracks ui.gadgets.worlds ui.private ui.text
5 vocabs.loader ;
6 IN: ui
7
8 HELP: close-window
9 { $values { "gadget" gadget } }
10 { $description "Close the native window containing " { $snippet "gadget" } "." } ;
11
12 HELP: open-window
13 { $values { "gadget" gadget } { "title/attributes" { "a " { $link string } " or a " { $link world-attributes } " tuple" } } }
14 { $description "Opens a native window containing " { $snippet "gadget" } " with the specified attributes. If a string is provided, it is used as the window title; otherwise, the window attributes are specified in a " { $link world-attributes } " tuple." } ;
15
16 HELP: resize-window
17 { $values { "world" world } { "dim" "a pair of integers: width and height" } }
18 { $description "Resize the native window so that its contents area (called the \"client area\" in Windows) has the specified dimensions." } ;
19
20 HELP: set-fullscreen
21 { $values { "gadget" gadget } { "?" boolean } }
22 { $description "Sets and unsets fullscreen mode for the gadget's world." } ;
23
24 HELP: set-up-window
25 { $values { "world" world } }
26 { $description "Initializes the window that shows the world." } ;
27
28 HELP: ui-thread
29 { $var-description "Holds a reference to the running UI thread. This variable is used to ensure that there can only be one UI thread running at the same time." }
30 { $see-also start-ui-thread } ;
31
32 HELP: ui-running?
33 { $values { "?" boolean } }
34 { $description "Whether the UI is running or not." } ;
35
36 HELP: worlds
37 { $var-description "Global variable holding an association list mapping native window handles to " { $link world } " instances." } ;
38
39 { worlds open-window find-window world-attributes } related-words
40
41 HELP: world-attributes
42 { $values { "world-class" class } { "title" string } { "status" gadget } { "gadgets" sequence } { "pixel-format-attributes" sequence } { "window-controls" sequence } }
43 { $class-description "Tuples of this class can be passed to " { $link open-window } " to control attributes of the window opened. The following attributes can be set:" }
44 { $list
45     { { $snippet "world-class" } " specifies the class of world to construct. " { $link world } " is the default." }
46     { { $snippet "title" } " is the window title." }
47     { { $snippet "status" } ", if specified, is a gadget that will be used as the window's status bar." }
48     { { $snippet "gadgets" } " is a sequence of gadgets that will be placed inside the window." }
49     { { $snippet "pixel-format-attributes" } " is a sequence of " { $link "ui.pixel-formats-attributes" } " that the window will request for its OpenGL pixel format." }
50     { { $snippet "window-controls" } " is a sequence of " { $link "ui.gadgets.worlds-window-controls" } " that will be placed in the window." }
51 } ;
52
53 HELP: fullscreen?
54 { $values { "gadget" gadget } { "?" boolean } }
55 { $description "Queries the gadget's world to see if it is running in fullscreen mode." } ;
56
57 { fullscreen? set-fullscreen } related-words
58
59 HELP: find-windows
60 { $values { "quot" { $quotation ( world -- ? ) } } { "seq" sequence } }
61 { $description "Finds all native windows such that the gadget passed to " { $link open-window } " satisfies the quotation, outputting an empty sequence if no such gadget could be found. The front-most native window is the last in the " { $snippet "seq" } "." } ;
62
63 HELP: find-window
64 { $values { "quot" { $quotation ( world -- ? ) } } { "world/f" { $maybe world } } }
65 { $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." } ;
66
67 HELP: register-window
68 { $values { "world" world } { "handle" "a backend-specific handle" } }
69 { $description "Adds a window to the global " { $link worlds } " variable." }
70 { $notes "This word should only be called by the UI backend. User code can open new windows with " { $link open-window } "." } ;
71
72 HELP: unregister-window
73 { $values { "handle" "a backend-specific handle" } }
74 { $description "Removes a window from the global " { $link worlds } " variable." }
75 { $notes "This word should only be called only by the UI backend, and not user code." } ;
76
77 HELP: (with-ui)
78 { $values { "quot" quotation } }
79 { $contract "Starts the Factor UI." }
80 { $notes "This is a low-level word; user code should call " { $link with-ui } " instead." } ;
81
82 HELP: start-ui
83 { $values { "quot" quotation } }
84 { $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." } ;
85
86 HELP: (open-window)
87 { $values { "world" world } }
88 { $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." }
89 { $notes "This word should not be called directly by user code. Instead, use " { $link open-window } "." } ;
90
91 HELP: raise-window
92 { $values { "gadget" gadget } }
93 { $description "Makes the native window containing the given gadget the front-most window." } ;
94
95 HELP: with-ui
96 { $values { "quot" { $quotation ( -- ) } } }
97 { $description
98   "Calls the quotation, starting the UI if necessary. If starting the UI is necessary, this word does not return and the UI will start after the quotation returns." $nl
99   "While the combinator is running, " { $link ui-running? } " can be used by user code to determine whether it is running in a UI context or not."
100 }
101 { $notes "This word should be used in the " { $link POSTPONE: MAIN: } " word of an application that uses the UI in order for the vocabulary to work when run from either the UI listener (" { $snippet "\"my-app\" run" } ") and the command line (" { $snippet "./factor -run=my-app" } ")." }
102 { $examples "The " { $vocab-link "hello-ui" } " vocabulary implements a simple UI application which uses this word." } ;
103
104 HELP: beep
105 { $description "Plays the system beep sound." } ;
106
107 HELP: system-alert
108 { $values { "caption" string } { "text" string } }
109 { $description "Displays an application-modal alert dialog box with the given caption and text." }
110 { $notes "Since the window raised by this word is modal, all processing in all Factor threads will halt until the dialog is dismissed. In an application that makes full use of the UI framework, it would be more appropriate to display a pane gadget in a Factor window. This word is meant primarily to be used to display errors in deployed applications with minimal dependencies on the UI library, such as games." } ;
111
112 HELP: topmost-window
113 { $values { "world" world } }
114 { $description "Returns the " { $link world } " representing the currently focused window." } ;
115
116 ARTICLE: "ui-glossary" "UI glossary"
117 { $table
118     { "color" { "an instance of " { $link color } } }
119     { "dimension" "a pair of integers denoting pixel size on screen" }
120     { "font" { "an instance of " { $link font } } }
121     { "gadget" { "a graphical element which responds to user input. Gadgets are tuples which (directly or indirectly) inherit from " { $link gadget } "." } }
122     { "label specifier" { "a string, " { $link f } " or a gadget. See " { $link "ui.gadgets.buttons" } } }
123     { "orientation specifier" { "one of " { $link horizontal } " or " { $link vertical } } }
124     { "point" "a pair of integers denoting a pixel location on screen" }
125 } ;
126
127 ARTICLE: "building-ui" "Building user interfaces"
128 "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 } "."
129 { $subsections gadget }
130 "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."
131 { $subsections
132     "ui-geometry"
133     "ui-layouts"
134     "gadgets"
135     "ui-worlds"
136     "ui.gadgets.status-bar"
137 }
138 { $see-also "models" } ;
139
140 ARTICLE: "gadgets" "Pre-made UI gadgets"
141 { $subsections
142     "ui.gadgets.labels"
143     "ui.gadgets.borders"
144     "ui.gadgets.labeled"
145     "ui.gadgets.buttons"
146     "ui.gadgets.sliders"
147     "ui.gadgets.scrollers"
148     "ui.gadgets.editors"
149     "ui.gadgets.menus"
150     "ui.gadgets.panes"
151     "ui.gadgets.presentations"
152     "ui.gadgets.tables"
153 } ;
154
155 ARTICLE: "ui-geometry" "Gadget geometry"
156 "The " { $link gadget } " class inherits from the " { $link rect } " class, and thus all gadgets have a bounding box:"
157 { $subsections "math.rectangles" }
158 "Word for converting from a child gadget's co-ordinate system to a parent's:"
159 { $subsections
160     relative-loc
161     screen-loc
162 }
163 "Hit testing:"
164 { $subsections
165     pick-up
166     children-on
167 } ;
168
169 ARTICLE: "ui-worlds" "Top-level windows"
170 "Opening a top-level window:"
171 { $subsections open-window }
172 "Finding top-level windows:"
173 { $subsections find-window }
174 "Top-level windows are stored in a global variable:"
175 { $subsections worlds }
176 "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:"
177 { $subsections graft* }
178 "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:"
179 { $subsections ungraft* }
180 "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:"
181 { $subsections world }
182 "There is also syntax for defining window words, including a main window that is the entry point for a vocabulary:"
183 { $subsections
184     POSTPONE: WINDOW:
185     POSTPONE: MAIN-WINDOW:
186 } ;
187
188 ARTICLE: "ui-backend" "Developing UI backends"
189 "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."
190 { $subsections
191     "ui-backend-init"
192     "ui-backend-windows"
193 }
194 "UI backends may implement the " { $link "clipboard-protocol" } "." ;
195
196 ARTICLE: "ui-backend-init" "UI initialization and the event loop"
197 "An UI backend is required to define a method on the " { $link (with-ui) } " word. This word should contain backend initialization, together with some boilerplate:"
198 { $code
199     "IN: shells"
200     ""
201     ": ui"
202     "    ... backend-specific initialization ..."
203     "    start-ui"
204     "    ... more backend-specific initialization ..."
205     "    ... start event loop here ... ;"
206 }
207 "The above word must call the following:"
208 { $subsections start-ui }
209 "The " { $link (with-ui) } " word must not return until the event loop has stopped and the UI has been shut down." ;
210
211 ARTICLE: "ui-backend-windows" "UI backend window management"
212 "The high-level " { $link open-window } " word eventually calls a low-level word which you must implement:"
213 { $subsections open-world-window }
214 "This word should create a native window, store some kind of handle in the " { $snippet "handle" } " slot, then call two words:"
215 { $subsections register-window }
216 "The following words must also be implemented:"
217 { $subsections
218     set-title
219     raise-window
220 }
221 "When a world needs to be redrawn, the UI will call a word automatically:"
222 { $subsections draw-world }
223 "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:"
224 { $subsections
225     select-gl-context
226     flush-gl-context
227 }
228 "If the user clicks the window's close box, you must call the following word:"
229 { $subsections close-window } ;
230
231 ARTICLE: "ui-layouts" "Gadget hierarchy and layouts"
232 "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."
233 { $subsections "ui-layout-basics" }
234 "Common layout gadgets:"
235 { $subsections
236     "ui-pack-layout"
237     "ui-track-layout"
238     "ui-grid-layout"
239     "ui-frame-layout"
240     "ui-book-layout"
241 }
242 "Advanced topics:"
243 { $subsections
244     "ui.gadgets.glass"
245     "ui-null-layout"
246     "ui-incremental-layout"
247     "ui-layout-impl"
248 }
249 { $see-also "ui.gadgets.borders" } ;
250
251 ARTICLE: "ui-layout-basics" "Layout basics"
252 "Gadgets are arranged in a hierarchy, and all visible gadgets except for instances of " { $link world } " are contained in a parent gadget."
253 $nl
254 "Managing the gadget hierarchy:"
255 { $subsections
256     add-gadget
257     unparent
258     add-gadgets
259     clear-gadget
260 }
261 "The children of a gadget are available via the "
262 { $snippet "children" } " slot."
263 $nl
264 "Working with gadget children:"
265 { $subsections
266     gadget-child
267     nth-gadget
268     each-child
269     child?
270 }
271 "Working with gadget parents:"
272 { $subsections
273     parents
274     each-parent
275     find-parent
276 }
277 "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."
278 { $subsections
279     relayout
280     relayout-1
281 }
282 "Gadgets implement a generic word to inform their parents of their preferred size:"
283 { $subsections pref-dim* }
284 "To get a gadget's preferred size, do not call the above word, instead use " { $link pref-dim } ", which caches the result." ;
285
286 ARTICLE: "ui-null-layout" "Manual layouts"
287 "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." ;
288
289 ARTICLE: "ui-layout-impl" "Implementing layout gadgets"
290 "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:"
291 { $subsections layout* }
292 "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
293 "Some assorted utility words which are useful for implementing layout logic:"
294 { $subsections
295     pref-dim
296     pref-dims
297     prefer
298     max-dims
299     sum-dims
300 }
301 { $warning
302     "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."
303     $nl
304     "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."
305 } ;
306
307 ARTICLE: "new-gadgets" "Implementing new gadgets"
308 "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."
309 $nl
310 "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" } "):"
311 { $subsections <gadget> }
312 "New gadgets are defined as subclasses of an existing gadget type, perhaps even " { $link gadget } " itself. Direct subclasses of " { $link gadget } " can be constructed using " { $link new } ", however some subclasses may define their own parameterized constructors (see " { $link "parameterized-constructors" } ")."
313 $nl
314 "Further topics:"
315 { $subsections
316     "ui-gestures"
317     "ui-paint"
318     "ui-control-impl"
319     "clipboard-protocol"
320     "ui.gadgets.line-support"
321 }
322 { $see-also "ui-layout-impl" } ;
323
324 ARTICLE: "starting-ui" "Starting the UI"
325 "The main word of a vocabulary implementing a UI application should use a combinator to ensure that the application works when run from the command line as well as in the UI listener:"
326 { $subsections with-ui } ;
327
328 ARTICLE: "ui" "UI framework"
329 "The " { $vocab-link "ui" } " vocabulary hierarchy implements the Factor UI framework. The implementation relies on a small amount of platform-specific code to open windows and receive keyboard and mouse events; UI gadgets are rendered using OpenGL."
330 { $subsections
331     "starting-ui"
332     "ui-glossary"
333     "building-ui"
334     "new-gadgets"
335     "ui-backend"
336 } ;
337
338 ABOUT: "ui"
339
340 HELP: close-button
341 { $description "Asks for a close button to be available for a window. Without a close button, a window cannot be closed by the user and must be closed by the program using " { $link close-window } "." } ;
342
343 HELP: minimize-button
344 { $description "Asks for a minimize button to be available for a window." } ;
345
346 HELP: maximize-button
347 { $description "Asks for a maximize button to be available for a window." } ;
348
349 HELP: resize-handles
350 { $description "Asks for resize controls to be available for a window. Without resize controls, the window size will not be changeable by the user." } ;
351
352 HELP: small-title-bar
353 { $description "Asks for a window to have a small title bar. Without a title bar, the " { $link close-button } ", " { $link minimize-button } ", and " { $link maximize-button } " controls will not be available. A small title bar may have other side effects in the window system, such as causing the window to not show up in the system task switcher and to float over other Factor windows." } ;
354
355 HELP: normal-title-bar
356 { $description "Asks for a window to have a title bar. Without a title bar, the " { $link close-button } ", " { $link minimize-button } ", and " { $link maximize-button } " controls will not be available." } ;
357
358 HELP: textured-background
359 { $description "Asks for a window to have a background that blends seamlessly with the window frame. Factor will leave the window background transparent and pass mouse button gestures not handled directly by a gadget through to the window system so that the window can be dragged from anywhere on its background." } ;
360
361 HELP: dialog-window
362 { $description "Provides a hint to the window manager to create a floating, dialog-style window. Currently, this is only implemented for the GTK backend." } ;
363
364 HELP: WINDOW:
365 { $syntax "WINDOW: window-word { attributes }
366     attribute-code ;" }
367 { $description "Defines a word for the current vocabulary named " { $snippet "window-word" } " that opens a UI window when run. The " { $snippet "attributes" } " specify the key-value pairs of the window's " { $link world-attributes } ". The " { $snippet "attribute-code" } " is run with the " { $snippet "world-attributes" } " on the stack; this allows the word to construct gadget objects to place in the " { $snippet "gadget" } " slot or set other runtime-dependent world attributes." }
368 { $examples
369 "From the " { $vocab-link "hello-ui" } " vocabulary. Creates a window with the title \"Hi\" containing a label reading \"Hello world\":"
370 { $code
371 "USING: accessors ui ui.gadgets.labels ;
372 IN: hello-ui
373
374 WINDOW: hello { { title \"Hi\" } }
375     \"Hello world\" <label> >>gadgets ;"
376 } } ;
377
378 HELP: MAIN-WINDOW:
379 { $syntax "MAIN-WINDOW: window-word { attributes }
380     attribute-code ;" }
381 { $description "Defines a " { $link POSTPONE: MAIN: } " word for the current vocabulary named " { $snippet "window-word" } " that opens a UI window when the vocabulary is " { $link run } ". The " { $snippet "attributes" } " specify the key-value pairs of the window's " { $link world-attributes } ". The " { $snippet "attribute-code" } " is run with the " { $snippet "world-attributes" } " on the stack; this allows the word to construct gadget objects to place in the " { $snippet "gadget" } " slot or set other runtime-dependent world attributes." }
382 { $examples
383 "From the " { $vocab-link "hello-ui" } " vocabulary. Creates a window with the title \"Hi\" containing a label reading \"Hello world\":"
384 { $code
385 "USING: accessors ui ui.gadgets.labels ;
386 IN: hello-ui
387
388 MAIN-WINDOW: hello { { title \"Hi\" } }
389     \"Hello world\" <label> >>gadgets ;"
390 } } ;
391
392 { POSTPONE: WINDOW: POSTPONE: MAIN-WINDOW: } related-words
393
394 ARTICLE: "ui.gadgets.worlds-window-controls" "Window controls"
395 "The following window controls can be placed in a " { $link world } " window:"
396 { $subsections
397     close-button
398     minimize-button
399     maximize-button
400     resize-handles
401     small-title-bar
402     normal-title-bar
403     textured-background
404     dialog-window
405 }
406 "Provide a sequence of these values in the " { $snippet "window-controls" } " slot of the " { $link world-attributes } " tuple you pass to " { $link open-window } "." ;