1 <ibex-doc title="The Ibex Reference" subtitle="Nitrogen Release" author="Adam Megacz" email="adam@ibex.org">
3 <!-- ----------------------------------------------------------------------- -->
4 <section title="Introduction">
7 If you are reading the html version of this document and are
8 thinking of printing it out, you might be interested in the nicely
9 typeset <link url="reference.pdf" text="pdf version"/> produced
13 This document is a __reference__. It is not a
14 __specification__ or a
17 This document does not guide the user gently through examples (as a
18 tutorial would), and it doesn't provide enough detail and formality
19 for a third party to construct a compatible re-implementation of the
20 Ibex Core (as a specification would).
22 Rather, the goal of this document is to completely describe every
23 aspect of the environment that the Ibex Core provides to client
24 applications, from the bottom up. If you want to be an Ibex expert,
25 this is the right document to read. It is assumed that you are already
26 familiar with XML and with either JavaScript or ECMAscript.
28 If you need to use or rely on some behavior you notice in the Ibex
29 Core, but which is not clearly defined here, please post to <link
30 url="http://lists.ibex.org/listinfo/users" text="the users mailing list"/>.
32 <section title="Key Concepts">
34 <definition term="The Core">
35 Ibex itself; the native code (or Java bytecode) that runs on
36 the client. This term does not include the **Wildebeest**
37 or the **UI**</definition>
39 <definition term="The UI / The Application">
40 A set of files (mostly XML, JavaScript, and PNG images)
41 bundled up in a zip archive, ending with the "[[.ibex]]"
42 extension. Together, these files specify the appearance and
43 behavior of the application's user interface.
46 <definition term="The Server">
47 We will use the term "the server" to refer to any other
48 computer which the client makes XML-RPC or SOAP calls
49 to. Note that it is possible for the client and server to be
50 the same machine.</definition>
52 <definition term="Wildebeest">
53 This is a very small piece of code that is downloaded the
54 first time a client uses Ibex. It downloads the Ibex core,
55 verifies its signature, and launches it with the appropriate
56 parameters indicating where to find the initial UI.
57 Wildebeest works differently on every platform, and is outside
58 the scope of this document.</definition>
60 <definition term="put/write">
61 In ECMAscript, when you change the value of a property on an
62 object, you are **putting** to that property, or
63 **writing** to it. For example, the ECMAscript expression
64 "[[foo.bar = 5]]" **puts** the value 5 to the bar
65 property on object foo.</definition>
67 <definition term="get/read">
68 In ECMAscript, when you access the value of a property on an
69 object, you are **getting** that property, or
70 **reading** from it. For example, the ECMAscript
71 expression "[[return (3 + foo.bar)]]" **gets** the
72 value of bar property on object foo and then adds 3 to it
73 before returning the result.</definition>
75 <definition term="JavaScript">
76 We will use the terms JavaScript and ECMAScript
77 interchangeably in this document. The Ibex interpreter is not
78 completely ECMA-compliant, however (see <link
79 appendix="ECMAscript compliance"/> for details).
84 <section title="Life Cycle of an Ibex Application">
86 <image url="lifecycle.pdf" caption="The Lifecycle of an Ibex Application"/>
88 A user typically begins an Ibex session by clicking on a link to
89 an Ibex application. This link serves the {\tt launch.html} file
90 to the user's browser, which in turn downloads the appropriate
91 {\it Wildebeest} -- currently either an ActiveX Control
92 (Win32/MSIE), XPInstaller (Mozilla), or Signed Applet (all
95 The Wildebeest downloads the appropriate core for the user's
96 machine and verifies its digital signature. It then launches the
97 core, which downloads the UI (an [[.ibex]] archive), loads it,
98 applies the [[main.t]] template (found in the archive), and
99 renders it onto the screen, running any associated JavaScript
102 The user interacts with the application by clicking and moving the
103 mouse, and by pressing keys on the keyboard. These actions trigger
104 fragments of JavaScript code which are designated to handle events.
105 This JavaScript code can then relay important information back to the
106 server using XML-RPC or SOAP, or it can modify the structure and
107 properties of the user interface to change its appearance, thereby
108 giving feedback to the user.
110 The Ibex core quits when the last remaining surface has been destroyed.
115 <section title="Surfaces">
117 <image url="offscreen.pdf" width="2in"
118 caption="An Ibex surface positioned at (83,0)"/>
119 Each top-level window in an Ibex UI is called a
120 **surface**. There are two kinds of surfaces: **frames**,
121 which usually have a platform-specific titlebar and border, and
122 **windows**, which never have any additional platform-specific
125 Whenever we refer to the size or position
126 of a surface, we are referring to the size or position of the
127 UI-accessible portion of the surface; this does not include any
128 platform-specific decorations. This means that if you set the
129 position of a frame to (0,0), the platform-specific titlebar will
130 actually be off the screen on most platforms (it will be above and
131 to the left of the top-left corner of the screen).
133 Surfaces are not actual JavaScript objects; you cannot obtain a
134 reference to a surface. However, each surface is uniquely identified
135 by its **root box**, described in the next section.
139 <section title="Boxes">
141 A **box** is the fundamental unit from which all Ibex user
142 interfaces are built. Boxes can contain other boxes (referred to as
143 its **children**). Each surface has a single box associated with
144 it called the **root box**; the root box and its children (and
145 its children's children, and so on) form the surface's **box
148 There are three ways to think of a box:
151 As a rendered visualization on the screen (the "**Visual Representation**")
153 As a JavaScript object (the "**Object Representation**")
155 As as an XML tag (the "XML Template Representation").
159 <image url="threeviews.pdf" caption="The three representations of an Ibex box"/>
161 All three representations are equally valid, and being able to
162 figure out what an action in one representation would mean in terms
163 of the other two representations is crucial to a solid understanding
169 <section title="The XML Template Representation">
171 A template (discussed in the next section) is an XML file which acts
172 as a blueprint for constructing a tree of boxes. We call this
173 construction process **applying**, since unlike
174 **instantiation** in object-oriented programming systems, you
175 always apply a template to a pre-existing box, and you can apply
176 multiple templates to the same box.
178 Each XML tag corresponds to a single box, or to another template
179 which will be applied to that box. For example, a [[scrollbar]]
180 template, when applied, will construct a tree of boxes which has the
181 visual appearance and behavior of a scrollbar.
183 Although it is useful to think of the XML tags as being boxes, keep
184 in mind that the XML representation is only a blueprint for
185 constructing a tree of JavaScript objects. Once the template has
186 been instantiated, the XML is effectively "thrown away", and
187 JavaScript code is free to alter the boxes. Once the process of
188 applying a template is complete, Ibex completely forgets the fact
189 that it has applied a particular template to a particular box. One
190 consequence of this approach is that if you think of templates as
191 classes, then Ibex has no equivalent for Java's [[instanceof]]
194 Each template is an XML document whose root element is
195 [[<ibex>]]. Here is a sample template file:
198 <ibex xmlns:lib="ibex.lib">
201 This is a cool widget.
204 // this code is executed only once
205 static = { instances : [] };
207 // this element applies the ibex.lib.focusable template
211 static.instances.push(thisbox);
212 <ui:box id="container"/>
221 The following two namespaces are predefined and need not be declared
224 <definition term="meta">
225 [[http://xmlns.ibex.org/meta]]
227 This will be referred to as the "[[meta]] namespace" in the
228 remainder of this document.
231 <definition term="ui">
232 [[http://xmlns.ibex.org/ui]]
234 This will be referred to as the "[[ui]] namespace" in the
235 remainder of this document.
238 Additionally, the default namespace for the document will be set to
239 the template's package FIXME.
241 <section title="Static Code">
244 If the root [[<ibex>]] element contains any non-whitespace
245 text content, this text is interpreted as JavaScript code and is
246 executed the first time the template is referenced. This code is
247 executed in a fresh scope containing two predefined properties:
249 <definition term="ibex">
250 The Ibex Object (described in <ref section="The Ibex Object"/>)
253 <definition term="static">
254 A reference to this template's **static object**, which is
255 initially [[null]]. The static object can be accessed (read
256 and written) from both static scripts as well as instance
257 scripts in a particular template. FIXME
261 If the root <t><ibex></t> element contains any non-whitespace
262 text content, this text is interpreted as JavaScript code and is
263 executed the first time the template is referenced. This code is
264 executed in a fresh scope containing two predefined properties:
266 <definition term="ibex">
267 The Ibex Object (described in <ref section="The Ibex Object"/>)
270 <definition term="static">
271 A reference to this template's <i>static object</i>, which is
272 initially <t>null</t>. The static object can be accessed (read
273 and written) from both static scripts as well as instance
274 scripts in a particular template. FIXME
277 <!-- _______________________________________________________________________ -->
278 <section title="Layout and Rendering">
284 <section title="Metadata">
286 Any immediate children of the root element which are in the
287 [[meta]] namespace are treated as metadata and are exempted from
288 the rest of the template application process. Currently only one
289 type of metadata element is defined:
292 [[<meta:doc>]]: structured documentation for the
298 <section title="Other Elements">
300 All remaining children of the root element are treated as elements
301 to be **applied** to the box, in the order in which they appear
302 in the file using the following procedure.
304 <remark text="While this process outlined below sounds very
305 complex, it actually works pretty intuitively. The
306 description below is given in great detail since
307 most applications will wind up being unintentionally
308 dependent on subtle features of this process.
309 However, most of the time you can just pretend that
310 the XML tags and the boxes are the same thing."/>
312 <heading title="Intuitive Description"/>
316 During a box initialization, script-private references to a
317 box's descendants with [[id]] attributes are placed on the
318 box. These references allow scripts on that box to easily refer
319 to descendant nodes created by the template in which the script
320 appears. For example, these two blocks of code have exactly the
325 <ui:box id="foo"/> <ui:box/>
326 $foo.color = "red"; var $foo = this[0];
331 <heading title="Precise Description"/>
333 To apply an XML tag [[__x__]] to a box [[__b__]], perform the following
334 operations, in this order:
336 <list type="ordered">
338 Allocate a fresh scope [[__s__]] whose parent scope is
341 Process each child element or text segment of [[__x__]]
342 in the order they appear in the document:
346 Treat each text segment [[__t__]] as JavaScript code
347 and execute it with [[__s__]] as the root scope.
349 For each child element [[__x'__]] of [[__x__]]:
352 Create a new box [[__b'__]].
354 If the name of tag [[__x'__]] is not
355 "[[box]]" in the [[ui]] namespace, prepend the
356 tag's namespace identifier uri (if any) to the name of
357 the tag, and use the result as a key to retrieve a
358 property from the root stream (defined later).
359 Interpret the resulting stream as a template and apply
360 that template to [[__b'__]].
362 (recursively) apply [[__x'__]] to [[__b'__]].
364 If [[__x'__]] has an [[id]] attribute, declare a variable
365 in [[__s__]] whose name is the value of the [[id]]
366 attribute, prefixed with the [[$]] character, and whose
369 Copy any [[$]]-variables created during the application
370 of [[__x'__]] into scope [[__s__]].
372 Append [[__b'__]] as the last child of [[__b__]].
376 Apply any attributes on [[__x__]] to [[__b__]], except for
377 [[id]]. Since XML specifies that the order of attributes
378 cannot be significant, Ibex processes attributes in
379 alphabetical order by attribute name. For example, if
380 [[__x__]] has the attribute [[foo="bar"]], then the
381 equivalent of the statement [[B.foo="bar";]] will be
382 performed, with the following exceptions:
385 If the value portion of the attribute is the string
386 "[[true]]", put the boolean [[true]]. If the
387 value is "[[false]]", put the boolean [[false]].
389 If the value is a valid ECMAscript number, put it as a
390 number (instead of a string).
392 If the value begins with a dollar sign ([[$]]),
393 retrieve the value of the corresponding variable in
394 [[__s__]] and use that value instead.
396 If the value begins with a dot ([[.]]), prepend the
397 attributes' namespace identifier uri (if any) and
398 interpret the remainder as a property to be retrieved from
399 the root stream (defined later).
403 <heading title="Initialization Invariants"/>
405 The last two steps are referred to as the **initialization** of the
406 node. There are two important aspects of this ordering to be aware of:
408 <list type="unordered">
410 A given box will be fully initialized before its parent is
411 given a reference to that box. This way, parents can be
412 certain that they will never wind up accessing a box when it
413 is in a partially-initialized state.
415 Attributes are applied **after** scripts are run so that
416 the attributes will trigger any **traps** (defined later)
417 placed by the script.
425 <!-- ----------------------------------------------------------------------- -->
426 <section title="Layout and Rendering">
428 Each box occupies a rectangular region on the surface. The visual
429 appearance of a surface is created by rendering each box in its tree.
430 Unless the [[clip]] attribute is [[false]], each box will
431 clip its childrens' visual representations to its own, so that the
432 children appear "confined to" the parent. Children are rendered after
433 their parents so they appear "on top of" their parents.
435 Each box has two major visual components, each with subcomponents:
439 <definition term="path">
441 A box's [[path]] consists of zero or more lines and curves.
442 The path may be filled with a color, gradient, or texture, and
443 may be stroked with a line of a given thickness and color. If
444 the path is not specified, it defaults to the perimiter of the
445 box. [**Note: Vector Graphics support (including the ability
446 to set the [[path]] property to anything other than the
447 default) is currently not implemented**].
452 an associated [[strokecolor]], which is a color
454 an associated [[strokewidth]], which is a number
455 specifying the width of the stroke. [**Note: Vector
456 Graphics support (including the [[strokewidth]]
457 property) is currently not implemented**]
459 a [[fill]], which is either a color, gradient, or
464 <definition term="text">
466 Each box also has a single line of [[text]], whose
467 appearance is determined by its:
470 associated [[font]], which can be any font supported by
471 the <link url="http://www.freetype.org" text="FreeType2"/>
474 an associated [[fontsize]] in **pixels**
476 an associated [[textcolor]]
480 These eight components plus the size of a box fully specify its
481 appearance. Every single box you see in Ibex is drawn only on the
482 basis of these components and its size.
484 The size and position of every box is determined by its
485 properties, its childrens' sizes, and its parent's size and
486 position. Box layout and rendering happens in four phases:
487 **packing**, **constraining**, **placing**, and
488 **rendering**. The Core is careful to only perform a phase on
489 a box if the box has changed in a way that invalidates the work
490 done the last time that phase was performed. The packing and
491 constraining phases are performed in a single traversal of the
492 tree (packing is preorder, constraining is postorder), and the
493 placing and rendering phases are performed in a second traversal
494 of the tree (first placing, then rendering, both preorder).
496 For brevity, the rest of this chapter deals only with width and
497 columns. Height and rows is treated identically and independently.
498 Also, it is important to note that the term **minimum width** is
499 not the same thing as the property [[minwidth]], although they
502 <heading title="The Size of the Root Box"/>
504 When the user resizes a window, Ibex changes the root box's
505 [[maxwidth]] and [[maxheight]] to match the size chosen by
506 the user and then determines the root box's size using the same sizing
507 rules it uses for other boxes.
509 Ibex will always attempt to prevent the
510 user from making the surface smaller than the root box's
511 [[minwidth]] and [[minheight]]. If the [[hshrink]] or
512 [[vshrink]] flag is set, Ibex will try to prevent the user from
513 resizing the surface at all. However, not all platforms give Ibex
514 enough control to do this.
516 <heading title="The alignment point"/>
518 When talking about positioning, we will often refer to the
521 If the [[align]] property is "[[center]]", then the
522 alignment point is the center of the box.
524 If the [[align]] property is "[[topleft]]",
525 "[[bottomleft]]", "[[topright]]", or
526 "[[bottomright]]", then the alignment point is
527 corresponding corner of the box.
529 If the [[align]] property is "[[top]]",
530 "[[bottom]]", "[[right]]", or "[[left]]", then
531 the alignment point is middle of the corresponding edge of the
534 <section title="Packing">
536 A grid of **cells** is created within the parent. If the
537 parent's [[cols]] property is set to 0, the cell grid has an
538 infinite number of columns. Either [[cols]] or [[rows]]
539 must be zero, but not both.
541 If a child's [[visible]] property is [[false]], it does
542 not occupy any cells (and is not rendered). Otherwise, each child
543 occupies a rectangular set of cells [[child.colspan]] cells
544 wide and [[child.rowspan]] cells high.
546 The Core iterates over the cells in the grid in the following
547 order: if [[rows]] is 0, the Core iterates across each column
548 before proceeding to the next row; otherwise rows come before
549 columns. At each cell, the Core attempts to place the **first
550 remaining unplaced child's** top-left corner in that cell
551 (with the child occupying some set of cells extending down and
552 to the right of that cell). If the parent has a fixed number of
553 columns and the child's [[colspan]] exceeds that limit, the
554 child is placed in column zero regardless, but only occupies the
555 available set of cells (it does not "hang off the end" of the
556 box). <image url="layout.pdf" width="1in"/>
561 <ui:box id="2" rowspan="2" />
562 <ui:box id="3" colspan="2" />
564 <ui:box id="5" colspan="2" />
570 <section title="Constraining">
572 Each box's minimum width is computed recursively as the
578 The width of the box's [[text]] (after applying the
579 box's [[transform]]) [**Note: Vector Graphics support
580 (including the [[transform]] property) is currently not
583 The width of the box's path (after applying the box's
584 [[transform]]) **if the box is [[packed]]**.
586 The minimum width of the children in each row.
589 If a box's [[hshrink]] property is set to
590 [[true]], the box's maximum width is the same as its
591 minimum width; otherwise it is the box's
596 <section title="Placing">
598 <heading title="Non-Packed Boxes"/>
600 Each non-packed box is transformed according to the parent's
601 [[transform]] property and then positioned so that its alignment
602 point is [[(child.x, child.y)]] pixels from the corresponding
603 edge/corner/center of its parent.
605 <heading title="Packed Boxes"/>
607 Ibex formulates a set of constraints for placing a box's
608 **packed** children as follows:
611 - A box's width can be no greater than the sum of the
613 - The sum of a set of colums cannot be smaller than the
614 minimum width of a box that spans them.
615 - The sum of the widths of the parents' columns will be at
616 least as large as the parent's width is (but possibly
620 Subject to these two unbreakable constraints, Ibex searches for
621 a solution which will optimize the following three goals,
622 prioritized from most important to least important:
625 - (__Most Important__) The sum of all columns will be a close
626 to the parent's with as possible (ie as small as possible)
627 - Ibex will attempt to make a set of columns no wider than
628 the [[maxwidth]] of a box spanning them.
629 - (__Least Important__) Ibex will attempt to make all
630 columns the same width.
633 Each packed box is then placed within the set of cells that it
634 spans. Usually the box will exactly fill this rectangle; if it
635 does not (due to [[maxwidth]] or minimum width constraints), the
636 box's will be placed so that its alignment point coincides with
637 the alignment point of that rectangle of cells.
641 <section title="Rendering">
643 Boxes are rendered in a depth-first, pre-order traversal. Note that
644 this may cause a non-packed box to overlap its siblings.
646 <list type="ordered">
648 If the box's [[transform]] property is non-null, the
649 coordinate space is transformed accordingly for the rest of
650 this phase and for the rendering of all children. [**Note:
651 Vector Graphics support (including the [[transform]]
652 property) is currently not implemented**].
654 If the box is packed and has a non-[[null]] path, the
655 path is translated such that the alignment point of the path's
656 bounding box coincides with the box's alignment point (both
657 alignment points are determined by the box's [[align]]
660 If a box has a path, that path is filled with the color,
661 gradient, or image specified by the [[fill]] property and
662 stroked with the color and width specified by the
663 [[strokecolor]] and [[strokewidth]] properties.
665 If the box has a non-null [[text]] attribute,
666 the text is rendered in [[font]] with size
667 [[fontsize]] and color [[textcolor]]. The text is
668 then translated such that the alignment point of the text's
669 bounding box coincides with the box's alignment point (both
670 alignment points are determined by the box's [[align]]
673 The box's children are rendered (pre-order traversal).
680 <!-- ----------------------------------------------------------------------- -->
681 <section title="Box Properties">
683 Each box is a full-fledged ECMAscript object, and can store
684 key-value pairs as properties. Some of these keys have special
685 meaning, which will be explained later. Each box's numeric
686 properties hold its **child boxes**.
688 <section title="Rendering Properties">
690 Every box has several special properties which control how it is
691 drawn. In general, if you put an
692 invalid value to a special property, no action will be taken -- the
695 <property name="strokecolor" type="string" default="clear">
697 If the value is a 5-character hex string ([[#RGB]]),
698 7-character hex string ([[#RRGGBB]]), 9-character hex
699 string ([[#AARRGGBB]]), the box's stroke color will be set
702 If the value is one of the <link
703 url="http://www.color.org/ICC-1A_1999-04.PDF"
704 text="ICC"/> colors (the same set of color names
705 supported by SVG), the stroke color be set to that color.
707 If the value is [[null]], the stroke color will be set
708 to clear ([[#00000000]]).
711 <property name="strokewidth" type="int" default="1">
712 The width (in pixels) to stroke the path with.
715 <property name="fill">
716 This property can be set to any of the values specified for
718 Alternatively, if the value written is an object, its stream
719 will be read and interpreted as a PNG, GIF, or JPEG image,
720 which will become the texture for this box, and the box's
721 [[minwidth]] and [[minheight]] properties will be
722 automatically set to the dimensions of the image.
725 <property name="path" type="string" default='""'>
726 The box's path. The grammar and feature set supported are
727 identical to that specified in <link
728 url="http://www.w3.org/TR/SVG11/paths.html" text="SVG 1.1,
732 <property name="text" type="string" default='""'>
733 The box's text; writing [[null]] to this property sets it
737 <property name="textcolor" type="number" default="black">
738 The color in which to render the font; accepts the same values as [[strokecolor]].
741 <property name="font" type="stream" default=".ibex.ui.font.sansserif">
742 When an object is written to this property, its stream is read
743 using the <link url="http://www.freetype.org" text="FreeType 2 library"/>,
744 and the resulting font is used to render the
748 <property name="fontsize" type="number" default="10">
749 The size (in points) to render the text.
754 <section title="Layout Properties">
756 <property name="shrink" type="boolean" default="false">
757 If set to [[true]], this box will shrink
758 (horizontally/vertically/both) to the smallest size allowed by
759 its children and the bounding box of its path.
762 <property name="x y" type="integer" default="varies">
763 If the box is a root box, this is the (x/y)-coordinate of the
764 surface; otherwise it is the distance between the parent's
765 alignment point and the corresponding corner/edge/center of
769 <property name="minwidth minheight" type="integer" default="0">
770 The desired minimum width and height.
773 <property name="maxwidth maxheight" type="integer" default="ibex.ui.maxdim">
774 The desired maximum width and height.
777 <property name="width height" type="integer">
778 When read, this is the current (width/height) of this box.
779 Writing to this property is equivalent to writing to
780 **both** the minimum and maximum (width/height).
783 <property name="cols rows" type="integer" default="0">
784 The number of (columns/rows) in which to lay out the children of this
785 box. If set to zero, the number of (columns/rows) is unconstrained.
786 Either [[rows]] or [[cols]] must be zero. If
787 [[0]] is written to [[cols]] when [[rows]] is
788 [[0]], the write is ignored. If a nonzero value is
789 written to [[cols]] when [[rows]] is nonzero,
790 [[rows]] is set to [[0]], and vice versa.
793 <property name="colspan rowspan" type="integer" default="1">
794 The number of (columns/rows) that this box spans within its parent.
797 <property name="align" type="string" default="center">
798 Determines the box's alignment point for positioning its text,
799 texture, path, and children.
802 <property name="visible" type="boolean" default="true">
803 If set to [[false]], this box will be rendered as if its
804 width and height were zero. If this is a root box, the
805 associated surface will be hidden.
807 When reading from this property, the value [[false]] will
808 be returned if this box **or any of its ancestors** is not
809 visible. Thus it is possible to write [[true]] to a box's
810 [[visible]] property and then read back [[false]].
813 <property name="packed" type="boolean" default="true">
814 The layout strategy for this box. If set to [[true]], the
815 box occupies no cells and is laid out independently of its
821 <section title="Child Control Properties">
823 <property name="redirect" type="box" default="thisbox">
824 Writing to this property sets the box's redirect target. This
825 property cannot be read from, and can only be written to if
826 the value being written is a **descendant** of the current
829 If a box has a non-null redirect target, reads and writes to
830 any of the other properties in this section will be forwarded
831 to the redirect target.
833 The [[redirect]] attribute is very useful for hiding the
834 internal structure of a widget, and for allowing widgets to act as
835 "smart" containers for other widgets. For example, a menu widget might
836 have an invisible child as its redirect target; this way, when boxes
837 representing items on the menu are added as children of the menu
838 widget, they do not appear until the menu is pulled down.
841 <property name="numeric properties" type="int" default="">
842 The **n**th child of box [[b]] can be accessed by reading from
843 [[b[n]]]. The **n**th child can be removed by writing
844 [[null]] to [[b[n]]] (the child will become parentless). A
845 new child can be inserted **before** the **n**th child by
846 writing it to [[b[n]]]; if the value written is already a child of
847 [[b]], it will be removed from [[b]] first. It is important
848 to note that this behavior is different from ECMAscript arrays --
849 writing a non-[[null]] value to [[b[n]]] does not eliminate
850 the **n**th child; it merely shifts it over one position.
851 __Note:__ Unlike most JavaScript objects, enumerating a Box's
852 properties with the JavaScript [[for..in]] construct will
853 enumerate **only** the box's children and not any other properties.
856 <property name="clip" type="boolean" default="true">
857 If [[true]], the visual representation of this box's
858 children will be clipped to the boundaries of this box.
859 __Note:__ setting this property to [[false]] imposes a
860 substantial performance penalty.
863 <property name="numchildren" type="integer" default="0">
864 The number of children this box has.
868 <property name="surface" type="" default="null">
870 If this box has a parent, this property returns
871 [[**parent**.surface]]; otherwise it returns null.
872 This property is a simple building block that the widget
873 library uses to implement more complex functionality such as
874 focus control and popups.
879 <section title="Other Box Properties">
881 <property name="cursor" type="string" default="null">
882 The shape that the cursor should take when inside this
883 box. Valid values are: "[[default]]" , "[[wait]]",
884 "[[crosshair]]", "[[text]]", "[[hand]]", and
885 "[[move]]", as well as resizing cursors"[[east]]",
886 "[[west]]", "[[north]]", "[[south]]",
887 "[[northwest]]", "[[northeast]]",
888 "[[southwest]]", and "[[southeast]]". Note that on
889 some platforms, resize cursors for opposite directions (such
890 as [[northwest]] and [[southeast]] are the
892 If a box's cursor is [[null]], its parent's cursor will
893 be used. If the root box's cursor is null, the
894 "[[default]]" cursor will be used.
897 <property name="static" type="object" default="N/A">
898 Reading from this property will return the parent scope used
899 to execute the [[<static/>]] block of the template
900 in which the currently-executing code resides.
903 <property name="thisbox" type="box" default=" ">
904 Returns a reference to the box itself.
905 If [[null]] is written to this property, and this box is
906 the root box of a surface, the box will be detached and the
907 surface destroyed. If this box has a parent, it will be
908 detached from its parent.
911 <property name="indexof()" type="function" default=" ">
912 This property is actually a function; invoking
913 [[parent.indexof(child)]] will return the numerical index
914 of [[child]] in [[parent]] if [[child]] is a
915 child of [[parent]] (or [[parent]]'s redirect
916 target), and [[-1]] otherwise. Writing to this property
920 <property name="distanceto()" type="function" default=" ">
921 This property is actually a function; invoking
922 [[box.distanceto(otherbox)]] will return an object with two
923 properties, [[x]] and [[y]], containing the horizontal
924 and vertical distance between the two boxes (negative if
925 [[otherbox]] is to the left of / above [[box]]). This
926 can be used to determine the relative placement of two boxes
927 on different branches of the box tree.
932 <section title="Root Box Properties">
934 The following special properties are only meaningful on the root box
937 <property name="Focused">
938 The value [[true]] is put to this property on the root box
939 when the surface gains the input focus, and [[false]] when
940 the surface loses the input focus. Reading from this value will
941 return [[true]] if the surface is focused and [[false]]
942 if it is not. Putting [[true]] to this property will
943 **not** cause the surface to "steal" the input focus from other
947 <property name="Maximized">
948 The value [[true]] is put to this property on the root box
949 when the surface is maximized, and [[false]] when the surface
950 is un-maximized. Reading from this value will return [[true]]
951 if the surface is maximized and [[false]] if it is
952 not. Putting [[true]] to this property will maximize the
953 window, and putting [[false]] to this property will
954 unmaximize the window.
955 Note that not all platforms support maximization.
958 <property name="Minimized">
959 The value [[true]] is put to this property on the root box
960 when the surface is minimized, and [[false]] when the surface
961 is unminimized. Reading from this value will return [[true]]
962 if the surface is minimized and [[false]] if it is
963 not. Putting [[true]] to this property will minimize the
964 window, and putting [[false]] will unminimize it.
967 <property name="Close">
968 When the user attempts to close a surface, the value
969 [[true]] will be put to this property. Scripts may trap
970 this property to prevent the window from closing. Putting the
972 [[true]] to this property on a root box has the same
973 effect as putting [[null]] to the [[thisbox]]
977 <property name="icon">
978 The surface's icon. This is usually displayed on the titlebar of a
979 window. The value should be an object whose stream is a PNG image. Note
980 that not all platforms support this property.
983 <property name="titlebar">
984 The surface's titlebar text. Note that not all platforms support
985 this property. Only ASCII characters 0x20-0x7F are permitted.
992 <!-- ----------------------------------------------------------------------- -->
993 <section title="Streams">
995 <heading title="Every object has a stream..."/>
997 Every object has a **stream** associated with it. A stream is a
998 sequence of bytes that can be read or written to.
1000 By default an object has an empty stream (zero bytes). However, some objects
1001 (returned from special methods on the [[ibex]] object) have
1002 streams yielding data read from an url, file, or a component of a zip
1003 archive. In a future release, the stream associated with a box will
1004 be an .ibex template which, when applied, will fully reconstitute the
1007 <heading title="...but streams are not objects"/>
1009 Despite the ubiquity of streams, you cannot actually reference a
1010 stream, since it is not an object. Instead, you simply reference the
1011 object it belongs to. If you are familiar with Java, this is similar
1012 to how every Java object has a monitor associated with it, but you
1013 cannot directly manipulate the monitor (you can't pass around a
1014 reference to just the monitor).
1016 In the rest of the section we will sometimes refer to "getting
1017 properties from a stream" or "passing a stream to a function"; this is
1018 just shorthand for saying to perform those actions on the object the
1021 <section title="Creating Streams from URLs">
1023 You can create a stream from a URL by calling
1026 var r = ibex.stream.url("http://...");
1029 This will return an object whose stream draws data from the specified
1030 URL. Streams are loaded lazily whenever possible.
1034 <section title="Getting Substreams">
1036 Most stream objects let you access
1037 substreams using the usual JavaScript operators [[[]]] and
1038 [[.]], as well as the [[for..in]] syntax.
1041 // r1 and r2 are equivalent but not equal (!=)
1042 var r1 = ibex.stream.url("http://www.ibex.org/foo/bar.html");
1043 var r2 = ibex.stream.url("http://www.ibex.org/foo")["bar.html"];
1048 <section title="The Root Stream">
1050 The empty-string property on the [[ibex]] object is called the
1051 **root stream**. You can access this object as [[ibex..]] or
1052 [[ibex[""]]]. Additionally, any expression which starts with a
1053 dot is treated as property to be retrieved from the root stream. The
1054 following three expressions are equivalent:
1064 <section title="Static Blocks">
1068 You can access variables within the static block of a template by
1069 appending a double period ([[..]]) and the variable name to the
1070 stream used to load that template:
1073 <!-- org/ibex/themes/linux/scrollbar.ibex -->
1077 ibex.log.print(org.ibex.themes.linux.scrollbar..foo); // prints "12"
1082 <section title="Formatting Streams">
1084 If you attempt to send a stream as part of an XML-RPC call, the
1085 stream will be read in its entirity, Base64-encoded, and transmitted
1086 as a [[<base64/>]] element.
1088 Ibex supports two special URL protocols. The first is [[data:]],
1089 which inteprets the rest of the URL as a Base64 encoded sequence of
1090 bytes to use as a source. The other is [[utf8:]] which
1091 interpretets the rest of the string as a Unicode character sequence to
1092 be UTF-8 encoded as a string of bytes to use as a source.
1095 var r5 = ibex.stream.url("data:WFWE876WEh99sd76f");
1096 var r6 = ibex.stream.url("utf8:this is a test");
1099 You can read a UTF-8 encoded string from a stream like this:
1102 var myString = ibex.stream.fromUTF(ibex.stream.url("utf8:testing..."));
1104 You can also parse XML from a stream using SAX like this:
1107 ibex.stream.xml.sax(
1108 ibex.stream.url("http://foo.com/foo.xml"),
1109 { beginElement : function(tagname, attributeKeyValuePairs) { ... },
1110 endElement : function(tagname) { ... },
1111 content : function(contentString) { ... }
1112 whitespace : function(whitespaceString) { ... }
1120 <!-- ----------------------------------------------------------------------- -->
1121 <section title="The Ibex object">
1123 The [[ibex]] object is present in the top-level scope of every
1124 script. It has the following properties:
1126 <heading title="General"/>
1128 <property name="ibex.box">
1129 reading from this property returns a new box
1131 <property name="ibex.clone(o)">
1132 creates a clone of object
1134 <property name="ibex.bless(s)">
1135 returns a blessed clone of stream
1138 <heading title="ECMA Library Objects"/>
1140 <property name="ibex.date">
1141 reading from this property returns a new date
1143 <property name="ibex.math">
1144 this object contains the ECMA math functions
1146 <property name="ibex.regexp(s)">
1147 return a regexp object corresponding to string **s**
1149 <property name="ibex.string">
1150 this object contains the ECMA string manipulation functions
1153 <heading title="Logging"/>
1155 <property name="ibex.log.debug(m1, ... mn)">
1156 log the debug messages **m1** through **mn**.
1160 <property name="ibex.log.info(m1, ... mn)">
1161 log the info messages **m1** through **mn**.
1164 <property name="ibex.log.warn(m1, ... mn)">
1165 log the warning messages **m1** through **mn**.
1168 <property name="ibex.log.error(m1, ... mn)">
1169 log the error messages **m1** through **mn**.
1172 <heading title="User Interface"/>
1174 <property name="ibex.ui.browser(u)">
1175 opens a new browser window with URL **u**
1178 <property name="ibex.ui.key.control">
1179 true if the control key is depressed
1182 <property name="ibex.ui.key.shift">
1183 true if the shift key is depressed
1186 <property name="ibex.ui.key.alt">
1187 true if the alt key is depressed
1190 <property name="ibex.ui.key.name.alt">
1191 the name of the "alt" key (usually either "alt", "meta", or
1195 <property name="ibex.ui.clipboard">
1196 the contents of the clipboard; can be read and written to
1199 <property name="ibex.ui.maxdim">
1200 the maximum dimension of any UI element; usually
1201 2<sup>31</sup>, but may be smaller
1204 <property name="ibex.ui.screen.width">
1205 the width of the screen, in pixels
1208 <property name="ibex.ui.screen.height">
1209 the height of the screen, in pixels
1212 <property name="ibex.ui.mouse.button">
1213 either 0, 1, 2, or 3, indicating the mouse button currently
1217 <property name="ibex.ui.frame">
1218 when a box is written to this property, it becomes the root
1222 <property name="ibex.ui.window">
1223 when a box is written to this property, it becomes the root
1227 <property name="ibex.ui.font.serif">
1228 an object whose stream is a a builtin serif font
1231 <property name="ibex.ui.font.sansserif">
1232 an object whose stream is a builtin sans-serif font
1235 <property name="ibex.ui.font.monospace">
1236 an object whose stream is a a builtin fixed-width font
1239 <heading title="Networking"/>
1241 <property name="ibex.net.rpc.xml(u)">
1242 return an XML-RPC call object with endpoint URL **u**
1245 <property name="ibex.net.rpc.soap(u,">
1246 return a SOAP call object with endpoint URL **u**,
1247 SoapAction **a**, and XML Namespace **n**
1250 <heading title="Threads"/>
1252 <property name="ibex.thread">
1253 when a function is written to this property, a new thread is
1257 <property name="ibex.thread.yield()">
1258 yield the current thread
1261 <property name="ibex.thread.sleep(n)">
1262 sleep for **n** milliseconds
1265 <heading title="Streams"/>
1267 <property name="ibex.stream.url(u)">
1268 returns a new object whose stream is drawn from URL **u**
1271 <property name="ibex.stream.unzip(s)">
1272 unpacks a zip archive from **s**'s stream
1275 <property name="ibex.stream.uncab(s)">
1276 unpacks a cab archive from **s**'s stream
1279 <property name="ibex.stream.cache(s,k)">
1280 valign=top>wraps a disk-backed read cache keyed on **k**
1281 around **s**'s stream
1284 <property name="ibex.stream.watch(s,f)">
1285 returns an object whose stream is drawn from **s**'s
1286 stream, but invokes **f(n,d)** as it is read from.
1289 <property name="ibex.stream.parse.xml(s, h)">
1290 Use SAX to parse the XML document on stream **s** with
1294 <property name="ibex.stream.parse.html(s, h)">
1295 Same as [[parse.xml()]], but tries to fix broken HTML.
1298 <property name="ibex.stream.parse.utf8(s)">
1299 treat **s**'s stream as a string encoded as a UTF-8 byte stream and return the string
1302 <property name="ibex.stream.homedir">
1303 [[ibex.stream.tempdir]]
1306 <heading title="Cryptography"/>
1308 <property name="ibex.crypto.rsa(k,s)">
1309 **not implemented yet:** return a
1310 stream which rsa-decrypts stream **s** with key **k**
1313 <property name="ibex.crypto.rc4(k,s)">
1314 **not implemented yet:** return a
1315 stream which rc4-decrypts stream **s** with key **k**
1318 <property name="ibex.crypto.md5(s)">
1319 **not implemented yet:** immediately
1320 MD5-hash stream **s**
1323 <property name="ibex.crypto.sha1(s)">
1324 **not implemented yet:** immediately
1325 SHA1-hash stream **s**
1329 <!-- ----------------------------------------------------------------------- -->
1330 <section title="Traps">
1332 You can add a trap to a property by applying the [[++=]] operator
1333 to a function with one argument. The trap will be invoked whenever
1334 that property is written to.
1338 foo ++= function(z) {
1339 ibex.log.info("foo is " + z);
1344 If another script were to set the property "[[foo]]"
1345 on the box above to the value [[5]], the function above would be
1346 invoked with the argument [[5]]. The function would then log
1347 the string "[[foo is 5]]".
1349 Within a trap, the expression [[trapee]] can be used to
1350 get a reference to the box on which the trap was placed.
1352 The expression [[trapname]] returns the name of the
1353 trap executing the current function. This is useful when a function
1354 is applied to multiple traps. For example:
1358 func ++= function(z) {
1359 ibex.log.info("called trap " + trapname);
1366 <section title="Removing Traps">
1368 You can remove a trap by using the [[--=]] operator with the same
1369 function you added as a trap:
1373 var myfunc = function(z) { /* ... */ }
1384 <heading title="Multiple Traps on the Same Property"/>
1386 When the trapped property is **written** to, each of the trap
1387 functions placed on it will be invoked in the opposite order that
1388 they were placed on the box -- the most recently placed trap will
1389 execute first. This last-to-first execution of traps is called
1390 **cascading**. After the last trap is invoked, the value is
1391 stored on the box (remember, boxes are objects, so they can hold
1392 properties just like all other ECMAscript objects).
1394 <section title="Manual Cascades">
1396 There are two additional tricks you can use when placing traps. The
1397 first is a **manual cascade**. If you want to cascade to lower
1398 traps in the middle of a function, or you want to cascade with a
1399 different value than the value passed to you (in effect "lying" to
1400 lower traps), you can use [[cascade]]. For example:
1403 <ui:box color="black">
1404 color ++= function(c) {
1405 ibex.log.info("refusing to change colors!");
1411 This effectively creates a box whose color cannot be changed, and
1412 which complains loudly if you try to do so.
1414 Do **not** try to do something like this:
1417 <ui:box color="black">
1418 color ++= function(z) {
1419 color = "black"; // INFINITE LOOP! BAD!!!
1423 To prevent automatic cascading, return [[true]] from your function:
1426 <ui:box color="black">
1427 color ++= function(z) {
1428 return true; // the box's color will not change
1435 <section title="Read Traps">
1437 The other trick is a **read-trap**. Read traps are just like normal
1438 traps, except that you use a function that takes zero arguments instead of one. Read traps
1439 also do not automatically cascade.
1443 doublewidth [[++=]] function() { return 2 * width; }
1447 If another script attempts to read from the [[doublewidth]]
1448 property on this box, the value it gets will be twice the actual width
1449 of the box. Note that
1450 the actual [[doublewidth]] property on the box never gets written
1451 to, since the trap does not cascade.
1453 You can manually cascade on read traps as well:
1457 text [[++=]] function() { return "my text is " + cascade; }
1461 Read traps are only rarely needed -- most of the time a write trap
1466 <heading title="Prohibited Traps"/>
1468 To prevent confusing and hard-to-debug behaviors, scripts may not
1469 place traps on any of the properties described in the sections
1470 <link text="Box Layout Properties" section="Layout Properties"/>, <link
1471 section="Child-Control Properties"/>, or <link section="Other Box
1472 Properties"/> except for [[childadded]],
1473 [[childremoved]] and [[surface]]. FIXME: remove?
1475 <heading title="Exceptions and Traps"/>
1477 If an uncaught exception is thrown from a trap, Ibex will log the
1478 exception, but will **not** propagate it to the code which
1479 triggered the trap. If the trap was a read trap, the value
1480 [[null]] will be returned.
1481 FIXME: is this right?
1483 <heading title="Architectural Significance of Traps"/>
1485 Traps are the backbone of Ibex. Since almost all UI programming is
1486 event/demand driven, traps eliminate the need for separate
1487 member/getter/setter declarations, often cutting the amount of typing
1488 you have to do to a third of what it would normally be.
1490 <section title="Cloning">
1492 **Cloning** is a companion technique for traps; together they can
1493 be used to simulate any sort of environment you might need. When you
1494 call [[ibex.clone(o)]], Ibex returns a new object (called the
1495 **clone**) which compares with equality ([[==]]) to the
1496 original object. Furthermore, both objects are "equal" as keys in
1501 var theclone = ibex.clone(o);
1503 ibex.log.info(hash[theclone]); // prints "5"
1506 Any writes to properties on the clone will actually write to
1507 properties on the original object, and reads from properties on the
1508 clone will read properties on the original object. In fact, the only
1509 thing that can be used to distinguish the original from the clone is
1510 traps -- a trap placed on the clone is **not** placed on the
1511 original object as well.
1516 <!-- ----------------------------------------------------------------------- -->
1517 <section title="Threads">
1519 <section title="Contexts">
1521 From the perspective of an application writer, Ibex is strictly
1522 single-threaded. Ibex is always in exactly one of the following three
1525 <list type="unordered">
1527 __Rendering Context__ -- (redrawing the screen)
1529 __Event Context__ (executing javascript traps triggered by an event)
1531 __Thread Context__ (executing a background thread spawned with [[ibex.thread]])
1535 There are two important restrictions on what can be done in particular contexts:
1537 <list type="unordered">
1539 The [[box.mouse]] property and its subproperties
1540 ([[x]], [[y]], and [[inside]]) can only be read
1541 from within the Event Context, or in a thread context
1542 **after** a the [[box.mouse]] property on this box or
1543 an ancestor box has been written to.
1545 Blocking operations (anything that accesses the network or
1546 disk) can only be performed in the Thread Context.
1552 <section title="Background Threads">
1554 Ibex offers easy access to threads. Spawning a background thread is as
1555 simple as writing a function to the [[ibex.thread]] property:
1558 ibex.thread = function() {
1559 ibex.log.info("this is happening in a background thread!");
1563 The argument set passed to the function is currently undefined and is
1564 reserved for use in future versions of Ibex. Scripts should not
1565 depend on the number or content of these arguments.
1567 Ibex is **cooperatively multitasked**, so threads must not process
1568 for too long. This was a deliberate choice; cooperatively
1569 multitasked environments do not require complex locking primitives
1570 like mutexes and semaphores which are difficult for novices to
1571 understand. The disadvantage of cooperative multitasking is that one
1572 thread can hog the CPU. This is unlikely to happen in Ibex for two reasons:
1573 first, all blocking I/O operations **automatically** yield the CPU,
1574 so the overall user interface never becomes unresponsive because it is
1575 waiting for a disk or network transfer. Second, since Ibex is strictly
1576 a user interface platform, Ibex scripts are unlikely to perform highly
1577 compute-intensive operations that keep the CPU busy for more than a
1583 <section title="Events">
1585 Every execution of the Event Context begins with an event, which
1586 consists of a key/value pair, and a mouse position, which consists of
1587 an x and y coordinate. The possible keys are [[_Press[1-3]]],
1588 [[_Release[1-3]]], [[_Click[1-3]]], [[_DoubleClick[1-3]]],
1589 [[_Move]], [[_KeyPressed]], and [[_KeyReleased]].
1591 Here are two example events:
1593 An event is triggered by writing the key to the value on a box. This
1594 triggers any trap handlers which may be present. Once these handlers
1595 have executed, Ibex figures out which child of the current box contains
1596 the mouse (taking into account that some boxes may cover up others)
1597 and writes the key and value to that box. If none of the box's
1598 children contain the mouse position, Ibex removes the leading
1599 underscore from the key name and writes the value to
1600 **that** property. Once all the traps on that property have
1601 executed, the value is written to the box's parent.
1603 Intuitively, Ibex delivers the underscored event to every box from the
1604 root to the target, and then delivers the non-underscored event to
1605 that same set of boxes in reverse order. So the event travels down
1606 the tree to the target, and then back up to the root. The following
1607 example prints out "first second third fourth" in that order.
1611 _Press1 ++= function(b) { ibex.log.info("first"); }
1612 Press1 ++= function(b) { ibex.log.info("fourth"); }
1614 _Press1 ++= function(b) { ibex.log.info("second"); }
1615 Press1 ++= function(b) { ibex.log.info("third"); }
1620 In general, you should use the **non-underscore** names to respond
1621 to user input and use the underscored names when you want to override
1622 child boxes' behavior or route events to particular boxes (for
1623 example, when implementing a focus protocol). This is why the
1624 underscored elements are delivered to parents before children (so
1625 parents can override their childrens' behavior), but non-underscored
1626 events are delivered to children before parents (since, visually, a
1627 mouse click is usually "intended" for the leaf box underneath the
1632 <heading title="Stopping the Process"/>
1634 At any point in this sequence, a trap handler can choose not to
1635 cascade (by returning [[true]] from the trap handler function).
1636 This will immediately cease the propagation of the event. This is how
1637 you would indicate that an event has been "handled".
1639 <heading title="Non-Propagating Events"/>
1641 Ibex uses the following events to notify a box about changes that
1642 only matter to that particular box. These events do not propagate
1643 either up or down the tree.
1645 <property name="Enter Leave">
1646 The value [[true]] is written to this property when the mouse (enters/leaves) the box.
1649 <property name="SizeChange">
1650 The value [[true]] is put to this property after the size
1651 of this box changes.
1654 <property name="ChildChange">
1655 When a child is added or removed, that child is written to
1656 this property. The write is always performed **after** the
1657 addition or removal, so these two cases can be distinguished
1658 by checking [[indexof(child)]].
1660 Note that if the parent's redirect target is set to another
1661 box, this trap will only be invoked when children are
1662 manipulated by reading and writing to the parent. Reads and
1663 writes directly to the redirect target will **not** trigger
1666 Note also that this traps is still triggered if a box's
1667 [[redirect]] target is **null**. This is useful for
1668 boxes that need to accept children and then relocate them
1672 <section title="Listing of Events">
1674 <property name="Press1 Press2 Press3">
1675 Indicates that the use has pressed a mouse button. On
1676 platforms with three mouse buttons, the **middle** button
1677 is button 3 -- this ensures that applications written to only
1678 use two buttons (1 and 2) will work intuitively on three button
1682 <property name="Release1 Release2 Release3">
1683 Indicates that the use has released a mouse button.
1686 <property name="Click1 Click2 Click3">
1687 Indicates that the user has pressed and released the
1688 mouse button without moving the mouse much (exactly how
1689 much is platform-dependent).
1692 <property name="DoubleClick1 DoubleClick2 DoubleClick3">
1693 Indicates that the user has clicked the
1694 mouse button twice within a short period of time (exactly how long is platform-dependent).
1697 <property name="Move">
1698 Indicates that the mouse has moved while within this box, or that
1699 the mouse while outside this box **if a button was pressed while within this box and has not yet been released**
1702 <property name="KeyPressed KeyReleased">
1704 A string is written to this property when a key is pressed or
1705 released If the key was any other key, a multi-character
1706 string describing the key will be put. For simplicity, we use
1707 the VK_ constants in the <link
1708 url="http://java.sun.com/products/jdk/1.1/docs/api/java.awt.event.KeyEvent.html#VK_0"
1709 text=" Java 1.1 API java.awt.event.KeyEvent class"/>. When a
1710 key is pressed or released, the string put will be the portion
1711 of its VK_ constant after the underscore, all in lower case.
1714 If the shift key was depressed immediately before the
1715 event took place, then the string will be capitalized. Special
1716 keynames are also capitalized; shift+home is reported as
1717 "[[HOME]]". Symbols are capitalized as they appear on the
1718 keyboard; for example, on an American QWERTY keyboard, shift+2
1719 is reported as "[[@]]".
1721 If the alt, meta, or command key was depressed immediately
1722 before this key was pressed, then the string will be prefixed
1723 with the string "[[A-]]". If the control key was depressed
1724 while this key was pressed, then the string will be prefixed
1725 with the string "[[C-]]". If both alt and control are
1726 depressed, the string is prefixed with "[[C-A-]]".
1728 Ibex does not distinguish between a key press resulting from
1729 the user physically pushing down a key, and a 'key press'
1730 resulting from the keyboard's typematic repeat. In the rare
1731 case that an application needs to distinguish between these
1732 two events, it should watch for KeyReleased messages and
1733 maintain an internal key-state vector.
1741 <!-- ----------------------------------------------------------------------- -->
1742 <section title="Networking">
1744 <section title="XML-RPC">
1746 XML-RPC objects can be created by calling [[ibex.net.rpc.xml(**XML-RPC
1747 URL**)]], and then invoking methods on that object. For example,
1750 Press1 += function(v) {
1751 ibex.thread = function() {
1752 color = ibex.net.rpc.xml("http://xmlrpc.ibex.org/RPC2/").
1753 color.getTodaysColor("Friday");
1758 When the user clicks the first mouse button on this box, it will
1759 contact the server [[xmlrpc.ibex.org]], route to the
1760 [[/RPC2/]] handler and invoke the [[getTodaysColor()]]
1761 method on the [[color]] object with a single string argument
1762 "[[Friday]]". The return value will be used to change the color
1763 of the box the user clicked on.
1765 Note that in this example we spawned a background thread to handle the
1766 request -- the [[Press1]] event is delivered in the foreground
1767 thread, and XML-RPC methods may only be invoked in background
1768 threads. This is to prevent the UI from "locking up" if the server
1769 takes a long time to reply.
1771 If the XML-RPC method faults, an object will be thrown with two
1772 properties: [[faultCode]] and [[faultString]], as defined in
1773 the <link url="http://www.xmlrpc.org/spec" text="XML-RPC specification"/>. If
1774 Ibex encounters a network, transport, or session-layer error, it will
1775 throw a [[String]] object describing the error in a
1776 human-readable format. Scripts should not rely on the contents of
1777 this string having any special structure or significance.
1779 If an object with an associated non-empty stream is passed as an
1780 argument to an XML-RPC method, it will be sent as a <base64/>
1781 element. If a <base64/> element is found in the XML-RPC reply, it
1782 will be returned as an object with a stream drawn from that byte sequence.
1784 Each object returned by [[ibex.net.rpc.xml()]] represents a
1785 single HTTP connection. The connection will be held open until
1786 the object is garbage collected or the server closes the
1787 connection. If a second call is issued on the object before the
1788 first one returns (usually from a seperate thread), the two calls
1790 url="http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.1.2.2"
1791 text="pipelined"/>. This can dramatically improve performance.
1793 Ibex supports HTTP Basic and Digest authentication. To use
1794 authentication, pass [[ibex.net.rpc.xml()]] a URL in the form
1797 http[s]://user:password@hostname/
1800 Ibex will use Digest authentication if the server supports it;
1801 otherwise it will use Basic authentication. Please be aware that
1802 many XML-RPC server implementations contain a <link
1803 url="http://www.ibex.org/faq.html#auth" text="broken
1804 implementation of Basic authentication"/>.
1808 <section title="SOAP">
1810 SOAP methods are invoked the same way as XML-RPC methods, but with three differences:
1812 <list type="ordered">
1814 [[ibex.net.rpc.soap()]] is used instead of
1815 [[ibex.net.rpc.xml()]]
1817 Instead of specifying just the URL of the service itself, you
1818 must specify the URL, the SOAPAction argument, and the
1821 The actual method invocation takes only one argument, which
1822 must be an object. This is necessary since SOAP arguments are
1823 specified by name, rather than ordering.
1827 SOAP faults are handled the same way as XML-RPC faults except that the
1828 capitalization of the [[faultstring]] and [[faultcode]]
1829 members is all lower-case, to match the SOAP spec. Here is a
1833 Press1 ++= function(v) {
1834 ibex.thread = function() {
1835 color = ibex.net.rpc.soap("http://soap.ibex.org/SOAP",
1837 "http://ibex.org/namespace"
1838 ).color.getTodaysColor( {
1845 As you can see, SOAP is much more verbose, yet does not offer
1846 substantially improved functionality. We recommend that XML-RPC be
1847 used whenever possible, and that SOAP be reserved for legacy
1850 The current Ibex SOAP stack does not support 'document style' or
1851 multi-ref ([[href]]) data structures.
1855 <section title="Security">
1857 Applications downloaded from the network (as opposed to those loaded
1858 from the filesystem) may only make certain kinds of connections to
1859 certain hosts. See Appendix A for a detailed description of the
1865 <!-- ----------------------------------------------------------------------- -->
1866 <section title="Error Handling">
1868 If the Ibex Core encounters an error while servicing a function call
1869 originating in JavaScript, the core will throw a string consisting of
1870 an error code followed by a colon, a space, and a descriptive message.
1874 "ibex.net.dns.unknownhostexception: unable to resolve host foo.com"
1877 The code should be used to determine how the program should respond to
1878 an error. The codes are organized in a hierarchy, so the
1879 string.startsWith() method can be used to determine if an error lies
1880 within a particular subhierarchy. The descriptive message portion of
1881 the string may be shown to the user.
1883 <property name="ibex.assertion.failed">
1886 <property name="ibex.io">
1887 General I/O exceptions
1889 <property name="ibex.io.encoding">
1890 Error translating between character encodings.
1892 <property name="ibex.io.zip">
1893 Attempted to access a corrupt zip archive.
1895 <property name="ibex.io.eof">
1896 End of file encountered unexpectedly
1898 <property name="ibex.net.security.prohibitedHost">
1899 A piece of untrusted Ibex code attempted to contact a
1900 restricted host. See <link appendix="Security Architecture and Considerations"/> for details.
1902 <property name="ibex.net.dns.temporaryFailure">
1903 An attempt to resolve a hostname failed but it is not known
1904 for certain that the hostname is invalid.
1906 <property name="ibex.net.dns.unknownHost">
1907 An attempt to resolve a hostname failed because the hostname
1910 <property name="ibex.net.socket.closed">
1911 A socket was closed unexpectedly.
1913 <property name="ibex.net.socket.connectionFailed">
1914 A connection could not be made to the remote host.
1916 <property name="ibex.net.url.malformed">
1917 Tried to parse a malformed URL.
1919 <property name="ibex.net.ssl">
1920 General SSL protocol errors.
1922 <property name="ibex.net.ssl.untrustedCertificate">
1923 The server's certificate was not signed by a CA trusted by Ibex.
1925 <property name="ibex.net.http.">
1926 Thrown when an HTTP error code is returned during an
1927 operation. The three characters [[**xyz**]] will be
1928 the three-digit HTTP status code.
1930 <property name="ibex.net.xmlrpc.null">
1931 The caller attempted to transmit the [[null]] value via XML-RPC.
1933 <property name="ibex.net.xmlrpc.circular">
1934 The caller attempted to transmit a circular data structure via XML-RPC.
1936 <property name="ibex.net.xmlrpc.specialObject">
1937 The caller attempted to transmit a "special" object via
1938 XML-RPC (for example, a Box or the Ibex object).
1940 <property name="ibex.null.put">
1941 A JavaScript attempted to put to a property on the [[null]] value
1943 <property name="ibex.null.get">
1944 A JavaScript attempted to get from a property on the [[null]] value
1946 <property name="ibex.null.call">
1947 A JavaScript attempted to call the [[null]] value
1950 If an exception is thrown inside a trap, the exception will propagate
1951 to the script that triggered the trap.
1953 If an uncaught exception is thrown while applying a template, or the
1954 requested template could not be found, an error will be logged and the
1955 box to which the template was being applied will be made invisible
1956 ([[visible = false]]). This ensures that half-applied widgets are
1957 never shown to the user.
1961 <!-- ----------------------------------------------------------------------- -->
1962 <section title="Advanced Topics">
1964 <section title="Re-routing events">
1966 At any point in the Event Context, you can write to the [[mouse]]
1967 property on any box. The value written should be an object with two
1968 properties, [[x]] and [[y]]. For example:
1971 _Press1 ++= function(p) {
1972 mouse = { x: 32, y: 77 };
1976 The coordinates specified are relative to the box whose [[mouse]]
1977 property is being written to. There is no need to supply the
1978 [[inside]] property; it is computed automatically. Writing to
1979 the [[mouse]] property causes Ibex to recompute the eventual
1980 target box, and also alter the values returned by [[mouse.x]],
1981 [[mouse.y]], and [[mouse.inside]] for any **descendants**
1982 of the current box. Writing to the [[mouse]] property also
1983 automatically prevents the event from returning to the box's parents
1984 -- it is equivalent to not cascading on the non-underscored event.
1985 This ensures that child boxes cannot trick their parent boxes into
1986 thinking that the mouse has moved.
1988 If you want the event to "skip over" the boxes between the trapee
1989 and the target, or if you want to re-route an event to a box which
1990 is not a descendant of the current box, simply write the value to
1991 the proper key on the target box.
1995 _KeyPressed = function(k) { ibex.log.info("first"); }
1996 KeyPressed = function(k) { ibex.log.info("sixth"); }
1997 $recipient.target = $target;
1998 <ui:box id="recipient">
1999 _KeyPressed = function(k) {
2000 ibex.log.info("second");
2001 thisbox.target.KeyPressed = k;
2002 // inhibit cascade; keep event from going to $excluded
2005 KeyPressed = function(k) { ibex.log.info("fifth"); }
2006 <ui:box id="excluded">
2007 _KeyPressed = function(k) {
2008 ibex.log.info("this never happens");
2012 <ui:box id="target">
2013 _KeyPressed = function(k) { ibex.log.info("third"); }
2014 KeyPressed = function(k) { ibex.log.info("fourth"); }
2021 <section title="Synthesizing Your Own Events">
2023 You can create "fake events" by simply writing to the [[mouse]]
2024 property and then writing a value to one of the underscored properties
2025 on a box. This will have exactly the same effect as if the use had
2026 actually pressed a key, clicked a button, or moved the mouse -- they
2027 are indistinguishable.
2031 <section title="Ibex self-emulation">
2033 When the core first starts up, it clones the [[ibex]] object,
2034 creates a stream for the initial .ibex, and then places a trap on the
2035 cloned [[ibex]] object so that its empty-string property returns
2036 the .ibex stream. The cloned Ibex object is then passed as the third
2037 (optional) argument to [[ibex.apply()]], making it the default
2038 [[ibex]] object for the scripts that are executed as part of the
2039 template instantiation.
2042 var new_ibex = ibex.clone(ibex);
2043 var stream = ibex.bless(ibex.stream.url("http://..."));
2044 new_ibex[""] ++= function() { return stream; }
2045 ibex.apply(ibex.box, new_ibex..main, new_ibex);
2048 Note that we called [[ibex.bless()]] on the stream before tacking
2049 it on to the new Ibex object. The bless function returns a clone of
2050 the object passed to it, with a few traps which are explained below.
2051 Additionally, any sub-streams retrieved by accessing properties of the
2052 blessed stream will also automatically be blessed (blessed streams are
2055 Blessing a stream serves three purposes:
2057 <list type="unordered">
2059 Blessed clones always return the appropriate static block when
2060 their empty property is accessed; this ensures that references
2061 to the static blocks of other templates work properly.
2063 Blessed substreams can return their parent stream by accessing
2064 a hidden property which is reserved for internal use by Ibex.
2065 This ensures that Ibex can automatically add filename
2066 extensions where needed, according to the following rules:
2069 If the stream is a template to be applied, the string
2070 "[[.ibex]]" is appended.
2072 If the stream is an image, the string "[[.png]]" is
2073 appended. If no stream is found, "[[.jpeg]]" and
2074 "[[.gif]]" are tried, in that order.
2076 If the stream is an font, the string "[[.ttf]]" is
2080 Every call to [[ibex.bless()]] returns a different object
2081 (which happens to be a clone of the object passed to it) with
2082 a completely separate set of static blocks.
2086 Ibex can self-emulate by using [[ibex.clone()]] on the Ibex object;
2087 this technique is very similar to the use of ClassLoaders in
2088 Java. This is useful for a number of applications, including
2089 debuggers, IDEs, sandboxing untrusted code, remote-control, and
2090 others. For example:
2093 var newLoadFunction = function(url) { /* ... */ };
2094 var new_ibex = ibex.clone(ibex);
2095 new_ibex.load ++= function() { return newLoadFunction; }
2096 ibex.apply(ibex.box, .main, new_ibex);
2101 <!-- ----------------------------------------------------------------------- -->
2102 <appendix title="Security Architecture and Considerations">
2104 Due to the expense and hassle imposed by the commercial PKI code
2105 signing architecture, and the fact that it <link
2106 url="http://www.counterpane.com/pki-risks-ft.txt" text="doesn't
2107 really provide any security anyways"/>, Ibex user interfaces are
2108 distributed as unsigned, untrusted code. As such, they are handled
2109 very carefully by the Ibex Core, and assumed to be potentially
2112 Ibex's security architecture is divided into defenses against four
2113 major classes of attacks:
2115 <heading title="Malicious UI attempts to acquire or alter data on the client"/>
2117 Ibex user interfaces are run in an extremely restrictive sandbox. The
2118 environment does not provide primitives for accessing any data outside
2119 the Ibex core except via XML-RPC and SOAP calls. There are no
2120 facilities to allow Ibex user interfaces to access the client's
2121 operating system or to interact with other applications on the same
2122 host (unless they provide a public XML-RPC or SOAP interface).
2123 An Ibex script may only access a file on the user's hard disk if the
2124 user explicitly chooses that file from an "open file" or "save file"
2125 dialog. There is one exception to this rule: if all templates
2126 currently loaded in the Ibex core originated from the local
2127 filesystem, those templates can load additional .ibexs from the local
2130 The Ibex Core is written in Java, so it is not possible for
2131 scripts to perform buffer overflow attacks against the core
2134 Ibex applications may only read from the clipboard when the user
2135 middle-clicks (X11 paste), presses control-V (Windows paste), or
2136 presses alt-V (Macintosh paste; the command key is mapped to Ibex
2137 "alt"). This ensures that Ibex applications are only granted access to
2138 data that other applications have placed on the clipboard when the user
2139 specifically indicates that that information should be made available
2140 to the Ibex application.
2142 <heading title="Malicious UI attempts to use client to circumvent firewalls"/>
2144 Ibex user interfaces may only make XML-RPC or SOAP calls and load .ibex
2145 archives via HTTP; they cannot execute arbitrary HTTP GET's or open
2146 regular TCP sockets.
2148 Ibex will not allow a script to connect to a non-public IP address
2149 (10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16, as specified in <link
2150 url="http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc1918.html" text="RFC
2151 1918"/>). There is one exception -- if all templates currently loaded
2152 in the core originated from the same IP address, those scripts may
2153 make calls to that IP address regardless of whether or not it is
2154 firewalled. If Ibex does not have access to a DNS resolver (because it
2155 is using a proxy which performs DNS lookups), Ibex will provide the
2156 proxy with the appropriate <link
2157 url="http://www.ibex.org/x-requestorigin.html"
2158 text="X-RequestOrigin"/> header that the proxy needs in order
2159 to maintain security.
2161 The only remaining possible attack is against a XML-RPC or SOAP
2162 service running on a firewalled host with a public address. Assigning
2163 such machines public IP addresses is a poor network security policy,
2164 and doing so squanders scarce public IPv4 addresses. As such, the onus
2165 is on the administrators of such machines to explicitly block access
2166 to clients reporting a [[User-Agent:]] header beginning with the
2167 four characters "[[IBEX]]".
2169 <heading title="Malicious UI attempts to trick user into divulging secret information"/>
2171 All top-level windows created by Ibex are **scarred** -- a stripe
2172 and a lock is drawn across the corner of the window. There is no way
2173 for a user interface to remove this scar. Ibex user interfaces may not
2174 create windows smaller than the size of the scar.
2176 <heading title="Malicious network attempts to snoop or man-in-the-middle transactions"/>
2178 Ibex user interfaces may transmit network data using HTTPS (SSL 3.0)
2179 for encryption. Ibex will attempt 128-bit encryption, but will
2180 negotiate down to 40-bit if the server does not support strong
2181 crypto. Ibex's SSL implementation is currently provided by <link
2182 url="http://www.ibex.org/tinyssl" text="TinySSL"/> and <link
2183 url="http://www.bouncycastle.org" text="The Legion of the Bouncy
2186 All HTTPS connections must be authenticated by the server using a
2187 certificate whose name matches the domain name of the HTTPS URL. The
2188 certificate must be signed by a trusted root CA. Ibex trusts the same
2189 93 root CAs whose certificates are included as "trusted" in Microsoft
2190 Internet Explorer 5.5 SP2. This provides a minimal level of protection
2191 against man-in-the-middle attacks; you should not trust this
2192 connection with any data you would not normally trust an SSL-enabled
2197 <!-- ----------------------------------------------------------------------- -->
2198 <appendix title="ECMAscript compliance">
2200 Ibex's scripts are written in a modified subset of ECMA-262, revision 3
2201 (aka JavaScript 1.5). The interpreter strays from the spec in a few
2204 <section title="Omissions">
2206 The following ECMA features are not supported:
2208 <list type="unordered">
2210 The [[undefined]] value, [[===]], and [[!==]]
2212 The [[new]] keyword (and ECMAScript object inheritance)
2215 [[getter]] and [[setter]]
2217 The ECMA [[this]] keyword.
2219 The [[String]], [[Number]], and [[Boolean]]
2220 classes. Note that [[string]], [[number]], and
2221 [[boolean]] values are supported, however.
2223 You may not [[throw]] the [[null]] value.
2227 Additionally, you must declare all root-scope variables (with
2228 [[var]]) before using them; failure to do so will result in an
2229 exception. Box properties are pre-defined in the scope that scripts
2234 <section title="Extensions">
2236 <list type="unordered">
2238 The token [[..]] is equivalent to [[[""]]].
2244 Extended [[catch]] syntax. The following code:
2246 } catch(e propname "foo.bar.baz") {
2253 if (e.propname != null and e.propname >= "foo.bar.baz" and
2254 "foo.bar.baz/" > e.propname) {
2259 Multiple extended-catch blocks can appear at the end of a single try
2260 block. However, at most one non-extended catch block may appear, and
2261 if it does appear, it must be the last one.
2263 Since Ibex ECMAscripts are wrapped in XML, the lexical token
2264 "[[lt]]" is be interpreted as [[<]], the lexical
2265 token "[[gt]]" is be interpreted as [[>]], and the
2266 token "[[and]]" is interpreted as [[&&]].
2267 Thus these tokens cannot be used as variable names.
2269 The identifier [[static]] is a reserved word in
2270 ECMAScript, but not in Ibex.
2272 Ibex defines an additional reserved word, "[[assert]]",
2273 which will evaluate the expression which follows it, throwing
2274 a [[ibex.assertion.failed]] exception if the expression
2275 evaluates to [[false]].
2277 To ensure that Ibex files appear the same in all text editors, tab
2278 characters are not allowed in Ibex files.
2282 Some useful tutorials include:
2284 <list type="unordered">
2287 url="http://developer.netscape.com/docs/manuals/communicator/jsref/index.htm"
2288 text=" JavaScript 1.2 Reference"/>. Although this document is
2289 out of date, it is arguably the best guide available for free
2290 on the Internet. The changes from JavaScript 1.2 (aka ECMA-262
2291 r1) to 1.5 were minimal, and many of them were <link
2292 url="ecmascriptcompliance" text="omitted"/> from Ibex.
2295 url="http://search.barnesandnoble.com/booksearch/isbnInquiry.asp?isbn=0596000480"
2296 text=" JavaScript: The Definitive Guide"/>, by David Flanagan
2297 and Paula Ferguson. The latest edition of this book covers
2298 JavaScript 1.5 (ECMA-262 r3).
2301 url="http://www.ecma.ch/ecma1/STAND/ECMA-262.HTM"
2302 text="ECMA-262"/> specification. This is an extremely
2309 <!-- ----------------------------------------------------------------------- -->
2310 <appendix title="Logging and Command Line Invocation">
2313 Usage: ibex [-lawp] [ url | file | directory ]
2314 -l [level] set logging level to { debug, info (default), warn, error, silent }
2315 -l rpc log all XML-RPC and SOAP conversations
2316 -l user@host email log to user@host
2317 -l host:port emit log to TCP socket
2318 -l [file] write log to a file on disk
2320 -w [window-id] reserved for libibex
2321 -p dump profiling information [not yet supported]
2324 If Ibex encounters a serious problem before it starts logging
2325 information, or if it is unable to open the log file, it will abort
2326 immediately with a critical abort, which will be displayed on the
2327 console for POSIX-native cores and in a dialog box for JVM-based and
2330 Note that Microsoft Windows does not provide any mechanism for
2331 redirecting standard input/output of an application which is not
2332 compiled as a "console application". Therefore, Ibex is compiled
2333 as a "console application", and will open a console window when
2334 invoked. To inhibit this console window, provide a logging
2335 destination (file, port, etc).
2337 The [[**source-location**]] parameter can be either the path
2338 to an [[.ibex]] archive, the http url of an [[.ibex]]
2339 archive, or the path to a directory comprising an unpacked
2342 The [[**initial-template**]] parameter is the stream name of
2343 a template to be used as the initial template. If ommitted, it
2344 defaults to [[main]].
2346 The [[-v]] option causes Ibex to enable verbose logging; this will
2347 cause it to log **lots** of information to the log file. This
2348 option will also substantially decrease Ibex's performance.
2352 <!-- ----------------------------------------------------------------------- -->
2354 <appendix title="Grammars">
2356 **Grammar support is experimental in this release
2357 and may not work properly. It may change in incompatible ways or
2358 disappear completely from future releases**
2360 Grammars are defined with a statement in the following form:
2365 A grammar is really just another function; once defined you can't tell
2366 it apart from an ordinary function. A grammar takes one argument,
2367 which can be a string or stream. The argument is parsed and the
2368 result of executing the code block 'c' is returned.
2370 The property 'a' is read; if the value is a grammar, a new production
2371 rule (ie a new alternative, as with '[[|]]') is added to that grammar
2372 (this is a destructive update). This allows you to add productions to
2373 pre-existing grammars (for example, adding a new type of expression to
2374 a programming language by extending the 'expr' grammar). If the old
2375 value is not a grammar, the value is discarded and a new grammar
2378 The value 'b' is a pattern, which may consist of seven simple
2381 <list type="unordered">
2384 grouping parens [[()]]
2386 combinators: [[ | + * ?]]
2388 references to other grammars
2391 The value 'c' and the braces surrounding it are an *optional* code
2392 block, in which the following identifiers are bound:
2394 <list type="unordered">
2396 The identifier 'whole' is bound to the string matched by the
2397 entire expression. If the code block is omitted it behaves
2398 as if it were "[[{ return whole; }]]".
2400 For every reference to another grammar which was matched in the
2401 pattern, the *name used to reference that other grammar* will
2402 be bound to the value returned by its code block. Here's an
2403 example of this important distinction:
2406 var foo ::= 'a' | 'b';
2408 var baz ::= 'c' | bar { /* foo is not defined here, but bar is */ };
2411 On the last line, the identifier 'bar' serves two purposes: it
2412 pulls in the definition of the pattern *and* acts as a binder
2413 within the scope of the braces.
2415 If a reference is matched multiple times (either because it
2416 appears multiple times in the pattern or because the * or +
2417 operator was applied to it) then its name will be bound to an
2418 array containing the matches.
2422 Here is the metacircular definition of the grammar facility:
2425 grammar ::= identifier '::=' pattern (';' | '{' code '}' ';'?)
2426 identifier ::= ('a'..'z' | 'A'..'Z' | '_' | '$') (identifier | '0'..'9')*
2427 char ::= '\0x0000'..'\0xffff'
2428 literal ::= '\'' char+ '\''
2429 | '\'' char '\'' '..' '\'' char '\''
2430 pattern ::= identifier
2437 | pattern '|' pattern
2442 Copyright (C) 2004 Adam Megacz, verbatim redistribution permitted.
2443 Ibex is a trademark of Adam Megacz