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 Each box occupies a rectangular region on the surface. The visual
406 appearance of a surface is created by rendering each box in its tree.
407 Unless the [[clip]] attribute is [[false]], each box will
408 clip its childrens' visual representations to its own, so that the
409 children appear "confined to" the parent. Children are rendered after
410 their parents so they appear "on top of" their parents.
412 Each box has two major visual components, each with subcomponents:
416 <definition term="path">
418 A box's [[path]] consists of zero or more lines and curves.
419 The path may be filled with a color, gradient, or texture, and
420 may be stroked with a line of a given thickness and color. If
421 the path is not specified, it defaults to the perimiter of the
422 box. [**Note: Vector Graphics support (including the ability
423 to set the [[path]] property to anything other than the
424 default) is currently not implemented**].
429 an associated [[strokecolor]], which is a color
431 an associated [[strokewidth]], which is a number
432 specifying the width of the stroke. [**Note: Vector
433 Graphics support (including the [[strokewidth]]
434 property) is currently not implemented**]
436 a [[fill]], which is either a color, gradient, or
441 <definition term="text">
443 Each box also has a single line of [[text]], whose
444 appearance is determined by its:
447 associated [[font]], which can be any font supported by
448 the <link url="http://www.freetype.org" text="FreeType2"/>
451 an associated [[fontsize]] in **pixels**
453 an associated [[textcolor]]
457 These eight components plus the size of a box fully specify its
458 appearance. Every single box you see in Ibex is drawn only on the
459 basis of these components and its size.
461 The size and position of every box is determined by its
462 properties, its childrens' sizes, and its parent's size and
463 position. Box layout and rendering happens in four phases:
464 **packing**, **constraining**, **placing**, and
465 **rendering**. The Core is careful to only perform a phase on
466 a box if the box has changed in a way that invalidates the work
467 done the last time that phase was performed. The packing and
468 constraining phases are performed in a single traversal of the
469 tree (packing is preorder, constraining is postorder), and the
470 placing and rendering phases are performed in a second traversal
471 of the tree (first placing, then rendering, both preorder).
473 For brevity, the rest of this chapter deals only with width and
474 columns. Height and rows is treated identically and independently.
475 Also, it is important to note that the term **minimum width** is
476 not the same thing as the property [[minwidth]], although they
479 <heading title="The Size of the Root Box"/>
481 When the user resizes a window, Ibex changes the root box's
482 [[maxwidth]] and [[maxheight]] to match the size chosen by
483 the user and then determines the root box's size using the same sizing
484 rules it uses for other boxes.
486 Ibex will always attempt to prevent the
487 user from making the surface smaller than the root box's
488 [[minwidth]] and [[minheight]]. If the [[hshrink]] or
489 [[vshrink]] flag is set, Ibex will try to prevent the user from
490 resizing the surface at all. However, not all platforms give Ibex
491 enough control to do this.
493 <heading title="The alignment point"/>
495 When talking about positioning, we will often refer to the
498 If the [[align]] property is "[[center]]", then the
499 alignment point is the center of the box.
501 If the [[align]] property is "[[topleft]]",
502 "[[bottomleft]]", "[[topright]]", or
503 "[[bottomright]]", then the alignment point is
504 corresponding corner of the box.
506 If the [[align]] property is "[[top]]",
507 "[[bottom]]", "[[right]]", or "[[left]]", then
508 the alignment point is middle of the corresponding edge of the
511 <section title="Packing">
513 A grid of **cells** is created within the parent. If the
514 parent's [[cols]] property is set to 0, the cell grid has an
515 infinite number of columns. Either [[cols]] or [[rows]]
516 must be zero, but not both.
518 If a child's [[visible]] property is [[false]], it does
519 not occupy any cells (and is not rendered). Otherwise, each child
520 occupies a rectangular set of cells [[child.colspan]] cells
521 wide and [[child.rowspan]] cells high.
523 The Core iterates over the cells in the grid in the following
524 order: if [[rows]] is 0, the Core iterates across each column
525 before proceeding to the next row; otherwise rows come before
526 columns. At each cell, the Core attempts to place the **first
527 remaining unplaced child's** top-left corner in that cell
528 (with the child occupying some set of cells extending down and
529 to the right of that cell). If the parent has a fixed number of
530 columns and the child's [[colspan]] exceeds that limit, the
531 child is placed in column zero regardless, but only occupies the
532 available set of cells (it does not "hang off the end" of the
533 box). <image url="layout.pdf" width="1in"/>
538 <ui:box id="2" rowspan="2" />
539 <ui:box id="3" colspan="2" />
541 <ui:box id="5" colspan="2" />
547 <section title="Constraining">
549 Each box's minimum width is computed recursively as the
555 The width of the box's [[text]] (after applying the
556 box's [[transform]]) [**Note: Vector Graphics support
557 (including the [[transform]] property) is currently not
560 The width of the box's path (after applying the box's
561 [[transform]]) **if the box is [[packed]]**.
563 The minimum width of the children in each row.
566 If a box's [[hshrink]] property is set to
567 [[true]], the box's maximum width is the same as its
568 minimum width; otherwise it is the box's
573 <section title="Placing">
575 <heading title="Non-Packed Boxes"/>
577 Each non-packed box is transformed according to the parent's
578 [[transform]] property and then positioned so that its alignment
579 point is [[(child.x, child.y)]] pixels from the corresponding
580 edge/corner/center of its parent.
582 <heading title="Packed Boxes"/>
584 Ibex formulates a set of constraints for placing a box's
585 **packed** children as follows:
588 - A box's width can be no greater than the sum of the
590 - The sum of a set of colums cannot be smaller than the
591 minimum width of a box that spans them.
592 - The sum of the widths of the parents' columns will be at
593 least as large as the parent's width is (but possibly
597 Subject to these two unbreakable constraints, Ibex searches for
598 a solution which will optimize the following three goals,
599 prioritized from most important to least important:
602 - (__Most Important__) The sum of all columns will be a close
603 to the parent's with as possible (ie as small as possible)
604 - Ibex will attempt to make a set of columns no wider than
605 the [[maxwidth]] of a box spanning them.
606 - (__Least Important__) Ibex will attempt to make all
607 columns the same width.
610 Each packed box is then placed within the set of cells that it
611 spans. Usually the box will exactly fill this rectangle; if it
612 does not (due to [[maxwidth]] or minimum width constraints), the
613 box's will be placed so that its alignment point coincides with
614 the alignment point of that rectangle of cells.
618 <section title="Rendering">
620 Boxes are rendered in a depth-first, pre-order traversal. Note that
621 this may cause a non-packed box to overlap its siblings.
623 <list type="ordered">
625 If the box's [[transform]] property is non-null, the
626 coordinate space is transformed accordingly for the rest of
627 this phase and for the rendering of all children. [**Note:
628 Vector Graphics support (including the [[transform]]
629 property) is currently not implemented**].
631 If the box is packed and has a non-[[null]] path, the
632 path is translated such that the alignment point of the path's
633 bounding box coincides with the box's alignment point (both
634 alignment points are determined by the box's [[align]]
637 If a box has a path, that path is filled with the color,
638 gradient, or image specified by the [[fill]] property and
639 stroked with the color and width specified by the
640 [[strokecolor]] and [[strokewidth]] properties.
642 If the box has a non-null [[text]] attribute,
643 the text is rendered in [[font]] with size
644 [[fontsize]] and color [[textcolor]]. The text is
645 then translated such that the alignment point of the text's
646 bounding box coincides with the box's alignment point (both
647 alignment points are determined by the box's [[align]]
650 The box's children are rendered (pre-order traversal).
657 <!-- ----------------------------------------------------------------------- -->
658 <section title="Box Properties">
660 Each box is a full-fledged ECMAscript object, and can store
661 key-value pairs as properties. Some of these keys have special
662 meaning, which will be explained later. Each box's numeric
663 properties hold its **child boxes**.
665 <section title="Rendering Properties">
667 Every box has several special properties which control how it is
668 drawn. In general, if you put an
669 invalid value to a special property, no action will be taken -- the
672 <property name="strokecolor" type="string" default="clear">
674 If the value is a 5-character hex string ([[#RGB]]),
675 7-character hex string ([[#RRGGBB]]), 9-character hex
676 string ([[#AARRGGBB]]), the box's stroke color will be set
679 If the value is one of the <link
680 url="http://www.color.org/ICC-1A_1999-04.PDF"
681 text="ICC"/> colors (the same set of color names
682 supported by SVG), the stroke color be set to that color.
684 If the value is [[null]], the stroke color will be set
685 to clear ([[#00000000]]).
688 <property name="strokewidth" type="int" default="1">
689 The width (in pixels) to stroke the path with.
692 <property name="fill">
693 This property can be set to any of the values specified for
695 Alternatively, if the value written is an object, its stream
696 will be read and interpreted as a PNG, GIF, or JPEG image,
697 which will become the texture for this box, and the box's
698 [[minwidth]] and [[minheight]] properties will be
699 automatically set to the dimensions of the image.
702 <property name="path" type="string" default='""'>
703 The box's path. The grammar and feature set supported are
704 identical to that specified in <link
705 url="http://www.w3.org/TR/SVG11/paths.html" text="SVG 1.1,
709 <property name="text" type="string" default='""'>
710 The box's text; writing [[null]] to this property sets it
714 <property name="textcolor" type="number" default="black">
715 The color in which to render the font; accepts the same values as [[strokecolor]].
718 <property name="font" type="stream" default=".ibex.ui.font.sansserif">
719 When an object is written to this property, its stream is read
720 using the <link url="http://www.freetype.org" text="FreeType 2 library"/>,
721 and the resulting font is used to render the
725 <property name="fontsize" type="number" default="10">
726 The size (in points) to render the text.
731 <section title="Layout Properties">
733 <property name="shrink" type="boolean" default="false">
734 If set to [[true]], this box will shrink
735 (horizontally/vertically/both) to the smallest size allowed by
736 its children and the bounding box of its path.
739 <property name="x y" type="integer" default="varies">
740 If the box is a root box, this is the (x/y)-coordinate of the
741 surface; otherwise it is the distance between the parent's
742 alignment point and the corresponding corner/edge/center of
746 <property name="minwidth minheight" type="integer" default="0">
747 The desired minimum width and height.
750 <property name="maxwidth maxheight" type="integer" default="ibex.ui.maxdim">
751 The desired maximum width and height.
754 <property name="width height" type="integer">
755 When read, this is the current (width/height) of this box.
756 Writing to this property is equivalent to writing to
757 **both** the minimum and maximum (width/height).
760 <property name="cols rows" type="integer" default="0">
761 The number of (columns/rows) in which to lay out the children of this
762 box. If set to zero, the number of (columns/rows) is unconstrained.
763 Either [[rows]] or [[cols]] must be zero. If
764 [[0]] is written to [[cols]] when [[rows]] is
765 [[0]], the write is ignored. If a nonzero value is
766 written to [[cols]] when [[rows]] is nonzero,
767 [[rows]] is set to [[0]], and vice versa.
770 <property name="colspan rowspan" type="integer" default="1">
771 The number of (columns/rows) that this box spans within its parent.
774 <property name="align" type="string" default="center">
775 Determines the box's alignment point for positioning its text,
776 texture, path, and children.
779 <property name="visible" type="boolean" default="true">
780 If set to [[false]], this box will be rendered as if its
781 width and height were zero. If this is a root box, the
782 associated surface will be hidden.
784 When reading from this property, the value [[false]] will
785 be returned if this box **or any of its ancestors** is not
786 visible. Thus it is possible to write [[true]] to a box's
787 [[visible]] property and then read back [[false]].
790 <property name="packed" type="boolean" default="true">
791 The layout strategy for this box. If set to [[true]], the
792 box occupies no cells and is laid out independently of its
798 <section title="Child Control Properties">
800 <property name="redirect" type="box" default="thisbox">
801 Writing to this property sets the box's redirect target. This
802 property cannot be read from, and can only be written to if
803 the value being written is a **descendant** of the current
806 If a box has a non-null redirect target, reads and writes to
807 any of the other properties in this section will be forwarded
808 to the redirect target.
810 The [[redirect]] attribute is very useful for hiding the
811 internal structure of a widget, and for allowing widgets to act as
812 "smart" containers for other widgets. For example, a menu widget might
813 have an invisible child as its redirect target; this way, when boxes
814 representing items on the menu are added as children of the menu
815 widget, they do not appear until the menu is pulled down.
818 <property name="numeric properties" type="int" default="">
819 The **n**th child of box [[b]] can be accessed by reading from
820 [[b[n]]]. The **n**th child can be removed by writing
821 [[null]] to [[b[n]]] (the child will become parentless). A
822 new child can be inserted **before** the **n**th child by
823 writing it to [[b[n]]]; if the value written is already a child of
824 [[b]], it will be removed from [[b]] first. It is important
825 to note that this behavior is different from ECMAscript arrays --
826 writing a non-[[null]] value to [[b[n]]] does not eliminate
827 the **n**th child; it merely shifts it over one position.
828 __Note:__ Unlike most JavaScript objects, enumerating a Box's
829 properties with the JavaScript [[for..in]] construct will
830 enumerate **only** the box's children and not any other properties.
833 <property name="clip" type="boolean" default="true">
834 If [[true]], the visual representation of this box's
835 children will be clipped to the boundaries of this box.
836 __Note:__ setting this property to [[false]] imposes a
837 substantial performance penalty.
840 <property name="numchildren" type="integer" default="0">
841 The number of children this box has.
845 <property name="surface" type="" default="null">
847 If this box has a parent, this property returns
848 [[**parent**.surface]]; otherwise it returns null.
849 This property is a simple building block that the widget
850 library uses to implement more complex functionality such as
851 focus control and popups.
856 <section title="Other Box Properties">
858 <property name="cursor" type="string" default="null">
859 The shape that the cursor should take when inside this
860 box. Valid values are: "[[default]]" , "[[wait]]",
861 "[[crosshair]]", "[[text]]", "[[hand]]", and
862 "[[move]]", as well as resizing cursors"[[east]]",
863 "[[west]]", "[[north]]", "[[south]]",
864 "[[northwest]]", "[[northeast]]",
865 "[[southwest]]", and "[[southeast]]". Note that on
866 some platforms, resize cursors for opposite directions (such
867 as [[northwest]] and [[southeast]] are the
869 If a box's cursor is [[null]], its parent's cursor will
870 be used. If the root box's cursor is null, the
871 "[[default]]" cursor will be used.
874 <property name="static" type="object" default="N/A">
875 Reading from this property will return the parent scope used
876 to execute the [[<static/>]] block of the template
877 in which the currently-executing code resides.
880 <property name="thisbox" type="box" default=" ">
881 Returns a reference to the box itself.
882 If [[null]] is written to this property, and this box is
883 the root box of a surface, the box will be detached and the
884 surface destroyed. If this box has a parent, it will be
885 detached from its parent.
888 <property name="indexof()" type="function" default=" ">
889 This property is actually a function; invoking
890 [[parent.indexof(child)]] will return the numerical index
891 of [[child]] in [[parent]] if [[child]] is a
892 child of [[parent]] (or [[parent]]'s redirect
893 target), and [[-1]] otherwise. Writing to this property
897 <property name="distanceto()" type="function" default=" ">
898 This property is actually a function; invoking
899 [[box.distanceto(otherbox)]] will return an object with two
900 properties, [[x]] and [[y]], containing the horizontal
901 and vertical distance between the two boxes (negative if
902 [[otherbox]] is to the left of / above [[box]]). This
903 can be used to determine the relative placement of two boxes
904 on different branches of the box tree.
909 <section title="Root Box Properties">
911 The following special properties are only meaningful on the root box
914 <property name="Focused">
915 The value [[true]] is put to this property on the root box
916 when the surface gains the input focus, and [[false]] when
917 the surface loses the input focus. Reading from this value will
918 return [[true]] if the surface is focused and [[false]]
919 if it is not. Putting [[true]] to this property will
920 **not** cause the surface to "steal" the input focus from other
924 <property name="Maximized">
925 The value [[true]] is put to this property on the root box
926 when the surface is maximized, and [[false]] when the surface
927 is un-maximized. Reading from this value will return [[true]]
928 if the surface is maximized and [[false]] if it is
929 not. Putting [[true]] to this property will maximize the
930 window, and putting [[false]] to this property will
931 unmaximize the window.
932 Note that not all platforms support maximization.
935 <property name="Minimized">
936 The value [[true]] is put to this property on the root box
937 when the surface is minimized, and [[false]] when the surface
938 is unminimized. Reading from this value will return [[true]]
939 if the surface is minimized and [[false]] if it is
940 not. Putting [[true]] to this property will minimize the
941 window, and putting [[false]] will unminimize it.
944 <property name="Close">
945 When the user attempts to close a surface, the value
946 [[true]] will be put to this property. Scripts may trap
947 this property to prevent the window from closing. Putting the
949 [[true]] to this property on a root box has the same
950 effect as putting [[null]] to the [[thisbox]]
954 <property name="icon">
955 The surface's icon. This is usually displayed on the titlebar of a
956 window. The value should be an object whose stream is a PNG image. Note
957 that not all platforms support this property.
960 <property name="titlebar">
961 The surface's titlebar text. Note that not all platforms support
962 this property. Only ASCII characters 0x20-0x7F are permitted.
969 <!-- ----------------------------------------------------------------------- -->
970 <section title="Streams">
972 <heading title="Every object has a stream..."/>
974 Every object has a **stream** associated with it. A stream is a
975 sequence of bytes that can be read or written to.
977 By default an object has an empty stream (zero bytes). However, some objects
978 (returned from special methods on the [[ibex]] object) have
979 streams yielding data read from an url, file, or a component of a zip
980 archive. In a future release, the stream associated with a box will
981 be an .ibex template which, when applied, will fully reconstitute the
984 <heading title="...but streams are not objects"/>
986 Despite the ubiquity of streams, you cannot actually reference a
987 stream, since it is not an object. Instead, you simply reference the
988 object it belongs to. If you are familiar with Java, this is similar
989 to how every Java object has a monitor associated with it, but you
990 cannot directly manipulate the monitor (you can't pass around a
991 reference to just the monitor).
993 In the rest of the section we will sometimes refer to "getting
994 properties from a stream" or "passing a stream to a function"; this is
995 just shorthand for saying to perform those actions on the object the
998 <section title="Creating Streams from URLs">
1000 You can create a stream from a URL by calling
1003 var r = ibex.stream.url("http://...");
1006 This will return an object whose stream draws data from the specified
1007 URL. Streams are loaded lazily whenever possible.
1011 <section title="Getting Substreams">
1013 Most stream objects let you access
1014 substreams using the usual JavaScript operators [[[]]] and
1015 [[.]], as well as the [[for..in]] syntax.
1018 // r1 and r2 are equivalent but not equal (!=)
1019 var r1 = ibex.stream.url("http://www.ibex.org/foo/bar.html");
1020 var r2 = ibex.stream.url("http://www.ibex.org/foo")["bar.html"];
1025 <section title="The Root Stream">
1027 The empty-string property on the [[ibex]] object is called the
1028 **root stream**. You can access this object as [[ibex..]] or
1029 [[ibex[""]]]. Additionally, any expression which starts with a
1030 dot is treated as property to be retrieved from the root stream. The
1031 following three expressions are equivalent:
1041 <section title="Static Blocks">
1045 You can access variables within the static block of a template by
1046 appending a double period ([[..]]) and the variable name to the
1047 stream used to load that template:
1050 <!-- org/ibex/themes/linux/scrollbar.ibex -->
1054 ibex.log.print(org.ibex.themes.linux.scrollbar..foo); // prints "12"
1059 <section title="Formatting Streams">
1061 If you attempt to send a stream as part of an XML-RPC call, the
1062 stream will be read in its entirity, Base64-encoded, and transmitted
1063 as a [[<base64/>]] element.
1065 Ibex supports two special URL protocols. The first is [[data:]],
1066 which inteprets the rest of the URL as a Base64 encoded sequence of
1067 bytes to use as a source. The other is [[utf8:]] which
1068 interpretets the rest of the string as a Unicode character sequence to
1069 be UTF-8 encoded as a string of bytes to use as a source.
1072 var r5 = ibex.stream.url("data:WFWE876WEh99sd76f");
1073 var r6 = ibex.stream.url("utf8:this is a test");
1076 You can read a UTF-8 encoded string from a stream like this:
1079 var myString = ibex.stream.fromUTF(ibex.stream.url("utf8:testing..."));
1081 You can also parse XML from a stream using SAX like this:
1084 ibex.stream.xml.sax(
1085 ibex.stream.url("http://foo.com/foo.xml"),
1086 { beginElement : function(tagname, attributeKeyValuePairs) { ... },
1087 endElement : function(tagname) { ... },
1088 content : function(contentString) { ... }
1089 whitespace : function(whitespaceString) { ... }
1097 <!-- ----------------------------------------------------------------------- -->
1098 <section title="The Ibex object">
1100 The [[ibex]] object is present in the top-level scope of every
1101 script. It has the following properties:
1103 <heading title="General"/>
1105 <property name="ibex.box">
1106 reading from this property returns a new box
1108 <property name="ibex.clone(o)">
1109 creates a clone of object
1111 <property name="ibex.bless(s)">
1112 returns a blessed clone of stream
1115 <heading title="ECMA Library Objects"/>
1117 <property name="ibex.date">
1118 reading from this property returns a new date
1120 <property name="ibex.math">
1121 this object contains the ECMA math functions
1123 <property name="ibex.regexp(s)">
1124 return a regexp object corresponding to string **s**
1126 <property name="ibex.string">
1127 this object contains the ECMA string manipulation functions
1130 <heading title="Logging"/>
1132 <property name="ibex.log.debug(m1, ... mn)">
1133 log the debug messages **m1** through **mn**.
1137 <property name="ibex.log.info(m1, ... mn)">
1138 log the info messages **m1** through **mn**.
1141 <property name="ibex.log.warn(m1, ... mn)">
1142 log the warning messages **m1** through **mn**.
1145 <property name="ibex.log.error(m1, ... mn)">
1146 log the error messages **m1** through **mn**.
1149 <heading title="User Interface"/>
1151 <property name="ibex.ui.browser(u)">
1152 opens a new browser window with URL **u**
1155 <property name="ibex.ui.key.control">
1156 true if the control key is depressed
1159 <property name="ibex.ui.key.shift">
1160 true if the shift key is depressed
1163 <property name="ibex.ui.key.alt">
1164 true if the alt key is depressed
1167 <property name="ibex.ui.key.name.alt">
1168 the name of the "alt" key (usually either "alt", "meta", or
1172 <property name="ibex.ui.clipboard">
1173 the contents of the clipboard; can be read and written to
1176 <property name="ibex.ui.maxdim">
1177 the maximum dimension of any UI element; usually
1178 2<sup>31</sup>, but may be smaller
1181 <property name="ibex.ui.screen.width">
1182 the width of the screen, in pixels
1185 <property name="ibex.ui.screen.height">
1186 the height of the screen, in pixels
1189 <property name="ibex.ui.mouse.button">
1190 either 0, 1, 2, or 3, indicating the mouse button currently
1194 <property name="ibex.ui.frame">
1195 when a box is written to this property, it becomes the root
1199 <property name="ibex.ui.window">
1200 when a box is written to this property, it becomes the root
1204 <property name="ibex.ui.font.serif">
1205 an object whose stream is a a builtin serif font
1208 <property name="ibex.ui.font.sansserif">
1209 an object whose stream is a builtin sans-serif font
1212 <property name="ibex.ui.font.monospace">
1213 an object whose stream is a a builtin fixed-width font
1216 <heading title="Networking"/>
1218 <property name="ibex.net.rpc.xml(u)">
1219 return an XML-RPC call object with endpoint URL **u**
1222 <property name="ibex.net.rpc.soap(u,">
1223 return a SOAP call object with endpoint URL **u**,
1224 SoapAction **a**, and XML Namespace **n**
1227 <heading title="Threads"/>
1229 <property name="ibex.thread">
1230 when a function is written to this property, a new thread is
1234 <property name="ibex.thread.yield()">
1235 yield the current thread
1238 <property name="ibex.thread.sleep(n)">
1239 sleep for **n** milliseconds
1242 <heading title="Streams"/>
1244 <property name="ibex.stream.url(u)">
1245 returns a new object whose stream is drawn from URL **u**
1248 <property name="ibex.stream.unzip(s)">
1249 unpacks a zip archive from **s**'s stream
1252 <property name="ibex.stream.uncab(s)">
1253 unpacks a cab archive from **s**'s stream
1256 <property name="ibex.stream.cache(s,k)">
1257 valign=top>wraps a disk-backed read cache keyed on **k**
1258 around **s**'s stream
1261 <property name="ibex.stream.watch(s,f)">
1262 returns an object whose stream is drawn from **s**'s
1263 stream, but invokes **f(n,d)** as it is read from.
1266 <property name="ibex.stream.parse.xml(s, h)">
1267 Use SAX to parse the XML document on stream **s** with
1271 <property name="ibex.stream.parse.html(s, h)">
1272 Same as [[parse.xml()]], but tries to fix broken HTML.
1275 <property name="ibex.stream.parse.utf8(s)">
1276 treat **s**'s stream as a string encoded as a UTF-8 byte stream and return the string
1279 <property name="ibex.stream.homedir">
1280 [[ibex.stream.tempdir]]
1283 <heading title="Cryptography"/>
1285 <property name="ibex.crypto.rsa(k,s)">
1286 **not implemented yet:** return a
1287 stream which rsa-decrypts stream **s** with key **k**
1290 <property name="ibex.crypto.rc4(k,s)">
1291 **not implemented yet:** return a
1292 stream which rc4-decrypts stream **s** with key **k**
1295 <property name="ibex.crypto.md5(s)">
1296 **not implemented yet:** immediately
1297 MD5-hash stream **s**
1300 <property name="ibex.crypto.sha1(s)">
1301 **not implemented yet:** immediately
1302 SHA1-hash stream **s**
1306 <!-- ----------------------------------------------------------------------- -->
1307 <section title="Traps">
1309 You can add a trap to a property by applying the [[++=]] operator
1310 to a function with one argument. The trap will be invoked whenever
1311 that property is written to.
1315 foo ++= function(z) {
1316 ibex.log.info("foo is " + z);
1321 If another script were to set the property "[[foo]]"
1322 on the box above to the value [[5]], the function above would be
1323 invoked with the argument [[5]]. The function would then log
1324 the string "[[foo is 5]]".
1326 Within a trap, the expression [[trapee]] can be used to
1327 get a reference to the box on which the trap was placed.
1329 The expression [[trapname]] returns the name of the
1330 trap executing the current function. This is useful when a function
1331 is applied to multiple traps. For example:
1335 func ++= function(z) {
1336 ibex.log.info("called trap " + trapname);
1343 <section title="Removing Traps">
1345 You can remove a trap by using the [[--=]] operator with the same
1346 function you added as a trap:
1350 var myfunc = function(z) { /* ... */ }
1361 <heading title="Multiple Traps on the Same Property"/>
1363 When the trapped property is **written** to, each of the trap
1364 functions placed on it will be invoked in the opposite order that
1365 they were placed on the box -- the most recently placed trap will
1366 execute first. This last-to-first execution of traps is called
1367 **cascading**. After the last trap is invoked, the value is
1368 stored on the box (remember, boxes are objects, so they can hold
1369 properties just like all other ECMAscript objects).
1371 <section title="Manual Cascades">
1373 There are two additional tricks you can use when placing traps. The
1374 first is a **manual cascade**. If you want to cascade to lower
1375 traps in the middle of a function, or you want to cascade with a
1376 different value than the value passed to you (in effect "lying" to
1377 lower traps), you can use [[cascade]]. For example:
1380 <ui:box color="black">
1381 color ++= function(c) {
1382 ibex.log.info("refusing to change colors!");
1388 This effectively creates a box whose color cannot be changed, and
1389 which complains loudly if you try to do so.
1391 Do **not** try to do something like this:
1394 <ui:box color="black">
1395 color ++= function(z) {
1396 color = "black"; // INFINITE LOOP! BAD!!!
1400 To prevent automatic cascading, return [[true]] from your function:
1403 <ui:box color="black">
1404 color ++= function(z) {
1405 return true; // the box's color will not change
1412 <section title="Read Traps">
1414 The other trick is a **read-trap**. Read traps are just like normal
1415 traps, except that you use a function that takes zero arguments instead of one. Read traps
1416 also do not automatically cascade.
1420 doublewidth [[++=]] function() { return 2 * width; }
1424 If another script attempts to read from the [[doublewidth]]
1425 property on this box, the value it gets will be twice the actual width
1426 of the box. Note that
1427 the actual [[doublewidth]] property on the box never gets written
1428 to, since the trap does not cascade.
1430 You can manually cascade on read traps as well:
1434 text [[++=]] function() { return "my text is " + cascade; }
1438 Read traps are only rarely needed -- most of the time a write trap
1443 <heading title="Prohibited Traps"/>
1445 To prevent confusing and hard-to-debug behaviors, scripts may not
1446 place traps on any of the properties described in the sections
1447 <link text="Box Layout Properties" section="Layout Properties"/>, <link
1448 section="Child-Control Properties"/>, or <link section="Other Box
1449 Properties"/> except for [[childadded]],
1450 [[childremoved]] and [[surface]]. FIXME: remove?
1452 <heading title="Exceptions and Traps"/>
1454 If an uncaught exception is thrown from a trap, Ibex will log the
1455 exception, but will **not** propagate it to the code which
1456 triggered the trap. If the trap was a read trap, the value
1457 [[null]] will be returned.
1458 FIXME: is this right?
1460 <heading title="Architectural Significance of Traps"/>
1462 Traps are the backbone of Ibex. Since almost all UI programming is
1463 event/demand driven, traps eliminate the need for separate
1464 member/getter/setter declarations, often cutting the amount of typing
1465 you have to do to a third of what it would normally be.
1467 <section title="Cloning">
1469 **Cloning** is a companion technique for traps; together they can
1470 be used to simulate any sort of environment you might need. When you
1471 call [[ibex.clone(o)]], Ibex returns a new object (called the
1472 **clone**) which compares with equality ([[==]]) to the
1473 original object. Furthermore, both objects are "equal" as keys in
1478 var theclone = ibex.clone(o);
1480 ibex.log.info(hash[theclone]); // prints "5"
1483 Any writes to properties on the clone will actually write to
1484 properties on the original object, and reads from properties on the
1485 clone will read properties on the original object. In fact, the only
1486 thing that can be used to distinguish the original from the clone is
1487 traps -- a trap placed on the clone is **not** placed on the
1488 original object as well.
1493 <!-- ----------------------------------------------------------------------- -->
1494 <section title="Threads">
1496 <section title="Contexts">
1498 From the perspective of an application writer, Ibex is strictly
1499 single-threaded. Ibex is always in exactly one of the following three
1502 <list type="unordered">
1504 __Rendering Context__ -- (redrawing the screen)
1506 __Event Context__ (executing javascript traps triggered by an event)
1508 __Thread Context__ (executing a background thread spawned with [[ibex.thread]])
1512 There are two important restrictions on what can be done in particular contexts:
1514 <list type="unordered">
1516 The [[box.mouse]] property and its subproperties
1517 ([[x]], [[y]], and [[inside]]) can only be read
1518 from within the Event Context, or in a thread context
1519 **after** a the [[box.mouse]] property on this box or
1520 an ancestor box has been written to.
1522 Blocking operations (anything that accesses the network or
1523 disk) can only be performed in the Thread Context.
1529 <section title="Background Threads">
1531 Ibex offers easy access to threads. Spawning a background thread is as
1532 simple as writing a function to the [[ibex.thread]] property:
1535 ibex.thread = function() {
1536 ibex.log.info("this is happening in a background thread!");
1540 The argument set passed to the function is currently undefined and is
1541 reserved for use in future versions of Ibex. Scripts should not
1542 depend on the number or content of these arguments.
1544 Ibex is **cooperatively multitasked**, so threads must not process
1545 for too long. This was a deliberate choice; cooperatively
1546 multitasked environments do not require complex locking primitives
1547 like mutexes and semaphores which are difficult for novices to
1548 understand. The disadvantage of cooperative multitasking is that one
1549 thread can hog the CPU. This is unlikely to happen in Ibex for two reasons:
1550 first, all blocking I/O operations **automatically** yield the CPU,
1551 so the overall user interface never becomes unresponsive because it is
1552 waiting for a disk or network transfer. Second, since Ibex is strictly
1553 a user interface platform, Ibex scripts are unlikely to perform highly
1554 compute-intensive operations that keep the CPU busy for more than a
1560 <section title="Events">
1562 Every execution of the Event Context begins with an event, which
1563 consists of a key/value pair, and a mouse position, which consists of
1564 an x and y coordinate. The possible keys are [[_Press[1-3]]],
1565 [[_Release[1-3]]], [[_Click[1-3]]], [[_DoubleClick[1-3]]],
1566 [[_Move]], [[_KeyPressed]], and [[_KeyReleased]].
1568 Here are two example events:
1570 An event is triggered by writing the key to the value on a box. This
1571 triggers any trap handlers which may be present. Once these handlers
1572 have executed, Ibex figures out which child of the current box contains
1573 the mouse (taking into account that some boxes may cover up others)
1574 and writes the key and value to that box. If none of the box's
1575 children contain the mouse position, Ibex removes the leading
1576 underscore from the key name and writes the value to
1577 **that** property. Once all the traps on that property have
1578 executed, the value is written to the box's parent.
1580 Intuitively, Ibex delivers the underscored event to every box from the
1581 root to the target, and then delivers the non-underscored event to
1582 that same set of boxes in reverse order. So the event travels down
1583 the tree to the target, and then back up to the root. The following
1584 example prints out "first second third fourth" in that order.
1588 _Press1 ++= function(b) { ibex.log.info("first"); }
1589 Press1 ++= function(b) { ibex.log.info("fourth"); }
1591 _Press1 ++= function(b) { ibex.log.info("second"); }
1592 Press1 ++= function(b) { ibex.log.info("third"); }
1597 In general, you should use the **non-underscore** names to respond
1598 to user input and use the underscored names when you want to override
1599 child boxes' behavior or route events to particular boxes (for
1600 example, when implementing a focus protocol). This is why the
1601 underscored elements are delivered to parents before children (so
1602 parents can override their childrens' behavior), but non-underscored
1603 events are delivered to children before parents (since, visually, a
1604 mouse click is usually "intended" for the leaf box underneath the
1609 <heading title="Stopping the Process"/>
1611 At any point in this sequence, a trap handler can choose not to
1612 cascade (by returning [[true]] from the trap handler function).
1613 This will immediately cease the propagation of the event. This is how
1614 you would indicate that an event has been "handled".
1616 <heading title="Non-Propagating Events"/>
1618 Ibex uses the following events to notify a box about changes that
1619 only matter to that particular box. These events do not propagate
1620 either up or down the tree.
1622 <property name="Enter Leave">
1623 The value [[true]] is written to this property when the mouse (enters/leaves) the box.
1626 <property name="SizeChange">
1627 The value [[true]] is put to this property after the size
1628 of this box changes.
1631 <property name="ChildChange">
1632 When a child is added or removed, that child is written to
1633 this property. The write is always performed **after** the
1634 addition or removal, so these two cases can be distinguished
1635 by checking [[indexof(child)]].
1637 Note that if the parent's redirect target is set to another
1638 box, this trap will only be invoked when children are
1639 manipulated by reading and writing to the parent. Reads and
1640 writes directly to the redirect target will **not** trigger
1643 Note also that this traps is still triggered if a box's
1644 [[redirect]] target is **null**. This is useful for
1645 boxes that need to accept children and then relocate them
1649 <section title="Listing of Events">
1651 <property name="Press1 Press2 Press3">
1652 Indicates that the use has pressed a mouse button. On
1653 platforms with three mouse buttons, the **middle** button
1654 is button 3 -- this ensures that applications written to only
1655 use two buttons (1 and 2) will work intuitively on three button
1659 <property name="Release1 Release2 Release3">
1660 Indicates that the use has released a mouse button.
1663 <property name="Click1 Click2 Click3">
1664 Indicates that the user has pressed and released the
1665 mouse button without moving the mouse much (exactly how
1666 much is platform-dependent).
1669 <property name="DoubleClick1 DoubleClick2 DoubleClick3">
1670 Indicates that the user has clicked the
1671 mouse button twice within a short period of time (exactly how long is platform-dependent).
1674 <property name="Move">
1675 Indicates that the mouse has moved while within this box, or that
1676 the mouse while outside this box **if a button was pressed while within this box and has not yet been released**
1679 <property name="KeyPressed KeyReleased">
1681 A string is written to this property when a key is pressed or
1682 released If the key was any other key, a multi-character
1683 string describing the key will be put. For simplicity, we use
1684 the VK_ constants in the <link
1685 url="http://java.sun.com/products/jdk/1.1/docs/api/java.awt.event.KeyEvent.html#VK_0"
1686 text=" Java 1.1 API java.awt.event.KeyEvent class"/>. When a
1687 key is pressed or released, the string put will be the portion
1688 of its VK_ constant after the underscore, all in lower case.
1691 If the shift key was depressed immediately before the
1692 event took place, then the string will be capitalized. Special
1693 keynames are also capitalized; shift+home is reported as
1694 "[[HOME]]". Symbols are capitalized as they appear on the
1695 keyboard; for example, on an American QWERTY keyboard, shift+2
1696 is reported as "[[@]]".
1698 If the alt, meta, or command key was depressed immediately
1699 before this key was pressed, then the string will be prefixed
1700 with the string "[[A-]]". If the control key was depressed
1701 while this key was pressed, then the string will be prefixed
1702 with the string "[[C-]]". If both alt and control are
1703 depressed, the string is prefixed with "[[C-A-]]".
1705 Ibex does not distinguish between a key press resulting from
1706 the user physically pushing down a key, and a 'key press'
1707 resulting from the keyboard's typematic repeat. In the rare
1708 case that an application needs to distinguish between these
1709 two events, it should watch for KeyReleased messages and
1710 maintain an internal key-state vector.
1718 <!-- ----------------------------------------------------------------------- -->
1719 <section title="Networking">
1721 <section title="XML-RPC">
1723 XML-RPC objects can be created by calling [[ibex.net.rpc.xml(**XML-RPC
1724 URL**)]], and then invoking methods on that object. For example,
1727 Press1 += function(v) {
1728 ibex.thread = function() {
1729 color = ibex.net.rpc.xml("http://xmlrpc.ibex.org/RPC2/").
1730 color.getTodaysColor("Friday");
1735 When the user clicks the first mouse button on this box, it will
1736 contact the server [[xmlrpc.ibex.org]], route to the
1737 [[/RPC2/]] handler and invoke the [[getTodaysColor()]]
1738 method on the [[color]] object with a single string argument
1739 "[[Friday]]". The return value will be used to change the color
1740 of the box the user clicked on.
1742 Note that in this example we spawned a background thread to handle the
1743 request -- the [[Press1]] event is delivered in the foreground
1744 thread, and XML-RPC methods may only be invoked in background
1745 threads. This is to prevent the UI from "locking up" if the server
1746 takes a long time to reply.
1748 If the XML-RPC method faults, an object will be thrown with two
1749 properties: [[faultCode]] and [[faultString]], as defined in
1750 the <link url="http://www.xmlrpc.org/spec" text="XML-RPC specification"/>. If
1751 Ibex encounters a network, transport, or session-layer error, it will
1752 throw a [[String]] object describing the error in a
1753 human-readable format. Scripts should not rely on the contents of
1754 this string having any special structure or significance.
1756 If an object with an associated non-empty stream is passed as an
1757 argument to an XML-RPC method, it will be sent as a <base64/>
1758 element. If a <base64/> element is found in the XML-RPC reply, it
1759 will be returned as an object with a stream drawn from that byte sequence.
1761 Each object returned by [[ibex.net.rpc.xml()]] represents a
1762 single HTTP connection. The connection will be held open until
1763 the object is garbage collected or the server closes the
1764 connection. If a second call is issued on the object before the
1765 first one returns (usually from a seperate thread), the two calls
1767 url="http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.1.2.2"
1768 text="pipelined"/>. This can dramatically improve performance.
1770 Ibex supports HTTP Basic and Digest authentication. To use
1771 authentication, pass [[ibex.net.rpc.xml()]] a URL in the form
1774 http[s]://user:password@hostname/
1777 Ibex will use Digest authentication if the server supports it;
1778 otherwise it will use Basic authentication. Please be aware that
1779 many XML-RPC server implementations contain a <link
1780 url="http://www.ibex.org/faq.html#auth" text="broken
1781 implementation of Basic authentication"/>.
1785 <section title="SOAP">
1787 SOAP methods are invoked the same way as XML-RPC methods, but with three differences:
1789 <list type="ordered">
1791 [[ibex.net.rpc.soap()]] is used instead of
1792 [[ibex.net.rpc.xml()]]
1794 Instead of specifying just the URL of the service itself, you
1795 must specify the URL, the SOAPAction argument, and the
1798 The actual method invocation takes only one argument, which
1799 must be an object. This is necessary since SOAP arguments are
1800 specified by name, rather than ordering.
1804 SOAP faults are handled the same way as XML-RPC faults except that the
1805 capitalization of the [[faultstring]] and [[faultcode]]
1806 members is all lower-case, to match the SOAP spec. Here is a
1810 Press1 ++= function(v) {
1811 ibex.thread = function() {
1812 color = ibex.net.rpc.soap("http://soap.ibex.org/SOAP",
1814 "http://ibex.org/namespace"
1815 ).color.getTodaysColor( {
1822 As you can see, SOAP is much more verbose, yet does not offer
1823 substantially improved functionality. We recommend that XML-RPC be
1824 used whenever possible, and that SOAP be reserved for legacy
1827 The current Ibex SOAP stack does not support 'document style' or
1828 multi-ref ([[href]]) data structures.
1832 <section title="Security">
1834 Applications downloaded from the network (as opposed to those loaded
1835 from the filesystem) may only make certain kinds of connections to
1836 certain hosts. See Appendix A for a detailed description of the
1842 <!-- ----------------------------------------------------------------------- -->
1843 <section title="Error Handling">
1845 If the Ibex Core encounters an error while servicing a function call
1846 originating in JavaScript, the core will throw a string consisting of
1847 an error code followed by a colon, a space, and a descriptive message.
1851 "ibex.net.dns.unknownhostexception: unable to resolve host foo.com"
1854 The code should be used to determine how the program should respond to
1855 an error. The codes are organized in a hierarchy, so the
1856 string.startsWith() method can be used to determine if an error lies
1857 within a particular subhierarchy. The descriptive message portion of
1858 the string may be shown to the user.
1860 <property name="ibex.assertion.failed">
1863 <property name="ibex.io">
1864 General I/O exceptions
1866 <property name="ibex.io.encoding">
1867 Error translating between character encodings.
1869 <property name="ibex.io.zip">
1870 Attempted to access a corrupt zip archive.
1872 <property name="ibex.io.eof">
1873 End of file encountered unexpectedly
1875 <property name="ibex.net.security.prohibitedHost">
1876 A piece of untrusted Ibex code attempted to contact a
1877 restricted host. See <link appendix="Security Architecture and Considerations"/> for details.
1879 <property name="ibex.net.dns.temporaryFailure">
1880 An attempt to resolve a hostname failed but it is not known
1881 for certain that the hostname is invalid.
1883 <property name="ibex.net.dns.unknownHost">
1884 An attempt to resolve a hostname failed because the hostname
1887 <property name="ibex.net.socket.closed">
1888 A socket was closed unexpectedly.
1890 <property name="ibex.net.socket.connectionFailed">
1891 A connection could not be made to the remote host.
1893 <property name="ibex.net.url.malformed">
1894 Tried to parse a malformed URL.
1896 <property name="ibex.net.ssl">
1897 General SSL protocol errors.
1899 <property name="ibex.net.ssl.untrustedCertificate">
1900 The server's certificate was not signed by a CA trusted by Ibex.
1902 <property name="ibex.net.http.">
1903 Thrown when an HTTP error code is returned during an
1904 operation. The three characters [[**xyz**]] will be
1905 the three-digit HTTP status code.
1907 <property name="ibex.net.xmlrpc.null">
1908 The caller attempted to transmit the [[null]] value via XML-RPC.
1910 <property name="ibex.net.xmlrpc.circular">
1911 The caller attempted to transmit a circular data structure via XML-RPC.
1913 <property name="ibex.net.xmlrpc.specialObject">
1914 The caller attempted to transmit a "special" object via
1915 XML-RPC (for example, a Box or the Ibex object).
1917 <property name="ibex.null.put">
1918 A JavaScript attempted to put to a property on the [[null]] value
1920 <property name="ibex.null.get">
1921 A JavaScript attempted to get from a property on the [[null]] value
1923 <property name="ibex.null.call">
1924 A JavaScript attempted to call the [[null]] value
1927 If an exception is thrown inside a trap, the exception will propagate
1928 to the script that triggered the trap.
1930 If an uncaught exception is thrown while applying a template, or the
1931 requested template could not be found, an error will be logged and the
1932 box to which the template was being applied will be made invisible
1933 ([[visible = false]]). This ensures that half-applied widgets are
1934 never shown to the user.
1938 <!-- ----------------------------------------------------------------------- -->
1939 <section title="Advanced Topics">
1941 <section title="Re-routing events">
1943 At any point in the Event Context, you can write to the [[mouse]]
1944 property on any box. The value written should be an object with two
1945 properties, [[x]] and [[y]]. For example:
1948 _Press1 ++= function(p) {
1949 mouse = { x: 32, y: 77 };
1953 The coordinates specified are relative to the box whose [[mouse]]
1954 property is being written to. There is no need to supply the
1955 [[inside]] property; it is computed automatically. Writing to
1956 the [[mouse]] property causes Ibex to recompute the eventual
1957 target box, and also alter the values returned by [[mouse.x]],
1958 [[mouse.y]], and [[mouse.inside]] for any **descendants**
1959 of the current box. Writing to the [[mouse]] property also
1960 automatically prevents the event from returning to the box's parents
1961 -- it is equivalent to not cascading on the non-underscored event.
1962 This ensures that child boxes cannot trick their parent boxes into
1963 thinking that the mouse has moved.
1965 If you want the event to "skip over" the boxes between the trapee
1966 and the target, or if you want to re-route an event to a box which
1967 is not a descendant of the current box, simply write the value to
1968 the proper key on the target box.
1972 _KeyPressed = function(k) { ibex.log.info("first"); }
1973 KeyPressed = function(k) { ibex.log.info("sixth"); }
1974 $recipient.target = $target;
1975 <ui:box id="recipient">
1976 _KeyPressed = function(k) {
1977 ibex.log.info("second");
1978 thisbox.target.KeyPressed = k;
1979 // inhibit cascade; keep event from going to $excluded
1982 KeyPressed = function(k) { ibex.log.info("fifth"); }
1983 <ui:box id="excluded">
1984 _KeyPressed = function(k) {
1985 ibex.log.info("this never happens");
1989 <ui:box id="target">
1990 _KeyPressed = function(k) { ibex.log.info("third"); }
1991 KeyPressed = function(k) { ibex.log.info("fourth"); }
1998 <section title="Synthesizing Your Own Events">
2000 You can create "fake events" by simply writing to the [[mouse]]
2001 property and then writing a value to one of the underscored properties
2002 on a box. This will have exactly the same effect as if the use had
2003 actually pressed a key, clicked a button, or moved the mouse -- they
2004 are indistinguishable.
2008 <section title="Ibex self-emulation">
2010 When the core first starts up, it clones the [[ibex]] object,
2011 creates a stream for the initial .ibex, and then places a trap on the
2012 cloned [[ibex]] object so that its empty-string property returns
2013 the .ibex stream. The cloned Ibex object is then passed as the third
2014 (optional) argument to [[ibex.apply()]], making it the default
2015 [[ibex]] object for the scripts that are executed as part of the
2016 template instantiation.
2019 var new_ibex = ibex.clone(ibex);
2020 var stream = ibex.bless(ibex.stream.url("http://..."));
2021 new_ibex[""] ++= function() { return stream; }
2022 ibex.apply(ibex.box, new_ibex..main, new_ibex);
2025 Note that we called [[ibex.bless()]] on the stream before tacking
2026 it on to the new Ibex object. The bless function returns a clone of
2027 the object passed to it, with a few traps which are explained below.
2028 Additionally, any sub-streams retrieved by accessing properties of the
2029 blessed stream will also automatically be blessed (blessed streams are
2032 Blessing a stream serves three purposes:
2034 <list type="unordered">
2036 Blessed clones always return the appropriate static block when
2037 their empty property is accessed; this ensures that references
2038 to the static blocks of other templates work properly.
2040 Blessed substreams can return their parent stream by accessing
2041 a hidden property which is reserved for internal use by Ibex.
2042 This ensures that Ibex can automatically add filename
2043 extensions where needed, according to the following rules:
2046 If the stream is a template to be applied, the string
2047 "[[.ibex]]" is appended.
2049 If the stream is an image, the string "[[.png]]" is
2050 appended. If no stream is found, "[[.jpeg]]" and
2051 "[[.gif]]" are tried, in that order.
2053 If the stream is an font, the string "[[.ttf]]" is
2057 Every call to [[ibex.bless()]] returns a different object
2058 (which happens to be a clone of the object passed to it) with
2059 a completely separate set of static blocks.
2063 Ibex can self-emulate by using [[ibex.clone()]] on the Ibex object;
2064 this technique is very similar to the use of ClassLoaders in
2065 Java. This is useful for a number of applications, including
2066 debuggers, IDEs, sandboxing untrusted code, remote-control, and
2067 others. For example:
2070 var newLoadFunction = function(url) { /* ... */ };
2071 var new_ibex = ibex.clone(ibex);
2072 new_ibex.load ++= function() { return newLoadFunction; }
2073 ibex.apply(ibex.box, .main, new_ibex);
2078 <!-- ----------------------------------------------------------------------- -->
2079 <appendix title="Security Architecture and Considerations">
2081 Due to the expense and hassle imposed by the commercial PKI code
2082 signing architecture, and the fact that it <link
2083 url="http://www.counterpane.com/pki-risks-ft.txt" text="doesn't
2084 really provide any security anyways"/>, Ibex user interfaces are
2085 distributed as unsigned, untrusted code. As such, they are handled
2086 very carefully by the Ibex Core, and assumed to be potentially
2089 Ibex's security architecture is divided into defenses against four
2090 major classes of attacks:
2092 <heading title="Malicious UI attempts to acquire or alter data on the client"/>
2094 Ibex user interfaces are run in an extremely restrictive sandbox. The
2095 environment does not provide primitives for accessing any data outside
2096 the Ibex core except via XML-RPC and SOAP calls. There are no
2097 facilities to allow Ibex user interfaces to access the client's
2098 operating system or to interact with other applications on the same
2099 host (unless they provide a public XML-RPC or SOAP interface).
2100 An Ibex script may only access a file on the user's hard disk if the
2101 user explicitly chooses that file from an "open file" or "save file"
2102 dialog. There is one exception to this rule: if all templates
2103 currently loaded in the Ibex core originated from the local
2104 filesystem, those templates can load additional .ibexs from the local
2107 The Ibex Core is written in Java, so it is not possible for
2108 scripts to perform buffer overflow attacks against the core
2111 Ibex applications may only read from the clipboard when the user
2112 middle-clicks (X11 paste), presses control-V (Windows paste), or
2113 presses alt-V (Macintosh paste; the command key is mapped to Ibex
2114 "alt"). This ensures that Ibex applications are only granted access to
2115 data that other applications have placed on the clipboard when the user
2116 specifically indicates that that information should be made available
2117 to the Ibex application.
2119 <heading title="Malicious UI attempts to use client to circumvent firewalls"/>
2121 Ibex user interfaces may only make XML-RPC or SOAP calls and load .ibex
2122 archives via HTTP; they cannot execute arbitrary HTTP GET's or open
2123 regular TCP sockets.
2125 Ibex will not allow a script to connect to a non-public IP address
2126 (10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16, as specified in <link
2127 url="http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc1918.html" text="RFC
2128 1918"/>). There is one exception -- if all templates currently loaded
2129 in the core originated from the same IP address, those scripts may
2130 make calls to that IP address regardless of whether or not it is
2131 firewalled. If Ibex does not have access to a DNS resolver (because it
2132 is using a proxy which performs DNS lookups), Ibex will provide the
2133 proxy with the appropriate <link
2134 url="http://www.ibex.org/x-requestorigin.html"
2135 text="X-RequestOrigin"/> header that the proxy needs in order
2136 to maintain security.
2138 The only remaining possible attack is against a XML-RPC or SOAP
2139 service running on a firewalled host with a public address. Assigning
2140 such machines public IP addresses is a poor network security policy,
2141 and doing so squanders scarce public IPv4 addresses. As such, the onus
2142 is on the administrators of such machines to explicitly block access
2143 to clients reporting a [[User-Agent:]] header beginning with the
2144 four characters "[[IBEX]]".
2146 <heading title="Malicious UI attempts to trick user into divulging secret information"/>
2148 All top-level windows created by Ibex are **scarred** -- a stripe
2149 and a lock is drawn across the corner of the window. There is no way
2150 for a user interface to remove this scar. Ibex user interfaces may not
2151 create windows smaller than the size of the scar.
2153 <heading title="Malicious network attempts to snoop or man-in-the-middle transactions"/>
2155 Ibex user interfaces may transmit network data using HTTPS (SSL 3.0)
2156 for encryption. Ibex will attempt 128-bit encryption, but will
2157 negotiate down to 40-bit if the server does not support strong
2158 crypto. Ibex's SSL implementation is currently provided by <link
2159 url="http://www.ibex.org/tinyssl" text="TinySSL"/> and <link
2160 url="http://www.bouncycastle.org" text="The Legion of the Bouncy
2163 All HTTPS connections must be authenticated by the server using a
2164 certificate whose name matches the domain name of the HTTPS URL. The
2165 certificate must be signed by a trusted root CA. Ibex trusts the same
2166 93 root CAs whose certificates are included as "trusted" in Microsoft
2167 Internet Explorer 5.5 SP2. This provides a minimal level of protection
2168 against man-in-the-middle attacks; you should not trust this
2169 connection with any data you would not normally trust an SSL-enabled
2174 <!-- ----------------------------------------------------------------------- -->
2175 <appendix title="ECMAscript compliance">
2177 Ibex's scripts are written in a modified subset of ECMA-262, revision 3
2178 (aka JavaScript 1.5). The interpreter strays from the spec in a few
2181 <section title="Omissions">
2183 The following ECMA features are not supported:
2185 <list type="unordered">
2187 The [[undefined]] value, [[===]], and [[!==]]
2189 The [[new]] keyword (and ECMAScript object inheritance)
2192 [[getter]] and [[setter]]
2194 The ECMA [[this]] keyword.
2196 The [[String]], [[Number]], and [[Boolean]]
2197 classes. Note that [[string]], [[number]], and
2198 [[boolean]] values are supported, however.
2200 You may not [[throw]] the [[null]] value.
2204 Additionally, you must declare all root-scope variables (with
2205 [[var]]) before using them; failure to do so will result in an
2206 exception. Box properties are pre-defined in the scope that scripts
2211 <section title="Extensions">
2213 <list type="unordered">
2215 The token [[..]] is equivalent to [[[""]]].
2221 Extended [[catch]] syntax. The following code:
2223 } catch(e propname "foo.bar.baz") {
2230 if (e.propname != null and e.propname >= "foo.bar.baz" and
2231 "foo.bar.baz/" > e.propname) {
2236 Multiple extended-catch blocks can appear at the end of a single try
2237 block. However, at most one non-extended catch block may appear, and
2238 if it does appear, it must be the last one.
2240 Since Ibex ECMAscripts are wrapped in XML, the lexical token
2241 "[[lt]]" is be interpreted as [[<]], the lexical
2242 token "[[gt]]" is be interpreted as [[>]], and the
2243 token "[[and]]" is interpreted as [[&&]].
2244 Thus these tokens cannot be used as variable names.
2246 The identifier [[static]] is a reserved word in
2247 ECMAScript, but not in Ibex.
2249 Ibex defines an additional reserved word, "[[assert]]",
2250 which will evaluate the expression which follows it, throwing
2251 a [[ibex.assertion.failed]] exception if the expression
2252 evaluates to [[false]].
2254 To ensure that Ibex files appear the same in all text editors, tab
2255 characters are not allowed in Ibex files.
2259 Some useful tutorials include:
2261 <list type="unordered">
2264 url="http://developer.netscape.com/docs/manuals/communicator/jsref/index.htm"
2265 text=" JavaScript 1.2 Reference"/>. Although this document is
2266 out of date, it is arguably the best guide available for free
2267 on the Internet. The changes from JavaScript 1.2 (aka ECMA-262
2268 r1) to 1.5 were minimal, and many of them were <link
2269 url="ecmascriptcompliance" text="omitted"/> from Ibex.
2272 url="http://search.barnesandnoble.com/booksearch/isbnInquiry.asp?isbn=0596000480"
2273 text=" JavaScript: The Definitive Guide"/>, by David Flanagan
2274 and Paula Ferguson. The latest edition of this book covers
2275 JavaScript 1.5 (ECMA-262 r3).
2278 url="http://www.ecma.ch/ecma1/STAND/ECMA-262.HTM"
2279 text="ECMA-262"/> specification. This is an extremely
2286 <!-- ----------------------------------------------------------------------- -->
2287 <appendix title="Logging and Command Line Invocation">
2290 Usage: ibex [-lawp] [ url | file | directory ]
2291 -l [level] set logging level to { debug, info (default), warn, error, silent }
2292 -l rpc log all XML-RPC and SOAP conversations
2293 -l user@host email log to user@host
2294 -l host:port emit log to TCP socket
2295 -l [file] write log to a file on disk
2297 -w [window-id] reserved for libibex
2298 -p dump profiling information [not yet supported]
2301 If Ibex encounters a serious problem before it starts logging
2302 information, or if it is unable to open the log file, it will abort
2303 immediately with a critical abort, which will be displayed on the
2304 console for POSIX-native cores and in a dialog box for JVM-based and
2307 Note that Microsoft Windows does not provide any mechanism for
2308 redirecting standard input/output of an application which is not
2309 compiled as a "console application". Therefore, Ibex is compiled
2310 as a "console application", and will open a console window when
2311 invoked. To inhibit this console window, provide a logging
2312 destination (file, port, etc).
2314 The [[**source-location**]] parameter can be either the path
2315 to an [[.ibex]] archive, the http url of an [[.ibex]]
2316 archive, or the path to a directory comprising an unpacked
2319 The [[**initial-template**]] parameter is the stream name of
2320 a template to be used as the initial template. If ommitted, it
2321 defaults to [[main]].
2323 The [[-v]] option causes Ibex to enable verbose logging; this will
2324 cause it to log **lots** of information to the log file. This
2325 option will also substantially decrease Ibex's performance.
2329 <!-- ----------------------------------------------------------------------- -->
2331 <appendix title="Grammars">
2333 **Grammar support is experimental in this release
2334 and may not work properly. It may change in incompatible ways or
2335 disappear completely from future releases**
2337 Grammars are defined with a statement in the following form:
2342 A grammar is really just another function; once defined you can't tell
2343 it apart from an ordinary function. A grammar takes one argument,
2344 which can be a string or stream. The argument is parsed and the
2345 result of executing the code block 'c' is returned.
2347 The property 'a' is read; if the value is a grammar, a new production
2348 rule (ie a new alternative, as with '[[|]]') is added to that grammar
2349 (this is a destructive update). This allows you to add productions to
2350 pre-existing grammars (for example, adding a new type of expression to
2351 a programming language by extending the 'expr' grammar). If the old
2352 value is not a grammar, the value is discarded and a new grammar
2355 The value 'b' is a pattern, which may consist of seven simple
2358 <list type="unordered">
2361 grouping parens [[()]]
2363 combinators: [[ | + * ?]]
2365 references to other grammars
2368 The value 'c' and the braces surrounding it are an *optional* code
2369 block, in which the following identifiers are bound:
2371 <list type="unordered">
2373 The identifier 'whole' is bound to the string matched by the
2374 entire expression. If the code block is omitted it behaves
2375 as if it were "[[{ return whole; }]]".
2377 For every reference to another grammar which was matched in the
2378 pattern, the *name used to reference that other grammar* will
2379 be bound to the value returned by its code block. Here's an
2380 example of this important distinction:
2383 var foo ::= 'a' | 'b';
2385 var baz ::= 'c' | bar { /* foo is not defined here, but bar is */ };
2388 On the last line, the identifier 'bar' serves two purposes: it
2389 pulls in the definition of the pattern *and* acts as a binder
2390 within the scope of the braces.
2392 If a reference is matched multiple times (either because it
2393 appears multiple times in the pattern or because the * or +
2394 operator was applied to it) then its name will be bound to an
2395 array containing the matches.
2399 Here is the metacircular definition of the grammar facility:
2402 grammar ::= identifier '::=' pattern (';' | '{' code '}' ';'?)
2403 identifier ::= ('a'..'z' | 'A'..'Z' | '_' | '$') (identifier | '0'..'9')*
2404 char ::= '\0x0000'..'\0xffff'
2405 literal ::= '\'' char+ '\''
2406 | '\'' char '\'' '..' '\'' char '\''
2407 pattern ::= identifier
2414 | pattern '|' pattern
2419 Copyright (C) 2004 Adam Megacz, verbatim redistribution permitted.
2420 Ibex is a trademark of Adam Megacz