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">
243 If the root [[<ibex>]] element contains any non-whitespace
244 text content, this text is interpreted as JavaScript code and is
245 executed the first time the template is referenced. This code is
246 executed in a fresh scope containing two predefined properties:
248 <definition term="ibex">
249 The Ibex Object (described in <ref section="The Ibex Object"/>)
252 <definition term="static">
253 A reference to this template's **static object**, which is
254 initially [[null]]. The static object can be accessed (read
255 and written) from both static scripts as well as instance
256 scripts in a particular template. FIXME
261 <section title="Metadata">
263 Any immediate children of the root element which are in the
264 [[meta]] namespace are treated as metadata and are exempted from
265 the rest of the template application process. Currently only one
266 type of metadata element is defined:
269 [[<meta:doc>]]: structured documentation for the
275 <section title="Other Elements">
277 All remaining children of the root element are treated as elements
278 to be **applied** to the box, in the order in which they appear
279 in the file using the following procedure.
281 <remark text="While this process outlined below sounds very
282 complex, it actually works pretty intuitively. The
283 description below is given in great detail since
284 most applications will wind up being unintentionally
285 dependent on subtle features of this process.
286 However, most of the time you can just pretend that
287 the XML tags and the boxes are the same thing."/>
289 <heading title="Intuitive Description"/>
293 During a box initialization, script-private references to a
294 box's descendants with [[id]] attributes are placed on the
295 box. These references allow scripts on that box to easily refer
296 to descendant nodes created by the template in which the script
297 appears. For example, these two blocks of code have exactly the
302 <ui:box id="foo"/> <ui:box/>
303 $foo.color = "red"; var $foo = this[0];
308 <heading title="Precise Description"/>
310 To apply an XML tag [[__x__]] to a box [[__b__]], perform the following
311 operations, in this order:
313 <list type="ordered">
315 Allocate a fresh scope [[__s__]] whose parent scope is
318 Process each child element or text segment of [[__x__]]
319 in the order they appear in the document:
323 Treat each text segment [[__t__]] as JavaScript code
324 and execute it with [[__s__]] as the root scope.
326 For each child element [[__x'__]] of [[__x__]]:
329 Create a new box [[__b'__]].
331 If the name of tag [[__x'__]] is not
332 "[[box]]" in the [[ui]] namespace, prepend the
333 tag's namespace identifier uri (if any) to the name of
334 the tag, and use the result as a key to retrieve a
335 property from the root stream (defined later).
336 Interpret the resulting stream as a template and apply
337 that template to [[__b'__]].
339 (recursively) apply [[__x'__]] to [[__b'__]].
341 If [[__x'__]] has an [[id]] attribute, declare a variable
342 in [[__s__]] whose name is the value of the [[id]]
343 attribute, prefixed with the [[$]] character, and whose
346 Copy any [[$]]-variables created during the application
347 of [[__x'__]] into scope [[__s__]].
349 Append [[__b'__]] as the last child of [[__b__]].
353 Apply any attributes on [[__x__]] to [[__b__]], except for
354 [[id]]. Since XML specifies that the order of attributes
355 cannot be significant, Ibex processes attributes in
356 alphabetical order by attribute name. For example, if
357 [[__x__]] has the attribute [[foo="bar"]], then the
358 equivalent of the statement [[B.foo="bar";]] will be
359 performed, with the following exceptions:
362 If the value portion of the attribute is the string
363 "[[true]]", put the boolean [[true]]. If the
364 value is "[[false]]", put the boolean [[false]].
366 If the value is a valid ECMAscript number, put it as a
367 number (instead of a string).
369 If the value begins with a dollar sign ([[$]]),
370 retrieve the value of the corresponding variable in
371 [[__s__]] and use that value instead.
373 If the value begins with a dot ([[.]]), prepend the
374 attributes' namespace identifier uri (if any) and
375 interpret the remainder as a property to be retrieved from
376 the root stream (defined later).
380 <heading title="Initialization Invariants"/>
382 The last two steps are referred to as the **initialization** of the
383 node. There are two important aspects of this ordering to be aware of:
385 <list type="unordered">
387 A given box will be fully initialized before its parent is
388 given a reference to that box. This way, parents can be
389 certain that they will never wind up accessing a box when it
390 is in a partially-initialized state.
392 Attributes are applied **after** scripts are run so that
393 the attributes will trigger any **traps** (defined later)
394 placed by the script.
402 <!-- ----------------------------------------------------------------------- -->
403 <section title="Layout and Rendering">
405 <section title="Visual Components">
407 Each box occupies a rectangular region on the surface. The visual
408 appearance of a surface is created by rendering each box in its tree.
409 Unless the [[clip]] attribute is [[false]], each box will
410 clip its childrens' visual representations to its own, so that the
411 children appear "confined to" the parent. Children are rendered after
412 their parents so they appear "on top of" their parents.
414 Each box has two major visual components, each with subcomponents:
418 <definition term="path">
420 A box's [[path]] consists of zero or more lines and curves.
421 The path may be filled with a color, gradient, or texture, and
422 may be stroked with a line of a given thickness and color. If
423 the path is not specified, it defaults to the perimiter of the
424 box. [**Note: Vector Graphics support (including the ability
425 to set the [[path]] property to anything other than the
426 default) is currently not implemented**].
431 an associated [[strokecolor]], which is a color
433 an associated [[strokewidth]], which is a number
434 specifying the width of the stroke. [**Note: Vector
435 Graphics support (including the [[strokewidth]]
436 property) is currently not implemented**]
438 a [[fill]], which is either a color, gradient, or
443 <definition term="text">
445 Each box also has a single line of [[text]], whose
446 appearance is determined by its:
449 associated [[font]], which can be any font supported by
450 the <link url="http://www.freetype.org" text="FreeType2"/>
453 an associated [[fontsize]] in **pixels**
455 an associated [[textcolor]]
459 These eight components plus the size of a box fully specify its
460 appearance. Every single box you see in Ibex is drawn only on the
461 basis of these components and its size.
464 <section title="Size and Position">
466 The size and position of every box is determined by its
467 properties, its childrens' sizes, and its parent's size and
468 position. Box layout and rendering happens in four phases:
469 **packing**, **constraining**, **placing**, and
470 **rendering**. The Core is careful to only perform a phase on
471 a box if the box has changed in a way that invalidates the work
472 done the last time that phase was performed. The packing and
473 constraining phases are performed in a single traversal of the
474 tree (packing is preorder, constraining is postorder), and the
475 placing and rendering phases are performed in a second traversal
476 of the tree (first placing, then rendering, both preorder).
478 For brevity, the rest of this chapter deals only with width and
479 columns. Height and rows is treated identically and independently.
480 Also, it is important to note that the term **minimum width** is
481 not the same thing as the property [[minwidth]], although they
484 <heading title="The Size of the Root Box"/>
486 When the user resizes a window, Ibex changes the root box's
487 [[maxwidth]] and [[maxheight]] to match the size chosen by
488 the user and then determines the root box's size using the same sizing
489 rules it uses for other boxes.
491 Ibex will always attempt to prevent the
492 user from making the surface smaller than the root box's
493 [[minwidth]] and [[minheight]]. If the [[hshrink]] or
494 [[vshrink]] flag is set, Ibex will try to prevent the user from
495 resizing the surface at all. However, not all platforms give Ibex
496 enough control to do this.
498 <image url="alignmentpoint.pdf" caption="The effect of alignment points on layout" width="3in"/>
500 <heading title="The alignment point"/>
502 When talking about positioning, we will often refer to the
505 If the [[align]] property is "[[center]]", then the
506 alignment point is the center of the box.
508 If the [[align]] property is "[[topleft]]",
509 "[[bottomleft]]", "[[topright]]", or
510 "[[bottomright]]", then the alignment point is
511 corresponding corner of the box.
513 If the [[align]] property is "[[top]]",
514 "[[bottom]]", "[[right]]", or "[[left]]", then
515 the alignment point is middle of the corresponding edge of the
518 <section title="Packing">
520 A grid of **cells** is created within the parent. If the
521 parent's [[cols]] property is set to 0, the cell grid has an
522 infinite number of columns. Either [[cols]] or [[rows]]
523 must be zero, but not both.
525 If a child's [[visible]] property is [[false]], it does
526 not occupy any cells (and is not rendered). Otherwise, each child
527 occupies a rectangular set of cells [[child.colspan]] cells
528 wide and [[child.rowspan]] cells high.
530 The Core iterates over the cells in the grid in the following
531 order: if [[rows]] is 0, the Core iterates across each column
532 before proceeding to the next row; otherwise rows come before
533 columns. At each cell, the Core attempts to place the **first
534 remaining unplaced child's** top-left corner in that cell
535 (with the child occupying some set of cells extending down and
536 to the right of that cell). If the parent has a fixed number of
537 columns and the child's [[colspan]] exceeds that limit, the
538 child is placed in column zero regardless, but only occupies the
539 available set of cells (it does not "hang off the end" of the
540 box). <image url="layout.pdf" width="1in"/>
545 <ui:box id="2" rowspan="2" />
546 <ui:box id="3" colspan="2" />
548 <ui:box id="5" colspan="2" />
557 <section title="Constraining">
559 Each box's minimum width is computed recursively as the
565 The width of the box's [[text]] (after applying the
566 box's [[transform]]) [**Note: Vector Graphics support
567 (including the [[transform]] property) is currently not
570 The width of the box's path (after applying the box's
571 [[transform]]) **if the box is [[packed]]**.
573 The minimum width of the children in each row.
576 If a box's [[hshrink]] property is set to
577 [[true]], the box's maximum width is the same as its
578 minimum width; otherwise it is the box's
583 <section title="Placing">
585 <section title="Packed Boxes">
587 Ibex formulates a set of constraints for placing a box's
588 **packed** children as follows:
591 - A box's width can be no greater than the sum of the
593 - The sum of a set of colums cannot be smaller than the
594 minimum width of a box that spans them.
595 - The sum of the widths of the parents' columns will be at
596 least as large as the parent's width is (but possibly
600 Subject to these two unbreakable constraints, Ibex searches for
601 a solution which will optimize the following three goals,
602 prioritized from most important to least important:
605 - (__Most Important__) The sum of all columns will be a close
606 to the parent's with as possible (ie as small as possible)
607 - Ibex will attempt to make a set of columns no wider than
608 the [[maxwidth]] of a box spanning them.
609 - (__Least Important__) Ibex will attempt to make all
610 columns the same width.
613 Each packed box is then placed within the set of cells that it
614 spans. Usually the box will exactly fill this rectangle; if it
615 does not (due to [[maxwidth]] or minimum width constraints), the
616 box's will be placed so that its alignment point coincides with
617 the alignment point of that rectangle of cells.
620 <section title="Non-Packed Boxes">
621 Each non-packed box is transformed according to the parent's
622 [[transform]] property and then positioned so that its alignment
623 point is [[(child.x, child.y)]] pixels from the corresponding
624 edge/corner/center of its parent.
629 <section title="Rendering">
631 Boxes are rendered in a depth-first, pre-order traversal. Note that
632 this may cause a non-packed box to overlap its siblings.
634 <list type="ordered">
636 If the box's [[transform]] property is non-null, the
637 coordinate space is transformed accordingly for the rest of
638 this phase and for the rendering of all children. [**Note:
639 Vector Graphics support (including the [[transform]]
640 property) is currently not implemented**].
642 If the box is packed and has a non-[[null]] path, the
643 path is translated such that the alignment point of the path's
644 bounding box coincides with the box's alignment point (both
645 alignment points are determined by the box's [[align]]
648 If a box has a path, that path is filled with the color,
649 gradient, or image specified by the [[fill]] property and
650 stroked with the color and width specified by the
651 [[strokecolor]] and [[strokewidth]] properties.
653 If the box has a non-null [[text]] attribute,
654 the text is rendered in [[font]] with size
655 [[fontsize]] and color [[textcolor]]. The text is
656 then translated such that the alignment point of the text's
657 bounding box coincides with the box's alignment point (both
658 alignment points are determined by the box's [[align]]
661 The box's children are rendered (pre-order traversal).
669 <!-- ----------------------------------------------------------------------- -->
670 <section title="Box Properties">
672 Each box is a full-fledged ECMAscript object, and can store
673 key-value pairs as properties. Some of these keys have special
674 meaning, which will be explained later. Each box's numeric
675 properties hold its **child boxes**.
677 <section title="Rendering Properties">
679 Every box has several special properties which control how it is
680 drawn. In general, if you put an
681 invalid value to a special property, no action will be taken -- the
684 <property name="strokecolor" type="string" default="clear">
686 If the value is a 5-character hex string ([[#RGB]]),
687 7-character hex string ([[#RRGGBB]]), 9-character hex
688 string ([[#AARRGGBB]]), the box's stroke color will be set
691 If the value is one of the <link
692 url="http://www.color.org/ICC-1A_1999-04.PDF"
693 text="ICC"/> colors (the same set of color names
694 supported by SVG), the stroke color be set to that color.
696 If the value is [[null]], the stroke color will be set
697 to clear ([[#00000000]]).
700 <property name="strokewidth" type="int" default="1">
701 The width (in pixels) to stroke the path with.
704 <property name="fill">
705 This property can be set to any of the values specified for
707 Alternatively, if the value written is an object, its stream
708 will be read and interpreted as a PNG, GIF, or JPEG image,
709 which will become the texture for this box, and the box's
710 [[minwidth]] and [[minheight]] properties will be
711 automatically set to the dimensions of the image.
714 <property name="path" type="string" default='""'>
715 The box's path. The grammar and feature set supported are
716 identical to that specified in <link
717 url="http://www.w3.org/TR/SVG11/paths.html" text="SVG 1.1,
721 <property name="text" type="string" default='""'>
722 The box's text; writing [[null]] to this property sets it
726 <property name="textcolor" type="number" default="black">
727 The color in which to render the font; accepts the same values as [[strokecolor]].
730 <property name="font" type="stream" default=".ibex.ui.font.sansserif">
731 When an object is written to this property, its stream is read
732 using the <link url="http://www.freetype.org" text="FreeType 2 library"/>,
733 and the resulting font is used to render the
737 <property name="fontsize" type="number" default="10">
738 The size (in points) to render the text.
743 <section title="Layout Properties">
745 <property name="shrink" type="boolean" default="false">
746 If set to [[true]], this box will shrink
747 (horizontally/vertically/both) to the smallest size allowed by
748 its children and the bounding box of its path.
751 <property name="x y" type="integer" default="varies">
752 If the box is a root box, this is the (x/y)-coordinate of the
753 surface; otherwise it is the distance between the parent's
754 alignment point and the corresponding corner/edge/center of
758 <property name="minwidth minheight" type="integer" default="0">
759 The desired minimum width and height.
762 <property name="maxwidth maxheight" type="integer" default="ibex.ui.maxdim">
763 The desired maximum width and height.
766 <property name="width height" type="integer">
767 When read, this is the current (width/height) of this box.
768 Writing to this property is equivalent to writing to
769 **both** the minimum and maximum (width/height).
772 <property name="cols rows" type="integer" default="0">
773 The number of (columns/rows) in which to lay out the children of this
774 box. If set to zero, the number of (columns/rows) is unconstrained.
775 Either [[rows]] or [[cols]] must be zero. If
776 [[0]] is written to [[cols]] when [[rows]] is
777 [[0]], the write is ignored. If a nonzero value is
778 written to [[cols]] when [[rows]] is nonzero,
779 [[rows]] is set to [[0]], and vice versa.
782 <property name="colspan rowspan" type="integer" default="1">
783 The number of (columns/rows) that this box spans within its parent.
786 <property name="align" type="string" default="center">
787 Determines the box's alignment point for positioning its text,
788 texture, path, and children.
791 <property name="visible" type="boolean" default="true">
792 If set to [[false]], this box will be rendered as if its
793 width and height were zero. If this is a root box, the
794 associated surface will be hidden.
796 When reading from this property, the value [[false]] will
797 be returned if this box **or any of its ancestors** is not
798 visible. Thus it is possible to write [[true]] to a box's
799 [[visible]] property and then read back [[false]].
802 <property name="packed" type="boolean" default="true">
803 The layout strategy for this box. If set to [[true]], the
804 box occupies no cells and is laid out independently of its
810 <section title="Child Control Properties">
812 <property name="redirect" type="box" default="thisbox">
813 Writing to this property sets the box's redirect target. This
814 property cannot be read from, and can only be written to if
815 the value being written is a **descendant** of the current
818 If a box has a non-null redirect target, reads and writes to
819 any of the other properties in this section will be forwarded
820 to the redirect target.
822 The [[redirect]] attribute is very useful for hiding the
823 internal structure of a widget, and for allowing widgets to act as
824 "smart" containers for other widgets. For example, a menu widget might
825 have an invisible child as its redirect target; this way, when boxes
826 representing items on the menu are added as children of the menu
827 widget, they do not appear until the menu is pulled down.
830 <property name="numeric properties" type="int" default="">
831 The **n**th child of box [[b]] can be accessed by reading from
832 [[b[n]]]. The **n**th child can be removed by writing
833 [[null]] to [[b[n]]] (the child will become parentless). A
834 new child can be inserted **before** the **n**th child by
835 writing it to [[b[n]]]; if the value written is already a child of
836 [[b]], it will be removed from [[b]] first. It is important
837 to note that this behavior is different from ECMAscript arrays --
838 writing a non-[[null]] value to [[b[n]]] does not eliminate
839 the **n**th child; it merely shifts it over one position.
840 __Note:__ Unlike most JavaScript objects, enumerating a Box's
841 properties with the JavaScript [[for..in]] construct will
842 enumerate **only** the box's children and not any other properties.
845 <property name="clip" type="boolean" default="true">
846 If [[true]], the visual representation of this box's
847 children will be clipped to the boundaries of this box.
848 __Note:__ setting this property to [[false]] imposes a
849 substantial performance penalty.
852 <property name="numchildren" type="integer" default="0">
853 The number of children this box has.
857 <property name="surface" type="" default="null">
859 If this box has a parent, this property returns
860 [[**parent**.surface]]; otherwise it returns null.
861 This property is a simple building block that the widget
862 library uses to implement more complex functionality such as
863 focus control and popups.
868 <section title="Other Box Properties">
870 <property name="cursor" type="string" default="null">
871 The shape that the cursor should take when inside this
872 box. Valid values are: "[[default]]" , "[[wait]]",
873 "[[crosshair]]", "[[text]]", "[[hand]]", and
874 "[[move]]", as well as resizing cursors"[[east]]",
875 "[[west]]", "[[north]]", "[[south]]",
876 "[[northwest]]", "[[northeast]]",
877 "[[southwest]]", and "[[southeast]]". Note that on
878 some platforms, resize cursors for opposite directions (such
879 as [[northwest]] and [[southeast]] are the
881 If a box's cursor is [[null]], its parent's cursor will
882 be used. If the root box's cursor is null, the
883 "[[default]]" cursor will be used.
886 <property name="static" type="object" default="N/A">
887 Reading from this property will return the parent scope used
888 to execute the [[<static/>]] block of the template
889 in which the currently-executing code resides.
892 <property name="thisbox" type="box" default=" ">
893 Returns a reference to the box itself.
894 If [[null]] is written to this property, and this box is
895 the root box of a surface, the box will be detached and the
896 surface destroyed. If this box has a parent, it will be
897 detached from its parent.
900 <property name="indexof()" type="function" default=" ">
901 This property is actually a function; invoking
902 [[parent.indexof(child)]] will return the numerical index
903 of [[child]] in [[parent]] if [[child]] is a
904 child of [[parent]] (or [[parent]]'s redirect
905 target), and [[-1]] otherwise. Writing to this property
909 <property name="distanceto()" type="function" default=" ">
910 This property is actually a function; invoking
911 [[box.distanceto(otherbox)]] will return an object with two
912 properties, [[x]] and [[y]], containing the horizontal
913 and vertical distance between the two boxes (negative if
914 [[otherbox]] is to the left of / above [[box]]). This
915 can be used to determine the relative placement of two boxes
916 on different branches of the box tree.
921 <section title="Root Box Properties">
923 The following special properties are only meaningful on the root box
926 <property name="Focused">
927 The value [[true]] is put to this property on the root box
928 when the surface gains the input focus, and [[false]] when
929 the surface loses the input focus. Reading from this value will
930 return [[true]] if the surface is focused and [[false]]
931 if it is not. Putting [[true]] to this property will
932 **not** cause the surface to "steal" the input focus from other
936 <property name="Maximized">
937 The value [[true]] is put to this property on the root box
938 when the surface is maximized, and [[false]] when the surface
939 is un-maximized. Reading from this value will return [[true]]
940 if the surface is maximized and [[false]] if it is
941 not. Putting [[true]] to this property will maximize the
942 window, and putting [[false]] to this property will
943 unmaximize the window.
944 Note that not all platforms support maximization.
947 <property name="Minimized">
948 The value [[true]] is put to this property on the root box
949 when the surface is minimized, and [[false]] when the surface
950 is unminimized. Reading from this value will return [[true]]
951 if the surface is minimized and [[false]] if it is
952 not. Putting [[true]] to this property will minimize the
953 window, and putting [[false]] will unminimize it.
956 <property name="Close">
957 When the user attempts to close a surface, the value
958 [[true]] will be put to this property. Scripts may trap
959 this property to prevent the window from closing. Putting the
961 [[true]] to this property on a root box has the same
962 effect as putting [[null]] to the [[thisbox]]
966 <property name="icon">
967 The surface's icon. This is usually displayed on the titlebar of a
968 window. The value should be an object whose stream is a PNG image. Note
969 that not all platforms support this property.
972 <property name="titlebar">
973 The surface's titlebar text. Note that not all platforms support
974 this property. Only ASCII characters 0x20-0x7F are permitted.
981 <!-- ----------------------------------------------------------------------- -->
982 <section title="Streams">
984 <heading title="Every object has a stream..."/>
986 Every object has a **stream** associated with it. A stream is a
987 sequence of bytes that can be read or written to.
989 By default an object has an empty stream (zero bytes). However, some objects
990 (returned from special methods on the [[ibex]] object) have
991 streams yielding data read from an url, file, or a component of a zip
992 archive. In a future release, the stream associated with a box will
993 be an .ibex template which, when applied, will fully reconstitute the
996 <heading title="...but streams are not objects"/>
998 Despite the ubiquity of streams, you cannot actually reference a
999 stream, since it is not an object. Instead, you simply reference the
1000 object it belongs to. If you are familiar with Java, this is similar
1001 to how every Java object has a monitor associated with it, but you
1002 cannot directly manipulate the monitor (you can't pass around a
1003 reference to just the monitor).
1005 In the rest of the section we will sometimes refer to "getting
1006 properties from a stream" or "passing a stream to a function"; this is
1007 just shorthand for saying to perform those actions on the object the
1010 <section title="Creating Streams from URLs">
1012 You can create a stream from a URL by calling
1015 var r = ibex.stream.url("http://...");
1018 This will return an object whose stream draws data from the specified
1019 URL. Streams are loaded lazily whenever possible.
1023 <section title="Getting Substreams">
1025 Most stream objects let you access
1026 substreams using the usual JavaScript operators [[[]]] and
1027 [[.]], as well as the [[for..in]] syntax.
1030 // r1 and r2 are equivalent but not equal (!=)
1031 var r1 = ibex.stream.url("http://www.ibex.org/foo/bar.html");
1032 var r2 = ibex.stream.url("http://www.ibex.org/foo")["bar.html"];
1037 <section title="The Root Stream">
1039 The empty-string property on the [[ibex]] object is called the
1040 **root stream**. You can access this object as [[ibex..]] or
1041 [[ibex[""]]]. Additionally, any expression which starts with a
1042 dot is treated as property to be retrieved from the root stream. The
1043 following three expressions are equivalent:
1053 <section title="Static Blocks">
1057 You can access variables within the static block of a template by
1058 appending a double period ([[..]]) and the variable name to the
1059 stream used to load that template:
1062 <!-- org/ibex/themes/linux/scrollbar.ibex -->
1066 ibex.log.print(org.ibex.themes.linux.scrollbar..foo); // prints "12"
1071 <section title="Formatting Streams">
1073 If you attempt to send a stream as part of an XML-RPC call, the
1074 stream will be read in its entirity, Base64-encoded, and transmitted
1075 as a [[<base64/>]] element.
1077 Ibex supports two special URL protocols. The first is [[data:]],
1078 which inteprets the rest of the URL as a Base64 encoded sequence of
1079 bytes to use as a source. The other is [[utf8:]] which
1080 interpretets the rest of the string as a Unicode character sequence to
1081 be UTF-8 encoded as a string of bytes to use as a source.
1084 var r5 = ibex.stream.url("data:WFWE876WEh99sd76f");
1085 var r6 = ibex.stream.url("utf8:this is a test");
1088 You can read a UTF-8 encoded string from a stream like this:
1091 var myString = ibex.stream.fromUTF(ibex.stream.url("utf8:testing..."));
1093 You can also parse XML from a stream using SAX like this:
1096 ibex.stream.xml.sax(
1097 ibex.stream.url("http://foo.com/foo.xml"),
1098 { beginElement : function(tagname, attributeKeyValuePairs) { ... },
1099 endElement : function(tagname) { ... },
1100 content : function(contentString) { ... }
1101 whitespace : function(whitespaceString) { ... }
1109 <!-- ----------------------------------------------------------------------- -->
1110 <section title="The Ibex object">
1112 The [[ibex]] object is present in the top-level scope of every
1113 script. It has the following properties:
1115 <heading title="General"/>
1117 <property name="ibex.box">
1118 reading from this property returns a new box
1120 <property name="ibex.clone(o)">
1121 creates a clone of object
1123 <property name="ibex.bless(s)">
1124 returns a blessed clone of stream
1127 <heading title="ECMA Library Objects"/>
1129 <property name="ibex.date">
1130 reading from this property returns a new date
1132 <property name="ibex.math">
1133 this object contains the ECMA math functions
1135 <property name="ibex.regexp(s)">
1136 return a regexp object corresponding to string **s**
1138 <property name="ibex.string">
1139 this object contains the ECMA string manipulation functions
1142 <heading title="Logging"/>
1144 <property name="ibex.log.debug(m1, ... mn)">
1145 log the debug messages **m1** through **mn**.
1149 <property name="ibex.log.info(m1, ... mn)">
1150 log the info messages **m1** through **mn**.
1153 <property name="ibex.log.warn(m1, ... mn)">
1154 log the warning messages **m1** through **mn**.
1157 <property name="ibex.log.error(m1, ... mn)">
1158 log the error messages **m1** through **mn**.
1161 <heading title="User Interface"/>
1163 <property name="ibex.ui.browser(u)">
1164 opens a new browser window with URL **u**
1167 <property name="ibex.ui.key.control">
1168 true if the control key is depressed
1171 <property name="ibex.ui.key.shift">
1172 true if the shift key is depressed
1175 <property name="ibex.ui.key.alt">
1176 true if the alt key is depressed
1179 <property name="ibex.ui.key.name.alt">
1180 the name of the "alt" key (usually either "alt", "meta", or
1184 <property name="ibex.ui.clipboard">
1185 the contents of the clipboard; can be read and written to
1188 <property name="ibex.ui.maxdim">
1189 the maximum dimension of any UI element; usually
1190 2<sup>31</sup>, but may be smaller
1193 <property name="ibex.ui.screen.width">
1194 the width of the screen, in pixels
1197 <property name="ibex.ui.screen.height">
1198 the height of the screen, in pixels
1201 <property name="ibex.ui.mouse.button">
1202 either 0, 1, 2, or 3, indicating the mouse button currently
1206 <property name="ibex.ui.frame">
1207 when a box is written to this property, it becomes the root
1211 <property name="ibex.ui.window">
1212 when a box is written to this property, it becomes the root
1216 <property name="ibex.ui.font.serif">
1217 an object whose stream is a a builtin serif font
1220 <property name="ibex.ui.font.sansserif">
1221 an object whose stream is a builtin sans-serif font
1224 <property name="ibex.ui.font.monospace">
1225 an object whose stream is a a builtin fixed-width font
1228 <heading title="Networking"/>
1230 <property name="ibex.net.rpc.xml(u)">
1231 return an XML-RPC call object with endpoint URL **u**
1234 <property name="ibex.net.rpc.soap(u,">
1235 return a SOAP call object with endpoint URL **u**,
1236 SoapAction **a**, and XML Namespace **n**
1239 <heading title="Threads"/>
1241 <property name="ibex.thread">
1242 when a function is written to this property, a new thread is
1246 <property name="ibex.thread.yield()">
1247 yield the current thread
1250 <property name="ibex.thread.sleep(n)">
1251 sleep for **n** milliseconds
1254 <heading title="Streams"/>
1256 <property name="ibex.stream.url(u)">
1257 returns a new object whose stream is drawn from URL **u**
1260 <property name="ibex.stream.unzip(s)">
1261 unpacks a zip archive from **s**'s stream
1264 <property name="ibex.stream.uncab(s)">
1265 unpacks a cab archive from **s**'s stream
1268 <property name="ibex.stream.cache(s,k)">
1269 valign=top>wraps a disk-backed read cache keyed on **k**
1270 around **s**'s stream
1273 <property name="ibex.stream.watch(s,f)">
1274 returns an object whose stream is drawn from **s**'s
1275 stream, but invokes **f(n,d)** as it is read from.
1278 <property name="ibex.stream.parse.xml(s, h)">
1279 Use SAX to parse the XML document on stream **s** with
1283 <property name="ibex.stream.parse.html(s, h)">
1284 Same as [[parse.xml()]], but tries to fix broken HTML.
1287 <property name="ibex.stream.parse.utf8(s)">
1288 treat **s**'s stream as a string encoded as a UTF-8 byte stream and return the string
1291 <property name="ibex.stream.homedir">
1292 [[ibex.stream.tempdir]]
1295 <heading title="Cryptography"/>
1297 <property name="ibex.crypto.rsa(k,s)">
1298 **not implemented yet:** return a
1299 stream which rsa-decrypts stream **s** with key **k**
1302 <property name="ibex.crypto.rc4(k,s)">
1303 **not implemented yet:** return a
1304 stream which rc4-decrypts stream **s** with key **k**
1307 <property name="ibex.crypto.md5(s)">
1308 **not implemented yet:** immediately
1309 MD5-hash stream **s**
1312 <property name="ibex.crypto.sha1(s)">
1313 **not implemented yet:** immediately
1314 SHA1-hash stream **s**
1318 <!-- ----------------------------------------------------------------------- -->
1319 <section title="Traps">
1321 You can add a trap to a property by applying the [[++=]] operator
1322 to a function with one argument. The trap will be invoked whenever
1323 that property is written to.
1327 foo ++= function(z) {
1328 ibex.log.info("foo is " + z);
1333 If another script were to set the property "[[foo]]"
1334 on the box above to the value [[5]], the function above would be
1335 invoked with the argument [[5]]. The function would then log
1336 the string "[[foo is 5]]".
1338 Within a trap, the expression [[trapee]] can be used to
1339 get a reference to the box on which the trap was placed.
1341 The expression [[trapname]] returns the name of the
1342 trap executing the current function. This is useful when a function
1343 is applied to multiple traps. For example:
1347 func ++= function(z) {
1348 ibex.log.info("called trap " + trapname);
1355 <section title="Removing Traps">
1357 You can remove a trap by using the [[--=]] operator with the same
1358 function you added as a trap:
1362 var myfunc = function(z) { /* ... */ }
1373 <heading title="Multiple Traps on the Same Property"/>
1375 When the trapped property is **written** to, each of the trap
1376 functions placed on it will be invoked in the opposite order that
1377 they were placed on the box -- the most recently placed trap will
1378 execute first. This last-to-first execution of traps is called
1379 **cascading**. After the last trap is invoked, the value is
1380 stored on the box (remember, boxes are objects, so they can hold
1381 properties just like all other ECMAscript objects).
1383 <section title="Manual Cascades">
1385 There are two additional tricks you can use when placing traps. The
1386 first is a **manual cascade**. If you want to cascade to lower
1387 traps in the middle of a function, or you want to cascade with a
1388 different value than the value passed to you (in effect "lying" to
1389 lower traps), you can use [[cascade]]. For example:
1392 <ui:box color="black">
1393 color ++= function(c) {
1394 ibex.log.info("refusing to change colors!");
1400 This effectively creates a box whose color cannot be changed, and
1401 which complains loudly if you try to do so.
1403 Do **not** try to do something like this:
1406 <ui:box color="black">
1407 color ++= function(z) {
1408 color = "black"; // INFINITE LOOP! BAD!!!
1412 To prevent automatic cascading, return [[true]] from your function:
1415 <ui:box color="black">
1416 color ++= function(z) {
1417 return true; // the box's color will not change
1424 <section title="Read Traps">
1426 The other trick is a **read-trap**. Read traps are just like normal
1427 traps, except that you use a function that takes zero arguments instead of one. Read traps
1428 also do not automatically cascade.
1432 doublewidth [[++=]] function() { return 2 * width; }
1436 If another script attempts to read from the [[doublewidth]]
1437 property on this box, the value it gets will be twice the actual width
1438 of the box. Note that
1439 the actual [[doublewidth]] property on the box never gets written
1440 to, since the trap does not cascade.
1442 You can manually cascade on read traps as well:
1446 text [[++=]] function() { return "my text is " + cascade; }
1450 Read traps are only rarely needed -- most of the time a write trap
1455 <heading title="Prohibited Traps"/>
1457 To prevent confusing and hard-to-debug behaviors, scripts may not
1458 place traps on any of the properties described in the sections
1459 <link text="Box Layout Properties" section="Layout Properties"/>, <link
1460 section="Child-Control Properties"/>, or <link section="Other Box
1461 Properties"/> except for [[childadded]],
1462 [[childremoved]] and [[surface]]. FIXME: remove?
1464 <heading title="Exceptions and Traps"/>
1466 If an uncaught exception is thrown from a trap, Ibex will log the
1467 exception, but will **not** propagate it to the code which
1468 triggered the trap. If the trap was a read trap, the value
1469 [[null]] will be returned.
1470 FIXME: is this right?
1472 <heading title="Architectural Significance of Traps"/>
1474 Traps are the backbone of Ibex. Since almost all UI programming is
1475 event/demand driven, traps eliminate the need for separate
1476 member/getter/setter declarations, often cutting the amount of typing
1477 you have to do to a third of what it would normally be.
1479 <section title="Cloning">
1481 **Cloning** is a companion technique for traps; together they can
1482 be used to simulate any sort of environment you might need. When you
1483 call [[ibex.clone(o)]], Ibex returns a new object (called the
1484 **clone**) which compares with equality ([[==]]) to the
1485 original object. Furthermore, both objects are "equal" as keys in
1490 var theclone = ibex.clone(o);
1492 ibex.log.info(hash[theclone]); // prints "5"
1495 Any writes to properties on the clone will actually write to
1496 properties on the original object, and reads from properties on the
1497 clone will read properties on the original object. In fact, the only
1498 thing that can be used to distinguish the original from the clone is
1499 traps -- a trap placed on the clone is **not** placed on the
1500 original object as well.
1505 <!-- ----------------------------------------------------------------------- -->
1506 <section title="Threads">
1508 <section title="Contexts">
1510 From the perspective of an application writer, Ibex is strictly
1511 single-threaded. Ibex is always in exactly one of the following three
1514 <list type="unordered">
1516 __Rendering Context__ -- (redrawing the screen)
1518 __Event Context__ (executing javascript traps triggered by an event)
1520 __Thread Context__ (executing a background thread spawned with [[ibex.thread]])
1524 There are two important restrictions on what can be done in particular contexts:
1526 <list type="unordered">
1528 The [[box.mouse]] property and its subproperties
1529 ([[x]], [[y]], and [[inside]]) can only be read
1530 from within the Event Context, or in a thread context
1531 **after** a the [[box.mouse]] property on this box or
1532 an ancestor box has been written to.
1534 Blocking operations (anything that accesses the network or
1535 disk) can only be performed in the Thread Context.
1541 <section title="Background Threads">
1543 Ibex offers easy access to threads. Spawning a background thread is as
1544 simple as writing a function to the [[ibex.thread]] property:
1547 ibex.thread = function() {
1548 ibex.log.info("this is happening in a background thread!");
1552 The argument set passed to the function is currently undefined and is
1553 reserved for use in future versions of Ibex. Scripts should not
1554 depend on the number or content of these arguments.
1556 Ibex is **cooperatively multitasked**, so threads must not process
1557 for too long. This was a deliberate choice; cooperatively
1558 multitasked environments do not require complex locking primitives
1559 like mutexes and semaphores which are difficult for novices to
1560 understand. The disadvantage of cooperative multitasking is that one
1561 thread can hog the CPU. This is unlikely to happen in Ibex for two reasons:
1562 first, all blocking I/O operations **automatically** yield the CPU,
1563 so the overall user interface never becomes unresponsive because it is
1564 waiting for a disk or network transfer. Second, since Ibex is strictly
1565 a user interface platform, Ibex scripts are unlikely to perform highly
1566 compute-intensive operations that keep the CPU busy for more than a
1572 <section title="Events">
1574 Every execution of the Event Context begins with an event, which
1575 consists of a key/value pair, and a mouse position, which consists of
1576 an x and y coordinate. The possible keys are [[_Press[1-3]]],
1577 [[_Release[1-3]]], [[_Click[1-3]]], [[_DoubleClick[1-3]]],
1578 [[_Move]], [[_KeyPressed]], and [[_KeyReleased]].
1580 Here are two example events:
1582 An event is triggered by writing the key to the value on a box. This
1583 triggers any trap handlers which may be present. Once these handlers
1584 have executed, Ibex figures out which child of the current box contains
1585 the mouse (taking into account that some boxes may cover up others)
1586 and writes the key and value to that box. If none of the box's
1587 children contain the mouse position, Ibex removes the leading
1588 underscore from the key name and writes the value to
1589 **that** property. Once all the traps on that property have
1590 executed, the value is written to the box's parent.
1592 Intuitively, Ibex delivers the underscored event to every box from the
1593 root to the target, and then delivers the non-underscored event to
1594 that same set of boxes in reverse order. So the event travels down
1595 the tree to the target, and then back up to the root. The following
1596 example prints out "first second third fourth" in that order.
1600 _Press1 ++= function(b) { ibex.log.info("first"); }
1601 Press1 ++= function(b) { ibex.log.info("fourth"); }
1603 _Press1 ++= function(b) { ibex.log.info("second"); }
1604 Press1 ++= function(b) { ibex.log.info("third"); }
1609 In general, you should use the **non-underscore** names to respond
1610 to user input and use the underscored names when you want to override
1611 child boxes' behavior or route events to particular boxes (for
1612 example, when implementing a focus protocol). This is why the
1613 underscored elements are delivered to parents before children (so
1614 parents can override their childrens' behavior), but non-underscored
1615 events are delivered to children before parents (since, visually, a
1616 mouse click is usually "intended" for the leaf box underneath the
1621 <heading title="Stopping the Process"/>
1623 At any point in this sequence, a trap handler can choose not to
1624 cascade (by returning [[true]] from the trap handler function).
1625 This will immediately cease the propagation of the event. This is how
1626 you would indicate that an event has been "handled".
1628 <heading title="Non-Propagating Events"/>
1630 Ibex uses the following events to notify a box about changes that
1631 only matter to that particular box. These events do not propagate
1632 either up or down the tree.
1634 <property name="Enter Leave">
1635 The value [[true]] is written to this property when the mouse (enters/leaves) the box.
1638 <property name="SizeChange">
1639 The value [[true]] is put to this property after the size
1640 of this box changes.
1643 <property name="ChildChange">
1644 When a child is added or removed, that child is written to
1645 this property. The write is always performed **after** the
1646 addition or removal, so these two cases can be distinguished
1647 by checking [[indexof(child)]].
1649 Note that if the parent's redirect target is set to another
1650 box, this trap will only be invoked when children are
1651 manipulated by reading and writing to the parent. Reads and
1652 writes directly to the redirect target will **not** trigger
1655 Note also that this traps is still triggered if a box's
1656 [[redirect]] target is **null**. This is useful for
1657 boxes that need to accept children and then relocate them
1661 <section title="Listing of Events">
1663 <property name="Press1 Press2 Press3">
1664 Indicates that the use has pressed a mouse button. On
1665 platforms with three mouse buttons, the **middle** button
1666 is button 3 -- this ensures that applications written to only
1667 use two buttons (1 and 2) will work intuitively on three button
1671 <property name="Release1 Release2 Release3">
1672 Indicates that the use has released a mouse button.
1675 <property name="Click1 Click2 Click3">
1676 Indicates that the user has pressed and released the
1677 mouse button without moving the mouse much (exactly how
1678 much is platform-dependent).
1681 <property name="DoubleClick1 DoubleClick2 DoubleClick3">
1682 Indicates that the user has clicked the
1683 mouse button twice within a short period of time (exactly how long is platform-dependent).
1686 <property name="Move">
1687 Indicates that the mouse has moved while within this box, or that
1688 the mouse while outside this box **if a button was pressed while within this box and has not yet been released**
1691 <property name="KeyPressed KeyReleased">
1693 A string is written to this property when a key is pressed or
1694 released If the key was any other key, a multi-character
1695 string describing the key will be put. For simplicity, we use
1696 the VK_ constants in the <link
1697 url="http://java.sun.com/products/jdk/1.1/docs/api/java.awt.event.KeyEvent.html#VK_0"
1698 text=" Java 1.1 API java.awt.event.KeyEvent class"/>. When a
1699 key is pressed or released, the string put will be the portion
1700 of its VK_ constant after the underscore, all in lower case.
1703 If the shift key was depressed immediately before the
1704 event took place, then the string will be capitalized. Special
1705 keynames are also capitalized; shift+home is reported as
1706 "[[HOME]]". Symbols are capitalized as they appear on the
1707 keyboard; for example, on an American QWERTY keyboard, shift+2
1708 is reported as "[[@]]".
1710 If the alt, meta, or command key was depressed immediately
1711 before this key was pressed, then the string will be prefixed
1712 with the string "[[A-]]". If the control key was depressed
1713 while this key was pressed, then the string will be prefixed
1714 with the string "[[C-]]". If both alt and control are
1715 depressed, the string is prefixed with "[[C-A-]]".
1717 Ibex does not distinguish between a key press resulting from
1718 the user physically pushing down a key, and a 'key press'
1719 resulting from the keyboard's typematic repeat. In the rare
1720 case that an application needs to distinguish between these
1721 two events, it should watch for KeyReleased messages and
1722 maintain an internal key-state vector.
1730 <!-- ----------------------------------------------------------------------- -->
1731 <section title="Networking">
1733 <section title="XML-RPC">
1735 XML-RPC objects can be created by calling [[ibex.net.rpc.xml(**XML-RPC
1736 URL**)]], and then invoking methods on that object. For example,
1739 Press1 += function(v) {
1740 ibex.thread = function() {
1741 color = ibex.net.rpc.xml("http://xmlrpc.ibex.org/RPC2/").
1742 color.getTodaysColor("Friday");
1747 When the user clicks the first mouse button on this box, it will
1748 contact the server [[xmlrpc.ibex.org]], route to the
1749 [[/RPC2/]] handler and invoke the [[getTodaysColor()]]
1750 method on the [[color]] object with a single string argument
1751 "[[Friday]]". The return value will be used to change the color
1752 of the box the user clicked on.
1754 Note that in this example we spawned a background thread to handle the
1755 request -- the [[Press1]] event is delivered in the foreground
1756 thread, and XML-RPC methods may only be invoked in background
1757 threads. This is to prevent the UI from "locking up" if the server
1758 takes a long time to reply.
1760 If the XML-RPC method faults, an object will be thrown with two
1761 properties: [[faultCode]] and [[faultString]], as defined in
1762 the <link url="http://www.xmlrpc.org/spec" text="XML-RPC specification"/>. If
1763 Ibex encounters a network, transport, or session-layer error, it will
1764 throw a [[String]] object describing the error in a
1765 human-readable format. Scripts should not rely on the contents of
1766 this string having any special structure or significance.
1768 If an object with an associated non-empty stream is passed as an
1769 argument to an XML-RPC method, it will be sent as a <base64/>
1770 element. If a <base64/> element is found in the XML-RPC reply, it
1771 will be returned as an object with a stream drawn from that byte sequence.
1773 Each object returned by [[ibex.net.rpc.xml()]] represents a
1774 single HTTP connection. The connection will be held open until
1775 the object is garbage collected or the server closes the
1776 connection. If a second call is issued on the object before the
1777 first one returns (usually from a seperate thread), the two calls
1779 url="http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.1.2.2"
1780 text="pipelined"/>. This can dramatically improve performance.
1782 Ibex supports HTTP Basic and Digest authentication. To use
1783 authentication, pass [[ibex.net.rpc.xml()]] a URL in the form
1786 http[s]://user:password@hostname/
1789 Ibex will use Digest authentication if the server supports it;
1790 otherwise it will use Basic authentication. Please be aware that
1791 many XML-RPC server implementations contain a <link
1792 url="http://www.ibex.org/faq.html#auth" text="broken
1793 implementation of Basic authentication"/>.
1797 <section title="SOAP">
1799 SOAP methods are invoked the same way as XML-RPC methods, but with three differences:
1801 <list type="ordered">
1803 [[ibex.net.rpc.soap()]] is used instead of
1804 [[ibex.net.rpc.xml()]]
1806 Instead of specifying just the URL of the service itself, you
1807 must specify the URL, the SOAPAction argument, and the
1810 The actual method invocation takes only one argument, which
1811 must be an object. This is necessary since SOAP arguments are
1812 specified by name, rather than ordering.
1816 SOAP faults are handled the same way as XML-RPC faults except that the
1817 capitalization of the [[faultstring]] and [[faultcode]]
1818 members is all lower-case, to match the SOAP spec. Here is a
1822 Press1 ++= function(v) {
1823 ibex.thread = function() {
1824 color = ibex.net.rpc.soap("http://soap.ibex.org/SOAP",
1826 "http://ibex.org/namespace"
1827 ).color.getTodaysColor( {
1834 As you can see, SOAP is much more verbose, yet does not offer
1835 substantially improved functionality. We recommend that XML-RPC be
1836 used whenever possible, and that SOAP be reserved for legacy
1839 The current Ibex SOAP stack does not support 'document style' or
1840 multi-ref ([[href]]) data structures.
1844 <section title="Security">
1846 Applications downloaded from the network (as opposed to those loaded
1847 from the filesystem) may only make certain kinds of connections to
1848 certain hosts. See Appendix A for a detailed description of the
1854 <!-- ----------------------------------------------------------------------- -->
1855 <section title="Error Handling">
1857 If the Ibex Core encounters an error while servicing a function call
1858 originating in JavaScript, the core will throw a string consisting of
1859 an error code followed by a colon, a space, and a descriptive message.
1863 "ibex.net.dns.unknownhostexception: unable to resolve host foo.com"
1866 The code should be used to determine how the program should respond to
1867 an error. The codes are organized in a hierarchy, so the
1868 string.startsWith() method can be used to determine if an error lies
1869 within a particular subhierarchy. The descriptive message portion of
1870 the string may be shown to the user.
1872 <property name="ibex.assertion.failed">
1875 <property name="ibex.io">
1876 General I/O exceptions
1878 <property name="ibex.io.encoding">
1879 Error translating between character encodings.
1881 <property name="ibex.io.zip">
1882 Attempted to access a corrupt zip archive.
1884 <property name="ibex.io.eof">
1885 End of file encountered unexpectedly
1887 <property name="ibex.net.security.prohibitedHost">
1888 A piece of untrusted Ibex code attempted to contact a
1889 restricted host. See <link appendix="Security Architecture and Considerations"/> for details.
1891 <property name="ibex.net.dns.temporaryFailure">
1892 An attempt to resolve a hostname failed but it is not known
1893 for certain that the hostname is invalid.
1895 <property name="ibex.net.dns.unknownHost">
1896 An attempt to resolve a hostname failed because the hostname
1899 <property name="ibex.net.socket.closed">
1900 A socket was closed unexpectedly.
1902 <property name="ibex.net.socket.connectionFailed">
1903 A connection could not be made to the remote host.
1905 <property name="ibex.net.url.malformed">
1906 Tried to parse a malformed URL.
1908 <property name="ibex.net.ssl">
1909 General SSL protocol errors.
1911 <property name="ibex.net.ssl.untrustedCertificate">
1912 The server's certificate was not signed by a CA trusted by Ibex.
1914 <property name="ibex.net.http.">
1915 Thrown when an HTTP error code is returned during an
1916 operation. The three characters [[**xyz**]] will be
1917 the three-digit HTTP status code.
1919 <property name="ibex.net.xmlrpc.null">
1920 The caller attempted to transmit the [[null]] value via XML-RPC.
1922 <property name="ibex.net.xmlrpc.circular">
1923 The caller attempted to transmit a circular data structure via XML-RPC.
1925 <property name="ibex.net.xmlrpc.specialObject">
1926 The caller attempted to transmit a "special" object via
1927 XML-RPC (for example, a Box or the Ibex object).
1929 <property name="ibex.null.put">
1930 A JavaScript attempted to put to a property on the [[null]] value
1932 <property name="ibex.null.get">
1933 A JavaScript attempted to get from a property on the [[null]] value
1935 <property name="ibex.null.call">
1936 A JavaScript attempted to call the [[null]] value
1939 If an exception is thrown inside a trap, the exception will propagate
1940 to the script that triggered the trap.
1942 If an uncaught exception is thrown while applying a template, or the
1943 requested template could not be found, an error will be logged and the
1944 box to which the template was being applied will be made invisible
1945 ([[visible = false]]). This ensures that half-applied widgets are
1946 never shown to the user.
1950 <!-- ----------------------------------------------------------------------- -->
1951 <section title="Advanced Topics">
1953 <section title="Re-routing events">
1955 At any point in the Event Context, you can write to the [[mouse]]
1956 property on any box. The value written should be an object with two
1957 properties, [[x]] and [[y]]. For example:
1960 _Press1 ++= function(p) {
1961 mouse = { x: 32, y: 77 };
1965 The coordinates specified are relative to the box whose [[mouse]]
1966 property is being written to. There is no need to supply the
1967 [[inside]] property; it is computed automatically. Writing to
1968 the [[mouse]] property causes Ibex to recompute the eventual
1969 target box, and also alter the values returned by [[mouse.x]],
1970 [[mouse.y]], and [[mouse.inside]] for any **descendants**
1971 of the current box. Writing to the [[mouse]] property also
1972 automatically prevents the event from returning to the box's parents
1973 -- it is equivalent to not cascading on the non-underscored event.
1974 This ensures that child boxes cannot trick their parent boxes into
1975 thinking that the mouse has moved.
1977 If you want the event to "skip over" the boxes between the trapee
1978 and the target, or if you want to re-route an event to a box which
1979 is not a descendant of the current box, simply write the value to
1980 the proper key on the target box.
1984 _KeyPressed = function(k) { ibex.log.info("first"); }
1985 KeyPressed = function(k) { ibex.log.info("sixth"); }
1986 $recipient.target = $target;
1987 <ui:box id="recipient">
1988 _KeyPressed = function(k) {
1989 ibex.log.info("second");
1990 thisbox.target.KeyPressed = k;
1991 // inhibit cascade; keep event from going to $excluded
1994 KeyPressed = function(k) { ibex.log.info("fifth"); }
1995 <ui:box id="excluded">
1996 _KeyPressed = function(k) {
1997 ibex.log.info("this never happens");
2001 <ui:box id="target">
2002 _KeyPressed = function(k) { ibex.log.info("third"); }
2003 KeyPressed = function(k) { ibex.log.info("fourth"); }
2010 <section title="Synthesizing Your Own Events">
2012 You can create "fake events" by simply writing to the [[mouse]]
2013 property and then writing a value to one of the underscored properties
2014 on a box. This will have exactly the same effect as if the use had
2015 actually pressed a key, clicked a button, or moved the mouse -- they
2016 are indistinguishable.
2020 <section title="Ibex self-emulation">
2022 When the core first starts up, it clones the [[ibex]] object,
2023 creates a stream for the initial .ibex, and then places a trap on the
2024 cloned [[ibex]] object so that its empty-string property returns
2025 the .ibex stream. The cloned Ibex object is then passed as the third
2026 (optional) argument to [[ibex.apply()]], making it the default
2027 [[ibex]] object for the scripts that are executed as part of the
2028 template instantiation.
2031 var new_ibex = ibex.clone(ibex);
2032 var stream = ibex.bless(ibex.stream.url("http://..."));
2033 new_ibex[""] ++= function() { return stream; }
2034 ibex.apply(ibex.box, new_ibex..main, new_ibex);
2037 Note that we called [[ibex.bless()]] on the stream before tacking
2038 it on to the new Ibex object. The bless function returns a clone of
2039 the object passed to it, with a few traps which are explained below.
2040 Additionally, any sub-streams retrieved by accessing properties of the
2041 blessed stream will also automatically be blessed (blessed streams are
2044 Blessing a stream serves three purposes:
2046 <list type="unordered">
2048 Blessed clones always return the appropriate static block when
2049 their empty property is accessed; this ensures that references
2050 to the static blocks of other templates work properly.
2052 Blessed substreams can return their parent stream by accessing
2053 a hidden property which is reserved for internal use by Ibex.
2054 This ensures that Ibex can automatically add filename
2055 extensions where needed, according to the following rules:
2058 If the stream is a template to be applied, the string
2059 "[[.ibex]]" is appended.
2061 If the stream is an image, the string "[[.png]]" is
2062 appended. If no stream is found, "[[.jpeg]]" and
2063 "[[.gif]]" are tried, in that order.
2065 If the stream is an font, the string "[[.ttf]]" is
2069 Every call to [[ibex.bless()]] returns a different object
2070 (which happens to be a clone of the object passed to it) with
2071 a completely separate set of static blocks.
2075 Ibex can self-emulate by using [[ibex.clone()]] on the Ibex object;
2076 this technique is very similar to the use of ClassLoaders in
2077 Java. This is useful for a number of applications, including
2078 debuggers, IDEs, sandboxing untrusted code, remote-control, and
2079 others. For example:
2082 var newLoadFunction = function(url) { /* ... */ };
2083 var new_ibex = ibex.clone(ibex);
2084 new_ibex.load ++= function() { return newLoadFunction; }
2085 ibex.apply(ibex.box, .main, new_ibex);
2090 <!-- ----------------------------------------------------------------------- -->
2091 <appendix title="Security Architecture and Considerations">
2093 Due to the expense and hassle imposed by the commercial PKI code
2094 signing architecture, and the fact that it <link
2095 url="http://www.counterpane.com/pki-risks-ft.txt" text="doesn't
2096 really provide any security anyways"/>, Ibex user interfaces are
2097 distributed as unsigned, untrusted code. As such, they are handled
2098 very carefully by the Ibex Core, and assumed to be potentially
2101 Ibex's security architecture is divided into defenses against four
2102 major classes of attacks:
2104 <heading title="Malicious UI attempts to acquire or alter data on the client"/>
2106 Ibex user interfaces are run in an extremely restrictive sandbox. The
2107 environment does not provide primitives for accessing any data outside
2108 the Ibex core except via XML-RPC and SOAP calls. There are no
2109 facilities to allow Ibex user interfaces to access the client's
2110 operating system or to interact with other applications on the same
2111 host (unless they provide a public XML-RPC or SOAP interface).
2112 An Ibex script may only access a file on the user's hard disk if the
2113 user explicitly chooses that file from an "open file" or "save file"
2114 dialog. There is one exception to this rule: if all templates
2115 currently loaded in the Ibex core originated from the local
2116 filesystem, those templates can load additional .ibexs from the local
2119 The Ibex Core is written in Java, so it is not possible for
2120 scripts to perform buffer overflow attacks against the core
2123 Ibex applications may only read from the clipboard when the user
2124 middle-clicks (X11 paste), presses control-V (Windows paste), or
2125 presses alt-V (Macintosh paste; the command key is mapped to Ibex
2126 "alt"). This ensures that Ibex applications are only granted access to
2127 data that other applications have placed on the clipboard when the user
2128 specifically indicates that that information should be made available
2129 to the Ibex application.
2131 <heading title="Malicious UI attempts to use client to circumvent firewalls"/>
2133 Ibex user interfaces may only make XML-RPC or SOAP calls and load .ibex
2134 archives via HTTP; they cannot execute arbitrary HTTP GET's or open
2135 regular TCP sockets.
2137 Ibex will not allow a script to connect to a non-public IP address
2138 (10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16, as specified in <link
2139 url="http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc1918.html" text="RFC
2140 1918"/>). There is one exception -- if all templates currently loaded
2141 in the core originated from the same IP address, those scripts may
2142 make calls to that IP address regardless of whether or not it is
2143 firewalled. If Ibex does not have access to a DNS resolver (because it
2144 is using a proxy which performs DNS lookups), Ibex will provide the
2145 proxy with the appropriate <link
2146 url="http://www.ibex.org/x-requestorigin.html"
2147 text="X-RequestOrigin"/> header that the proxy needs in order
2148 to maintain security.
2150 The only remaining possible attack is against a XML-RPC or SOAP
2151 service running on a firewalled host with a public address. Assigning
2152 such machines public IP addresses is a poor network security policy,
2153 and doing so squanders scarce public IPv4 addresses. As such, the onus
2154 is on the administrators of such machines to explicitly block access
2155 to clients reporting a [[User-Agent:]] header beginning with the
2156 four characters "[[IBEX]]".
2158 <heading title="Malicious UI attempts to trick user into divulging secret information"/>
2160 All top-level windows created by Ibex are **scarred** -- a stripe
2161 and a lock is drawn across the corner of the window. There is no way
2162 for a user interface to remove this scar. Ibex user interfaces may not
2163 create windows smaller than the size of the scar.
2165 <heading title="Malicious network attempts to snoop or man-in-the-middle transactions"/>
2167 Ibex user interfaces may transmit network data using HTTPS (SSL 3.0)
2168 for encryption. Ibex will attempt 128-bit encryption, but will
2169 negotiate down to 40-bit if the server does not support strong
2170 crypto. Ibex's SSL implementation is currently provided by <link
2171 url="http://www.ibex.org/tinyssl" text="TinySSL"/> and <link
2172 url="http://www.bouncycastle.org" text="The Legion of the Bouncy
2175 All HTTPS connections must be authenticated by the server using a
2176 certificate whose name matches the domain name of the HTTPS URL. The
2177 certificate must be signed by a trusted root CA. Ibex trusts the same
2178 93 root CAs whose certificates are included as "trusted" in Microsoft
2179 Internet Explorer 5.5 SP2. This provides a minimal level of protection
2180 against man-in-the-middle attacks; you should not trust this
2181 connection with any data you would not normally trust an SSL-enabled
2186 <!-- ----------------------------------------------------------------------- -->
2187 <appendix title="ECMAscript compliance">
2189 Ibex's scripts are written in a modified subset of ECMA-262, revision 3
2190 (aka JavaScript 1.5). The interpreter strays from the spec in a few
2193 <section title="Omissions">
2195 The following ECMA features are not supported:
2197 <list type="unordered">
2199 The [[undefined]] value, [[===]], and [[!==]]
2201 The [[new]] keyword (and ECMAScript object inheritance)
2204 [[getter]] and [[setter]]
2206 The ECMA [[this]] keyword.
2208 The [[String]], [[Number]], and [[Boolean]]
2209 classes. Note that [[string]], [[number]], and
2210 [[boolean]] values are supported, however.
2212 You may not [[throw]] the [[null]] value.
2216 Additionally, you must declare all root-scope variables (with
2217 [[var]]) before using them; failure to do so will result in an
2218 exception. Box properties are pre-defined in the scope that scripts
2223 <section title="Extensions">
2225 <list type="unordered">
2227 The token [[..]] is equivalent to [[[""]]].
2233 Extended [[catch]] syntax. The following code:
2235 } catch(e propname "foo.bar.baz") {
2242 if (e.propname != null and e.propname >= "foo.bar.baz" and
2243 "foo.bar.baz/" > e.propname) {
2248 Multiple extended-catch blocks can appear at the end of a single try
2249 block. However, at most one non-extended catch block may appear, and
2250 if it does appear, it must be the last one.
2252 Since Ibex ECMAscripts are wrapped in XML, the lexical token
2253 "[[lt]]" is be interpreted as [[<]], the lexical
2254 token "[[gt]]" is be interpreted as [[>]], and the
2255 token "[[and]]" is interpreted as [[&&]].
2256 Thus these tokens cannot be used as variable names.
2258 The identifier [[static]] is a reserved word in
2259 ECMAScript, but not in Ibex.
2261 Ibex defines an additional reserved word, "[[assert]]",
2262 which will evaluate the expression which follows it, throwing
2263 a [[ibex.assertion.failed]] exception if the expression
2264 evaluates to [[false]].
2266 To ensure that Ibex files appear the same in all text editors, tab
2267 characters are not allowed in Ibex files.
2271 Some useful tutorials include:
2273 <list type="unordered">
2276 url="http://developer.netscape.com/docs/manuals/communicator/jsref/index.htm"
2277 text=" JavaScript 1.2 Reference"/>. Although this document is
2278 out of date, it is arguably the best guide available for free
2279 on the Internet. The changes from JavaScript 1.2 (aka ECMA-262
2280 r1) to 1.5 were minimal, and many of them were <link
2281 url="ecmascriptcompliance" text="omitted"/> from Ibex.
2284 url="http://search.barnesandnoble.com/booksearch/isbnInquiry.asp?isbn=0596000480"
2285 text=" JavaScript: The Definitive Guide"/>, by David Flanagan
2286 and Paula Ferguson. The latest edition of this book covers
2287 JavaScript 1.5 (ECMA-262 r3).
2290 url="http://www.ecma.ch/ecma1/STAND/ECMA-262.HTM"
2291 text="ECMA-262"/> specification. This is an extremely
2298 <!-- ----------------------------------------------------------------------- -->
2299 <appendix title="Logging and Command Line Invocation">
2302 Usage: ibex [-lawp] [ url | file | directory ]
2303 -l [level] set logging level to { debug, info (default), warn, error, silent }
2304 -l rpc log all XML-RPC and SOAP conversations
2305 -l user@host email log to user@host
2306 -l host:port emit log to TCP socket
2307 -l [file] write log to a file on disk
2309 -w [window-id] reserved for libibex
2310 -p dump profiling information [not yet supported]
2313 If Ibex encounters a serious problem before it starts logging
2314 information, or if it is unable to open the log file, it will abort
2315 immediately with a critical abort, which will be displayed on the
2316 console for POSIX-native cores and in a dialog box for JVM-based and
2319 Note that Microsoft Windows does not provide any mechanism for
2320 redirecting standard input/output of an application which is not
2321 compiled as a "console application". Therefore, Ibex is compiled
2322 as a "console application", and will open a console window when
2323 invoked. To inhibit this console window, provide a logging
2324 destination (file, port, etc).
2326 The [[**source-location**]] parameter can be either the path
2327 to an [[.ibex]] archive, the http url of an [[.ibex]]
2328 archive, or the path to a directory comprising an unpacked
2331 The [[**initial-template**]] parameter is the stream name of
2332 a template to be used as the initial template. If ommitted, it
2333 defaults to [[main]].
2335 The [[-v]] option causes Ibex to enable verbose logging; this will
2336 cause it to log **lots** of information to the log file. This
2337 option will also substantially decrease Ibex's performance.
2341 <!-- ----------------------------------------------------------------------- -->
2343 <appendix title="Grammars">
2345 **Grammar support is experimental in this release
2346 and may not work properly. It may change in incompatible ways or
2347 disappear completely from future releases**
2349 Grammars are defined with a statement in the following form:
2354 A grammar is really just another function; once defined you can't tell
2355 it apart from an ordinary function. A grammar takes one argument,
2356 which can be a string or stream. The argument is parsed and the
2357 result of executing the code block 'c' is returned.
2359 The property 'a' is read; if the value is a grammar, a new production
2360 rule (ie a new alternative, as with '[[|]]') is added to that grammar
2361 (this is a destructive update). This allows you to add productions to
2362 pre-existing grammars (for example, adding a new type of expression to
2363 a programming language by extending the 'expr' grammar). If the old
2364 value is not a grammar, the value is discarded and a new grammar
2367 The value 'b' is a pattern, which may consist of seven simple
2370 <list type="unordered">
2373 grouping parens [[()]]
2375 combinators: [[ | + * ?]]
2377 references to other grammars
2380 The value 'c' and the braces surrounding it are an *optional* code
2381 block, in which the following identifiers are bound:
2383 <list type="unordered">
2385 The identifier 'whole' is bound to the string matched by the
2386 entire expression. If the code block is omitted it behaves
2387 as if it were "[[{ return whole; }]]".
2389 For every reference to another grammar which was matched in the
2390 pattern, the *name used to reference that other grammar* will
2391 be bound to the value returned by its code block. Here's an
2392 example of this important distinction:
2395 var foo ::= 'a' | 'b';
2397 var baz ::= 'c' | bar { /* foo is not defined here, but bar is */ };
2400 On the last line, the identifier 'bar' serves two purposes: it
2401 pulls in the definition of the pattern *and* acts as a binder
2402 within the scope of the braces.
2404 If a reference is matched multiple times (either because it
2405 appears multiple times in the pattern or because the * or +
2406 operator was applied to it) then its name will be bound to an
2407 array containing the matches.
2411 Here is the metacircular definition of the grammar facility:
2414 grammar ::= identifier '::=' pattern (';' | '{' code '}' ';'?)
2415 identifier ::= ('a'..'z' | 'A'..'Z' | '_' | '$') (identifier | '0'..'9')*
2416 char ::= '\0x0000'..'\0xffff'
2417 literal ::= '\'' char+ '\''
2418 | '\'' char '\'' '..' '\'' char '\''
2419 pattern ::= identifier
2426 | pattern '|' pattern
2431 Copyright (C) 2004 Adam Megacz, verbatim redistribution permitted.
2432 Ibex is a trademark of Adam Megacz