+++ /dev/null
-<ibex-doc title="The Ibex Reference" subtitle="Nitrogen Release" author="Adam Megacz" email="adam@ibex.org">
-
-<!-- ----------------------------------------------------------------------- -->
-<section title="Preface">
-
- <i>
- If you are reading the html version of this document and are
- thinking of printing it out, you might be interested in the nicely
- typeset <link url="reference.pdf" text="pdf version"/> produced
- with LaTeX.
- </i>
-
- This document is a <b>reference</b>. It is not a
- <b>specification</b> or a
- <b>tutorial</b>.
-
- This document does not guide the user gently through examples (as a
- tutorial would), and it doesn't provide enough detail and formality
- for a third party to construct a compatible re-implementation of the
- Ibex Core (as a specification would).
-
- Rather, the goal of this document is to completely describe every
- aspect of the environment that the Ibex Core provides to client
- applications, from the bottom up. If you want to be an Ibex expert,
- this is the right document to read. It is assumed that you are already
- familiar with XML and with either JavaScript or ECMAscript. If
- you are not familiar with ECMAscript, some reference materials are
- provided in <link appendix="G"/>
-
- The <i>wildebeest sequence</i> (how the Ibex Core gets onto the
- client's computer, and how it knows where to download the initial
- <t>.ibex</t> from) is not described in this document, since it
- will be different for every platform that Ibex is ported to.
-
- If you need to use or rely on some behavior you notice in the Ibex
- Core, but which is not clearly defined here, please post to <link
- url="http://lists.ibex.org/listinfo/users" text="the users mailing list"/>.
-
- <section title="Key Concepts">
-
- <definition term="The Core">
- Ibex itself; the native code (or Java bytecode) that runs on
- the client. This term does not include the <i>wildebeest</i>
- or the <i>UI</i></definition>
-
- <definition term="The UI / The Application">
- a set of files (mostly XML, JavaScript, and PNG images)
- bundled up in a zip archive, ending with the "..ibex"
- extension. Together, these files specify the appearance and
- behavior of the application's user interface. Sometimes
- we'll refer to this as the ".ibex" to be clear that we're
- talking about the actual zip archive, rather than its visual
- appearance when rendered on the screen.</definition>
-
- <definition term="The Server">
- We will use the term "the server" to refer to any other
- computer which the client makes XML-RPC or SOAP calls
- to. Note that it is possible for the client and server to be
- the same machine.</definition>
-
- <definition term="The Wildebeest">
- this is a very small piece of code that is downloaded the
- first time a client uses Ibex. It downloads the Ibex core,
- verifies its signature, and launches it with the appropriate
- parameters indicating where to find the initial UI. The
- Wildebeest works differently on every platform, and is outside
- the scope of this document.</definition>
-
- <definition term="put/write">
- In ECMAscript, when you change the value of a property on an
- object, you are <i>putting</i> to that property, or
- <i>writing</i> to it. For example, the ECMAscript expression
- "<t>foo.bar = 5</t>" <i>puts</i> the value 5 to the bar
- property on object foo.</definition>
-
- <definition term="get/read">
- In ECMAscript, when you access the value of a property on an
- object, you are <i>getting</i> that property, or
- <i>reading</i> from it. For example, the ECMAscript
- expression "<t>return (3 + foo.bar)</t>" <i>gets</i> the
- value of bar property on object foo and then adds 3 to it
- before returning the result.</definition>
-
- <definition term="JavaScript">
- We will use the terms JavaScript and ECMAScript
- interchangeably in this document. The Ibex interpreter is not
- completely ECMA-compliant, however (see <link
- appendix="C"/> for details). </definition>
- </section>
-</section>
-
-<section title="Surfaces">
-
- Each top-level window in an Ibex UI is called a
- <i>surface</i>. There are two kinds of surfaces: <i>frames</i>,
- which usually have a platform-specific titlebar and border, and
- <i>windows</i>, which never have any additional platform-specific
- decorations.
-
- Whenever we refer to the size or position of a surface, we are
- referring to the size or position of the UI-accessible portion of the
- surface; this does not include any platform-specific decorations. This
- means that if you set the position of a frame to (0,0), the
- platform-specific titlebar will actually be off the screen on most
- platforms (it will be above and to the left of the top-left corner of
- the screen).
-
- Surfaces are not actual JavaScript objects; you cannot obtain a
- reference to a surface. However, each surface is uniquely identified
- by its <i>root box</i>, described in the next section.
-
-</section>
-
-<section title="Boxes">
-
- A <i>box</i> is the fundamental unit from which all Ibex user
- interfaces are built. Boxes can contain other boxes (known as
- <i>children</i>). Each Surface has a single box associated with it
- called the <i>root box</i>; the root box and its children (and its
- children's children, and so on) form the surface's <i>box tree</i>.
-
- There are three ways to think of a box: as a rendered visualization on
- the screen (the "Visual Representation"), as a JavaScript object (the
- "Object Representation"), and as an XML tag (the "XML
- Representation").
-
- FIXME: diagram here
-
- All three representations are equally valid, and being able to figure
- out what an action in one representation would mean in terms of the other
- two representations is crucial to a solid understanding of Ibex.
-
- <section title="The Object Representation">
-
- Each box is a full-fledged ECMAscript object, and can store key-value
- pairs as properties. Some of these keys have special meaning, which
- will be explained later. Each box's numeric properties hold its
- <i>child boxes</i>.
-
- </section>
-
- <section title="The Visual Representation">
-
- Each box occupies a rectangular region on the surface. The visual
- appearance of a surface is created by rendering each box in its tree.
- Unless the <t>clip</t> attribute is <t>false</t>, each box will
- clip its childrens' visual representations to its own, so that the
- children appear "confined to" the parent. Children are rendered after
- their parents so they appear "on top of" their parents (they obscure
- them).
-
- Each box has two major visual components, each with subcomponents:
-
- FIXME: diagram
-
- <list>
- A <b>path</b>, which consists of zero or more lines and
- curves. The path may be filled with a color, gradient, or
- texture, and may be stroked with a line of a given thickness
- and color. If the path is not specified, it defaults to the
- perimiter of the box.
-
- <list>
- The path has an associated <b>strokecolor</b>, which is a
- color
-
- The path has an associated <b>strokewidth</b>, which is a
- number specifying the width of the stroke.
-
- The path also has a <b>fill</b>, which is either a color, gradient, or
- texture
-
- A single line of <b>text</b>, which can be rendered in
- different fonts, colors, and sizes.
- </list>
-
- The text has an associated <b>font</b>, which currently can be
- any font supported by the <link url="http://www.freetype.org"
- text="FreeType2"/> library.
-
- The text also has an associated <b>fontsize</b>
-
- The text is drawn in an associated <b>textcolor</b>
-
- </list>
-
- These eight components plus the size of a box fully specify its
- appearance. Every single box you see in Ibex is drawn only on the
- basis of these components and its size.
-
- </section>
-
- <section title="The XML Representation">
-
- A template (discussed in the next section) is an XML file which acts
- as a blueprint for constructing a tree of boxes. We call this
- construction process <i>applying</i>, since unlike
- <i>instantiation</i>, you always apply a template to a pre-existing
- box, and you can apply multiple templates to the same box. Each XML
- tag corresponds to a single box, or to another template which will be
- applied to that box. For example, a <t>scrollbar</t> template, when
- applied, will construct a tree of boxes which has the visual
- appearance and behavior of a scrollbar.
-
- Although it is useful to think of the XML tags as being boxes, keep in
- mind that the XML representation is only a blueprint for constructing
- a tree of JavaScript objects. Once the template has been
- instantiated, the XML is effectively "thrown away", and JavaScript code is
- free to alter the boxes.
-
- </section>
-</section>
-
-<section title="Templates">
-
- Each template is an XML document whose root element
- is <t><ibex></t>. Any text content of the root element is
- ignored, and may safely be used for comments. The root element may
- have any of the following elements as children, each of which may
- appear no more than once, and which must appear in this order:
-
- Here is a sample Ibex file:
-
- <pre>
- <ibex xmlns="ibex.widget" xmlns:lib="ibex.lib">
- This is a sample Ibex file. Text up here is ignored.
- Copyright (C) 2004 Mustapha Mond.
- <static>
- // code here will be executed only once
- </static>
- <template cols="5">
- <box id="container"/>
- <checkbox/>
- <box>
- /* This has to be commented out or else it
- will be treated as a script */
- <lib:scrollbar/>
- </box>
- </template>
- </ibex>
- </pre>
-
- <heading title="Applying an XML Tag to a Box"/>
-
- The following description of the box application is extremely detailed
- and precise; it is intended for UI designers who need to know the
- exact order in which each event happens. FIXME:
- easier description. While this whole process sounds very
- complex, it actually works pretty intuitively. The description below
- is given in great detail since most applications will wind up being
- unintentionally dependent on subtle features of this process.
- However, most of the time you can just pretend that the XML tags and
- the boxes are the same thing.
-
- To apply an XML tag <t><b>X</b></t> to a box <t><b>B</b></t>, perform the following
- operations, in this order:
-
- <list type="ordered">
-
- Allocate a fresh scope <t><b>s</b></t> whose parent scope is
- <t><b>b</b></t>.
-
- Process each child element or text segment of <t><b>X</b></t> in the
- order they appear in the document: For each <i>text
- segment</i> <t><b>t</b></t>:
-
- <list>
- Treat <t><b>t</b></t> a JavaScript script, and execute it
- with <t><b>s</b></t> as the root scope.
- </list>
-
- For each child element <t><b>x</b></t> of
- <t><b>x</b></t>:
-
- <list>
- Create a new box <t><b>b</b></t>.
-
- If the name of tag <t><b>x</b></t> is not "<t>box</t>" (in the
- default XML namespace), prepend the tag's namespace
- identifier uri (if any) to the name of the tag, and use
- the result as a key to retrieve a property from the root
- stream (defined later). Interpret the resulting stream as
- a template and apply that template to <t><b>b</b></t>.
-
- (recursively) apply <t><b>x</b></t> to <t><b>b</b></t>.
-
- If <t><b>x</b></t> has an <t>id</t> attribute, declare a variable
- in <t><b>s</b></t> whose name is the value of the <t>id</t>
- attribute, prefixed with the <t>$</t> character, and whose
- value is <t><b>b</b></t>
-
- Copy any <t>$</t>-variables created during the application
- of <t><b>x</b></t> into scope <t><b>s</b></t>.
-
- Append <t><b>b</b></t> as the last child of <t><b>b</b></t>.
- </list>
-
- Apply any attributes on <t><b>x</b></t> to <t><b>b</b></t>, except for
- <t>id</t>. Since XML specifies that the order of attributes
- cannot be significant, Ibex processes attributes in
- alphabetical order by attribute name. For example, if
- <t><b>x</b></t> has the attribute <t>foo="bar</t>", then the
- equivalent of the statement <t>B.foo="bar";</t> will be
- performed, with the following exceptions:
-
- <list>
- If the value portion of the attribute is the string
- "<t>true</t>", put the boolean <t>true</t>. If the
- value is "<t>false</t>", put the boolean <t>false</t>.
-
- If the value is a valid ECMAscript number, put it as a
- number (instead of a string).
-
- If the value begins with a dollar sign (<t>$</t>),
- retrieve the value of the corresponding variable in
- <t><b>s</b></t> and use that value instead.
-
- If the value begins with a dot (<t>.</t>), prepend the
- attributes' namespace identifier uri (if any) and
- interpret the remainder as a property to be retrieved from
- the root stream (defined later).
- </list>
- </list>
-
- The last two steps are referred to as the <i>initialization</i> of the
- node. There are two important aspects of this ordering to be aware of:
-
- <list type="unordered">
-
- A given box will be fully initialized before its parent is
- given a reference to that box. This way, parents can be
- certain that they will never wind up accessing a box when it
- is in a partially-initialized state.
-
- Attributes are applied <i>after</i> scripts are run so that
- the attributes will trigger any <i>traps</i> (defined later)
- placed by the script.
-
- </list>
-
-</section>
-
-<section title="Life Cycle of an Ibex Application">
-
- A user begins by specifying the URL of an Ibex application run.
- Usually this is done by visiting a web page which uses the
- <i>wildebeest</i> to install the core if it is not already on the user's
- machine, but you can also supply the URL on the command line.
-
- The Ibex Core downloads the .ibex for the application, loads it, applies
- the <t>main.ibex</t> template and renders it onto the screen, running
- any associated ECMAscript code.
-
- The user interacts with the application by clicking and moving the
- mouse, and by pressing keys on the keyboard. These actions trigger
- fragments of JavaScript code which are designated to handle events.
- This JavaScript code can then relay important information back to the
- server using XML-RPC or SOAP, or it can modify the structure and
- properties of the user interface to change its appearance, thereby
- giving feedback to the user.
-
-
- DIAGRAM: graphic here showing the circular feedback cycle.
-
-
- The Ibex core quits when the last remaining surface has been destroyed.
-
-</section>
-
-<!-- ----------------------------------------------------------------------- -->
-<section title="Layout and Rendering">
-
- The size and position of every other box is determined
- by its properties, its childrens' sizes, and its parent's size and position.
- Box layout and rendering happens in four phases: <i>packing</i>,
- <i>constraining</i>, <i>placing</i>, and <i>rendering</i>. The Core is careful to only
- perform a phase on a box if the box has changed in a way that
- invalidates the work done the last time that phase was performed.
- The
- packing and constraining phases are performed in a single traversal of
- the tree (packing is preorder, constraining is postorder), and the
- placing and rendering phases are performed in a second traversal of
- the tree (first placing, then rendering, both preorder).
-
- For brevity, the rest of this chapter deals only with width and
- columns. Height and rows is treated identically and independently.
- Also, it is important to note that the term <i>minimum width</i> is
- not the same thing as the property <t>minwidth</t>, although they
- are closely related.
-
- <section title="The size of the root box">
-
- When the user resizes a window, Ibex changes the root box's
- <t>maxwidth</t> and <t>maxheight</t> to match the size chosen by
- the user and then determines the root box's size using the same sizing
- rules it uses for other boxes.
-
- Ibex will always attempt to prevent the
- user from making the surface smaller than the root box's
- <t>minwidth</t> and <t>minheight</t>. If the <t>hshrink</t> or
- <t>vshrink</t> flag is set, Ibex will try to prevent the user from
- resizing the surface at all. However, not all platforms give Ibex
- enough control to do this.
-
- </section>
-
- <section title="The alignment point">
-
- When talking about positioning, we will often refer to the
- <i>alignment point</i>.
-
- <list type="unordered">
-
- If the <t>align</t> property is "<t>center</t>", then the
- alignment point is the center of the box.
-
- If the <t>align</t> property is "<t>topleft</t>",
- "<t>bottomleft</t>", "<t>topright</t>", or
- "<t>bottomright</t>", then the alignment point is
- corresponding corner of the box.
-
- If the <t>align</t> property is "<t>top</t>",
- "<t>bottom</t>", "<t>right</t>", or "<t>left</t>", then
- the alignment point is middle of the corresponding edge of the
- box.
-
- </list>
-
- FIXME: diagram
-
- When positioning a child box, the alignment point is determined by the
- <i>parent's</i> <t>align</t> property. When positioning a visual
- element (a texture, path, or text string) within a box, the alignment
- point is determined by the <i>box's own</i> <t>align</t> property.
-
- A simple way to think about this is that whenever there are two boxes
- involved in the decision, you should use the parent's alignment point.
-
- </section>
-
- <section title="Packing">
-
- of <i>cells</i> is created within the parent. If the parent's
- <t>cols</t> property is set to 0, the cell grid has an infinite
- number of columns. Either <t>cols</t> or <t>rows</t> must be
- zero, but not both.
-
- If a child's <t>visible</t> property is <t>false</t>, it does
- not occupy any cells (and is not rendered). Otherwise, each child
- occupies a rectangular set of cells <t>child.colspan</t> cells
- wide and <t>child.rowspan</t> cells high.
-
- The Core iterates over the cells in the grid in the following
- order: if <t>rows</t> is 0, the Core iterates across each column
- before proceeding to the next row; otherwise rows come before
- columns. At each cell, the Core attempts to place the <i>first
- remaining unplaced child's</i> top-left corner in that cell (with
- the child occupying some set of cells extending down and to the
- right of that cell). If the parent has a fixed number of columns
- and the child's <t>colspan</t> exceeds that limit, the child is
- placed in column zero regardless, but only occupies the available
- set of cells (it does not "hang off the end" of the box).
-
- <image url="image/layout.png"/>
-
- <pre>
- <box cols="3">
- <box id="1" />
- <box id="2" rowspan="2" />
- <box id="3" colspan="2" />
- <box id="4" />
- <box id="5" colspan="2" />
- </box>
- </pre>
-
- Notes on the layout example:
-
- <list type="ordered">
-
- Box '3' doesn't fit in the gap after '2', nor in the gaps either
- side of '2' on the next row, hence it is pushed onto the 3rd row.
-
- Box '4' would fit in the gaps around '2', but must be placed
- <i>after</i> it's preceeding box, '3'.
-
- </list>
-
- </section>
-
- <section title="Constraining">
-
- <list type="ordered">
-
- Each box's minimum width is computed recursively as the
- maximum of:
-
- <list>
- Its <t>minwidth</t>
-
- The width of the box's <t>text</t> (after applying the
- box's <t>transform</t>).
-
- The width of the box's path (after applying the box's
- <t>transform</t>) <i>if the box is <t>packed</t></i>.
-
- The width of the bounding box enclosing the box's cells.
- </list>
-
- The minimum width of each cell is computed as the minimum
- width of the box occupying it divided by the box's
- <t>colspan</t>.
-
- If a box's <t>hshrink</t> property is set to
- <t>true</t>, the box's maximum width is the same as its
- minimum width; otherwise it is the box's
- <t>maxwidth</t>.
-
- The maximum width of each cell is the <t>maxwidth</t> of
- the box occupying it divided by the box's
- <t>colspan</t>.
-
- </list>
-
- </section>
-
- <section title="Placing">
-
- <list type="ordered">
-
- Each column's <i>actual width</i> is set to the maximum
- <i>minimum width</i> of all the cells in that column.
- <b>NOTE:</b> although a column or row can be sized smaller
- than its "minimum width" or larger than its "maximum width", a
- box will <i>never</i> be smaller than its <t>minwidth</t> or
- larger than its <t>maxwidth</t>.
-
- Each column's maximum width is the largest maximum width of
- the cells in that column, but no smaller than the column's
- minimum width.
-
- The <i>slack</i> is the difference between the parent's width
- and the sum of its columns' actual width. The slack is
- divided equally among the columns. Any column which has
- exceeded its maximum width is set to its maximum width, and
- the difference is returned to the slack. This process is
- repeated until the slack is zero or all columns are at their
- maximum width.
-
- Next, the rows and columns are positioned within the parent
- box. The rows and columns are transformed according to the
- parent's <t>transform</t> property, and the bounding box of
- the resulting cells are placed such that the cells' alignment
- point coincides with the parent's alignment point (both
- alignment points are determined by the parent's <t>align</t>
- property). FIXME: diagram
-
- <b>Packed boxes:</b> Each packed box's actual position
- and size is then set to the aggregation of the actual sizes of
- the cells it spans. If this size exceeds the box's maximum
- width, the box is sized to its maximum width and centered
- horizontally within the space occupied by its cells.
-
- <b>Non-packed boxes</b>: each non-packed box is transformed
- according to the parent's <t>transform</t> property and then
- positioned so that its alignment point is <t>(child.x,
- child.y)</t> pixels from the parent's alignment point (both
- alignment points are determined by the parent's <t>align</t>
- property).
-
- </list>
-
- </section>
-
- <section title="Rendering">
-
- Boxes are rendered in a depth-first, pre-order traversal. Note that
- this may cause a non-packed box to overlap its siblings.
-
- <list type="ordered">
-
- If the box's <t>transform</t> property is non-null, the
- coordinate space is transformed accordingly for the rest of
- this phase and for the rendering of all children.
-
- If the box is packed and has a non-<t>null</t> path, the
- path is translated such that the alignment point of the path's
- bounding box coincides with the box's alignment point (both
- alignment points are determined by the box's <t>align</t>
- property).
-
- If a box has a path, that path is filled with the color,
- gradient, or image specified by the <t>fill</t> property and
- stroked with the color and width specified by the
- <t>strokecolor</t> and <t>strokewidth</t> properties.
-
- If the box has a non-null <t>text</t> attribute,
- the text is rendered in <t>font</t> with size
- <t>fontsize</t> and color <t>textcolor</t>. The text is
- then translated such that the alignment point of the text's
- bounding box coincides with the box's alignment point (both
- alignment points are determined by the box's <t>align</t>
- property).
-
- The box's children are rendered (pre-prder traversal).
-
- </list>
-
- </section>
-
- </section>
-
-<!-- ----------------------------------------------------------------------- -->
-<section title="Box Properties">
-
- <section title="Rendering Properties">
-
- Every box has several special properties which control how it is
- drawn. In general, if you put an
- invalid value to a special property, no action will be taken -- the
- put will be ignored.
-
- <property name="strokecolor" type="string" default="clear">
- If the value is a 5-character hex string (<t>#RGB</t>),
- 7-character hex string (<t>#RRGGBB</t>), 9-character hex
- string (<t>#AARRGGBB</t>), the box's stroke color will be set
- to that color.
- If the value is one of the <link url="http://www.color.org/ICC-1A_1999-04.PDF" text="ICC"/> colors
- (the same set of color names supported by SVG), the stroke
- color be set to that color.
- If the value is <t>null</t>, the stroke color will be set to
- clear (<t>#00000000</t>).
- </property>
-
- <property name="strokewidth" type="int" default="1">
- The width (in pixels) to stroke the path with.
- </property>
-
- <property name="fill">
- This property can be set to any of the values specified for
- <t>strokecolor</t>.
- Alternatively, if the value written is an object, its stream
- will be read and interpreted as a PNG, GIF, or JPEG image,
- which will become the texture for this box, and the box's
- <t>minwidth</t> and <t>minheight</t> properties will be
- automatically set to the dimensions of the image.
- </property>
-
- <property name="path" type="string" default='""'>
- The box's path. The grammar and feature set supported are
- identical to that specified in <link
- url="http://www.w3.org/TR/SVG11/paths.html" text="SVG 1.1,
- section 8"/>.
- </property>
-
- <property name="text" type="string" default='""'>
- The box's text; writing <t>null</t> to this property sets it
- to "<t></t>".
- </property>
-
- <property name="font" type="stream" default=".ibex.font.sansserif">
- When an object is written to this property, its stream is read
- using the <link url="http://www.freetype.org" text="freetype2
- library"/>, and the resulting font is used to render the
- box's <t>text</t>.
- </property>
-
- <property name="fontsize" type="number" default="10">
- The size (in points) to render the text.
- </property>
-
- <property name="textcolor" type="number" default="black">
- The color in which to render the font; accepts the same values as <t>strokecolor</t>.
- </property>
-
- </section>
-
- <section title="Layout Properties">
-
- <property name="shrink" type="boolean" default="false">
- If set to <t>true</t>, this box will shrink
- (horizontally/vertically/both) to the smallest size allowed by
- its children and the bounding box of its path.
- </property>
-
- <property name="x" type="integer" default="varies">
- If the box is a root box, this is the (x/y)-coordinate of the
- surface; otherwise it is the distance between the parent's
- alignment point and this box's alignment point.
- </property>
-
- <property name="globalx" type="integer" default="varies">
- The distance between this box's (left/top) edge and the root
- box's (left/top) edge. A put to this property has the same
- effect as a put to the (<t>x</t>/<t>y</t>) property,
- except that it is relative to the root box rather than to this
- box's parent. FIXME is this fakeable? How is
- distance measured?
- </property>
-
- <property name="minwidth" type="integer" default="0">
- The desired minimum width and height.
- </property>
-
- <property name="maxwidth" type="integer" default="ibex.maxint">
- The desired maximum width and height.
- </property>
-
- <property name="width" type="integer" default="varies">
- When read, this is the (width/height) of this box. Writing to
- this property is equivalent to writing to <i>both</i> the
- minimum and maximum (width/height).
- </property>
-
- <property name="cols" type="integer" default="0">
- The number of (columns/rows) in which to lay out the children of this
- box. If set to zero, the number of (columns/rows) is unconstrained.
- Either <t>rows</t> or <t>cols</t> must be zero. If
- <t>0</t> is written to <t>cols</t> when <t>rows</t> is
- <t>0</t>, the write is ignored. If a nonzero value is
- written to <t>cols</t> when <t>rows</t> is nonzero,
- <t>rows</t> is set to <t>0</t>, and vice versa.
- </property>
-
- <property name="colspan" type="integer" default="1">
- The number of (columns/rows) that this box spans within its parent.
- </property>
-
- <property name="align" type="string" default="center">
- Determines the box's alignment point for positioning its text,
- texture, path, and children.
- </property>
-
- <property name="visible" type="boolean" default="true">
- If set to false, this box will be rendered as if its width and
- height were zero. If this is a root box, the associated surface
- will be hidden.
- When reading from this property, the value
- <t>false</t> will be returned if this box <i>or any of its
- ancestors</i> is not visible. Thus it is possible to write
- <t>true</t> to a box's <t>visible</t> property and then
- read back <t>false</t>.
- </property>
-
- <property name="packed" type="boolean" default="true">
- The layout strategy for this box.
- </property>
-
- </section>
-
- <section title="Child Control Properties">
-
- During a box initialization, script-private references to a box's
- descendants with <t>id</t> attributes are placed on the box. These
- references allow scripts on that box to easily refer to descendant
- nodes created by the template in which the script appears. For
- example, these two blocks of code have exactly the same effect:
-
- <pre>
- <box> <box>
- <box id="foo"/> <box/>
- $foo.color = "red"; var $foo = this[0];
- $foo.color = "red";
- </box> </box>
- </pre>
-
- The following special properties control how a box's children are laid
- out. If a box has a non-null redirect target, reads and writes to these
- properties will be forwarded to the redirect target.
-
- The <t>redirect</t> attribute is very useful for hiding the
- internal structure of a widget, and for allowing widgets to act as
- "smart" containers for other widgets. For example, a menu widget might
- have an invisible child as its redirect target; this way, when boxes
- representing items on the menu are added as children of the menu
- widget, they do not appear until the menu is pulled down.
-
- <property name="numeric properties" type="int" default="">
- The <i>n</i>th child of box <t>b</t> can be accessed by reading from
- <t>b[n]</t>. The <i>n</i>th child can be removed by writing
- <t>null</t> to <t>b[n]</t> (the child will become parentless). A
- new child can be inserted <i>before</i> the <i>n</i>th child by
- writing it to <t>b[n]</t>; if the value written is already a child of
- <t>b</t>, it will be removed from <t>b</t> first. It is important
- to note that this behavior is different from ECMAscript arrays --
- writing a non-<t>null</t> value to <t>b[n]</t> does not eliminate
- the <i>n</i>th child; it merely shifts it over one position.
- <b>Note:</b> Unlike most JavaScript objects, enumerating a Box's
- properties with the JavaScript <t>for..in</t> construct will
- enumerate <i>only</i> the box's children and not any other properties.
- </property>
-
- <property name="clip" type="boolean" default="true">
- If <t>true</t>, the visual representation of this box's
- children will be clipped to the boundaries of this box.
- <b>Note:</b> setting this property to <t>false</t> imposes a
- substantial performance penalty.
- </property>
-
- <property name="numchildren" type="integer" default="0">
- The number of children this box has.
- </property>
-
- <property name="redirect" type="box" default="thisbox">
- Writing to this property sets the box's redirect
- target. This property cannot be read from, and can only be
- written to once.
- </property>
-
- <property name="surface" type="" default="null">
- If this box has a parent, this property returns
- <t><i>parent</i>.surface</t>; otherwise it returns null.
- This property is a simple building block that the widget
- library uses to implement more complex functionality such as
- focus control and popups.
- </property>
-
- </section>
-
- <section title="Other Box Properties">
-
- <property name="cursor" type="string" default="null">
- The shape that the cursor should take when inside this
- box. Valid values are: "<t>default </t> " , "<t>wait</t>",
- "<t>crosshair</t>", "<t>text</t>", "<t>hand</t>", and
- "<t>move</t>", as well as resizing cursors"<t>east</t>",
- "<t>west</t>", "<t>north</t>", "<t>south</t>",
- "<t>northwest</t>", "<t>northeast</t>",
- "<t>southwest</t>", and "<t>southeast</t>". Note that on
- some platforms, resize cursors for opposite directions (such
- as <t>northwest</t> and <t>southeast</t> are the
- same).
- If a box's cursor is <t>null</t>, its parent's cursor will
- be used. If the root box's cursor is null, the
- "<t>default</t>" cursor will be used.
- </property>
-
- <property name="mouse.x" type="integer" default="varies">
- The (horizontal/vertical) distance between the mouse cursor and this
- box's (left/top) edge. Puts to this property are ignored. This
- value will not be updated if the mouse is outside the root
- box of the surface and no button was pressed when it left.
- </property>
-
- <property name="mouse.inside" type="boolean" default="false">
- True if the mouse is inside the rendered region of this box or
- any of its children. This value will be false if the mouse is
- inside a portion of this box which is covered up by one of
- this box's siblings, or one of its ancestors' descendants. Puts
- to this value are ignored.
- </property>
-
- <property name="static" type="object" default="N/A">
- Reading from this property will return the parent scope used
- to execute the <t><static/></t> block of the template
- in which the currently-executing code resides.
- </property>
-
- <property name="thisbox" type="box" default=" ">
- Returns a reference to the box itself.
- If <t>null</t> is written to this property, and this box is
- the root box of a surface, the box will be detached and the
- surface destroyed. If this box has a parent, it will be
- detached from its parent.
- </property>
-
- <property name="indexof()" type="function" default=" ">
- This property is actually a function; invoking
- <t>parent.indexof(child)</t> will return the numerical index
- of <t>child</t> in <t>parent</t> if <t>child</t> is a
- child of <t>parent</t> (or <t>parent</t>'s redirect
- target), and <t>-1</t> otherwise. Writing to this property
- has no effect.
- </property>
-
- <property name="childadded" type=" " default=" ">
-
- These properties are meant to be trapped on FIXME defined later?. Placing a trap on
- <t>childadded/childremoved</t> lets a box receive
- notification when a child is added/removed. In either
- situation, the child will be passed as an argument to the trap
- function <i>after</i> the addition or removal has been
- performed.
-
- Note that if the parent's redirect target is set to another
- box, these traps will only be invoked when children are
- manipulated by reading and writing to the parent. Reads and
- writes directly to the redirect target will <i>not</i> trigger
- the traps.
-
- Note also that these traps are still triggered if a box's
- <t>redirect</t> target is <i>null</i>. This is useful for
- boxes that need to accept children and then relocate them
- elsewhere.
- </property>
-
- </section>
-
- <section title="Notification Properties">
-
- The following properties are used to notify a box of changes specific
- to that particular box.
-
- <property name="Enter">
- The value <t>true</t> is written to this property when the mouse enters the box.
- </property>
-
- <property name="Leave">
- The value <t>true</t> is written to this property when the mouse leaves the box.
- </property>
-
- <property name="SizeChange">
- The value <t>true</t> is put to this property after the size
- of this box changes.
- </property>
-
- </section>
-
- <section title="Root Box Properties">
-
- The following special properties are only meaningful on the root box
- of a surface.
-
- <property name="Focused">
- The value <t>true</t> is put to this property on the root box
- when the surface gains the input focus, and <t>false</t> when
- the surface loses the input focus. Reading from this value will
- return <t>true</t> if the surface is focused and <t>false</t>
- if it is not. Putting <t>true</t> to this property will
- <i>not</i> cause the surface to "steal" the input focus from other
- windows.
- </property>
-
- <property name="Maximized">
- The value <t>true</t> is put to this property on the root box
- when the surface is maximized, and <t>false</t> when the surface
- is un-maximized. Reading from this value will return <t>true</t>
- if the surface is maximized and <t>false</t> if it is
- not. Putting <t>true</t> to this property will maximize the
- window, and putting <t>false</t> to this property will
- unmaximize the window.
- Note that not all platforms support maximization.
- </property>
-
- <property name="Minimized">
- The value <t>true</t> is put to this property on the root box
- when the surface is minimized, and <t>false</t> when the surface
- is unminimized. Reading from this value will return <t>true</t>
- if the surface is minimized and <t>false</t> if it is
- not. Putting <t>true</t> to this property will minimize the
- window, and putting <t>false</t> will unminimize it.
- </property>
-
- <property name="Close">
- When the user attempts to close a surface, the value
- <t>true</t> will be put to this property. Scripts may trap
- this property FIXME defined later? to
- prevent the window from closing. Putting the value
- <t>true</t> to this property on a root box has the same
- effect as putting <t>null</t> to the <t>thisbox</t>
- property.
- </property>
-
- <property name="icon">
- The surface's icon. This is usually displayed on the titlebar of a
- window. The value should be the stream name of a PNG image. Note
- that not all platforms support this property.
- </property>
-
- <property name="titlebar">
- The surface's titlebar text. Note that not all platforms support
- this property. Only ASCII characters 0x20-0x7F are permitted.
- </property>
-
- </section>
-
- </section>
-
-<!-- ----------------------------------------------------------------------- -->
-<section title="Streams">
-
- <section title="Every object has a stream...">
-
- Every object has a <i>stream</i> associated with it. A stream is a
- sequence of bytes that can be read or written to.
-
- By default an object has an empty stream (zero bytes). However, some objects
- (returned from special methods on the <t>ibex</t> object) have
- streams yielding data read from an url, file, or a component of a zip
- archive. In a future release, the stream associated with a box will
- be an .ibex template which, when applied, will fully reconstitute the
- box's state.
-
- </section>
-
- <section title="...but streams are not objects">
-
- Despite the ubiquity of streams, you cannot actually reference a
- stream, since it is not an object. Instead, you simply reference the
- object it belongs to. If you are familiar with Java, this is similar
- to how every Java object has a monitor associated with it, but you
- cannot directly manipulate the monitor (you can't pass around a
- reference to just the monitor).
-
- In the rest of the section we will sometimes refer to "getting
- properties from a stream" or "passing a stream to a function"; this is
- just shorthand for saying to perform those actions on the object the
- stream belongs to.
-
- </section>
-
- <section title="Creating Streams from URLs">
-
- You can create a stream from a URL by calling
-
- <pre>
- var r = ibex.stream.url("http://...");
- </pre>
-
- This will return an object whose stream draws data from the specified
- URL. Streams are loaded lazily whenever possible.
-
- </section>
-
- <section title="Getting Substreams">
-
- Most stream objects let you access
- substreams using the usual JavaScript operators <t>[]</t> and
- <t>.</t>, as well as the <t>for..in</t> syntax.
-
- <pre>
- // r1 and r2 are equivalent but not equal (!=)
- var r1 = ibex.stream.url("http://www.ibex.org/foo/bar.html");
- var r2 = ibex.stream.url("http://www.ibex.org/foo")["bar.html"];
- </pre>
-
- </section>
-
- <section title="The Root Stream">
-
- The empty-string property on the <t>ibex</t> object is called the
- <i>root stream</i>. You can access this object as <t>ibex..</t> or
- <t>ibex[""]</t>. Additionally, any expression which starts with a
- dot is treated as property to be retrieved from the root stream. The
- following three expressions are equivalent:
-
- <pre>
- ibex..foo
- ibex[""].foo
- .foo
- </pre>
-
- </section>
-
- <section title="Static Blocks">
-
- You can access variables within the static block of a template by
- appending a double period (<t>..</t>) and the variable name to the
- stream used to load that template:
-
- <pre>
- <!-- org/ibex/themes/monopoly/scrollbar.ibex -->
- foo = 12;
- ...
- // elsewhere
- ibex.log.print(org.ibex.themes.monopoly.scrollbar..foo); // prints "12"
- </pre>
-
- </section>
-
- <section title="Formatting Streams">
-
- If you attempt to send a stream as part of an XML-RPC call, the
- stream will be read in its entirity, Base64-encoded, and transmitted
- as a <t><base64/></t> element.
-
- Ibex supports two special URL protocols. The first is <t>data:</t>,
- which inteprets the rest of the URL as a Base64 encoded sequence of
- bytes to use as a source. The other is <t>utf8:</t> which
- interpretets the rest of the string as a Unicode character sequence to
- be UTF-8 encoded as a string of bytes to use as a source.
-
- <pre>
- var r5 = ibex.stream.url("data:WFWE876WEh99sd76f");
- var r6 = ibex.stream.url("utf8:this is a test");
- </pre>
-
- You can read a UTF-8 encoded string from a stream like this:
-
- <pre>
- var myString = ibex.stream.fromUTF(ibex.stream.url("utf8:this is a test"));
- </pre>
- You can also parse XML from a stream using SAX like this:
-
- <pre>
- ibex.stream.xml.sax(
- ibex.stream.url("http://foo.com/foo.xml"),
- { beginElement : function(tagname, attributeKeyValuePairs) { ... },
- endElement : function(tagname) { ... },
- content : function(contentString) { ... }
- whitespace : function(whitespaceString) { ... }
- });
- </pre>
-
- </section>
-
- </section>
-
-<!-- ----------------------------------------------------------------------- -->
-<section title="The Ibex object">
-
- The <t>ibex</t> object is present in the top-level scope of every
- script. It has the following properties:
-
- <heading title="General"/>
-
- <property name="ibex.box">
- reading from this property returns a new box
- </property>
- <property name="ibex.clone(o)">
- creates a clone of object
- </property>
- <property name="ibex.bless(s)">
- returns a blessed clone of stream
- </property>
-
- <heading title="ECMA Library Objects"/>
-
- <property name="ibex.date">
- reading from this property returns a new date
- </property>
- <property name="ibex.math">
- this object contains the ECMA math functions
- </property>
- <property name="ibex.regexp(s)">
- return a regexp object corresponding to string <i>s</i>
- </property>
- <property name="ibex.string">
- this object contains the ECMA string manipulation functions
- </property>
-
- <heading title="Logging"/>
-
- <property name="ibex.log.debug(m, o)">
- log the debug message <i>m</i>, optionally dumping object
- <i>o</i>
- </property>
-
- <property name="ibex.log.info(m, o)">
- log the informational message <i>m</i>, optionally dumping
- object <i>o</i>
- </property>
-
- <property name="ibex.log.warn(m, o)">
- log the warning message <i>m</i>, optionally dumping object
- <i>o</i>
- </property>
-
- <property name="ibex.log.error(m, o)">
- log the error message <i>m</i>, optionally dumping object
- <i>o</i>
- </property>
-
- <heading title="User Interface"/>
-
- <property name="ibex.ui.browser(u)">
- opens a new browser window with URL <i>u</i>
- </property>
-
- <property name="ibex.ui.key.control">
- true if the control key is depressed
- </property>
-
- <property name="ibex.ui.key.shift">
- true if the shift key is depressed
- </property>
-
- <property name="ibex.ui.key.alt">
- true if the alt key is depressed
- </property>
-
- <property name="ibex.ui.key.name.alt">
- the name of the "alt" key (usually either "alt", "meta", or
- "option")
- </property>
-
- <property name="ibex.ui.clipboard">
- the contents of the clipboard; can be read and written to
- </property>
-
- <property name="ibex.ui.maxdim">
- the maximum dimension of any UI element; usually
- 2<sup>31</sup>, but may be smaller
- </property>
-
- <property name="ibex.ui.screen.width">
- the width of the screen, in pixels
- </property>
-
- <property name="ibex.ui.screen.height">
- the height of the screen, in pixels
- </property>
-
- <property name="ibex.ui.mouse.button">
- either 0, 1, 2, or 3, indicating the mouse button currently
- being pressed
- </property>
-
- <property name="ibex.ui.frame">
- when a box is written to this property, it becomes the root
- box of a new window
- </property>
-
- <property name="ibex.ui.window">
- when a box is written to this property, it becomes the root
- box of a new frame
- </property>
-
- <property name="ibex.ui.font.serif">
- an object whose stream is a a builtin serif font
- </property>
-
- <property name="ibex.ui.font.sansserif">
- an object whose stream is a builtin sans-serif font
- </property>
-
- <property name="ibex.ui.font.monospace">
- an object whose stream is a a builtin fixed-width font
- </property>
-
- <heading title="Networking"/>
-
- <property name="ibex.net.http">
- not yet implemented
- </property>
-
- <property name="ibex.net.rpc.xml(u)">
- return an XML-RPC call object with endpoint URL <i>u</i>
- </property>
-
- <property name="ibex.net.rpc.soap(u,">
- return a SOAP call object with endpoint URL <i>u</i>,
- SoapAction <i>a</i>, and XML Namespace <i>n</i>
- </property>
-
- <heading title="Threads"/>
-
- <property name="ibex.thread">
- when a function is written to this property, a new thread is
- forked to call it
- </property>
-
- <property name="ibex.thread.yield()">
- yield the current thread
- </property>
-
- <property name="ibex.thread.sleep(n)">
- sleep for <i>n</i> milliseconds
- </property>
-
- <heading title="Streams"/>
-
- <property name="ibex.stream.url(u)">
- returns a new object whose stream is drawn from URL <i>u</i>
- </property>
-
- <property name="ibex.stream.unzip(s)">
- unpacks a zip archive from <i>s</i>'s stream
- </property>
-
- <property name="ibex.stream.uncab(s)">
- unpacks a cab archive from <i>s</i>'s stream
- </property>
-
- <property name="ibex.stream.cache(s,k)">
- valign=top>wraps a disk-backed read cache keyed on <i>k</i>
- around <i>s</i>'s stream
- </property>
-
- <property name="ibex.stream.watch(s,f)">
- returns an object whose stream is drawn from <i>s</i>'s
- stream, but invokes <i>f(n,d)</i> as it is read from.
- </property>
-
- <property name="ibex.stream.parse.xml(s, h)">
- Use SAX to parse the XML document on stream <i>s</i> with
- handler <i>h</i>
- </property>
-
- <property name="ibex.stream.parse.html(s, h)">
- Same as <t>parse.xml()</t>, but tries to fix broken HTML.
- </property>
-
- <property name="ibex.stream.parse.utf8(s)">
- treat <i>s</i>'s stream as a string encoded as a UTF-8 byte stream and return the string
- </property>
-
- <property name="ibex.stream.homedir">
- <t>ibex.stream.tempdir</t>
- </property>
-
- <heading title="Cryptography"/>
-
- <property name="ibex.crypto.rsa(k,s)">
- <i>not implemented yet:</i> return a
- stream which rsa-decrypts stream <i>s</i> with key <i>k</i>
- </property>
-
- <property name="ibex.crypto.rc4(k,s)">
- <i>not implemented yet:</i> return a
- stream which rc4-decrypts stream <i>s</i> with key <i>k</i>
- </property>
-
- <property name="ibex.crypto.md5(s)">
- <i>not implemented yet:</i> immediately
- MD5-hash stream <i>s</i>
- </property>
-
- <property name="ibex.crypto.sha1(s)">
- <i>not implemented yet:</i> immediately
- SHA1-hash stream <i>s</i>
- </property>
-
-</section>
-<!-- ----------------------------------------------------------------------- -->
-<section title="Traps">
-
- You can add a trap to a property by applying the <t>++=</t> operator
- to a function with one argument. The trap will be invoked whenever
- that property is written to.
-
- <pre>
- <box>
- foo ++= function(z) {
- ibex.log.info("foo is " + z);
- }
- </box>
- </pre>
-
- If another script were to set the property "<t>foo</t>"
- on the box above to the value <t>5</t>, the function above would be
- invoked with the argument <t>5</t>. The function would then log
- the string "<t>foo is 5</t>".
-
- Within a trap, the expression <t>trapee</t> can be used to
- get a reference to the box on which the trap was placed.
-
- The expression <t>trapname</t> returns the name of the
- trap executing the current function. This is useful when a function
- is applied to multiple traps. For example:
-
- <pre>
- <box>
- func ++= function(z) {
- ibex.log.info("called trap " + trapname);
- }
- foo ++= func;
- bar ++= func;
- </box>
- </pre>
-
- <section title="Removing Traps">
-
- You can remove a trap by using the <t>--=</t> operator with the same
- function you added as a trap:
-
- <pre>
- <box>
- var myfunc = function(z) { /* ... */ }
- // add the trap
- func ++= myfunc;
- // ...
- // remove the trap
- func --= myfunc;
- </box>
- </pre>
-
- </section>
-
- <heading title="Multiple Traps on the Same Property"/>
-
- When the property is <i>written</i> to, each of the trap functions placed
- on it will be invoked in the opposite order that they were placed on
- the box -- the most recently placed trap will execute first. This
- last-to-first execution of traps is called <i>cascading</i>. After the
- last trap is invoked, the value is stored on the box (remember, boxes
- are objects, so they can hold properties just like all other
- ECMAscript objects).
-
- <section title="Manual Cascades">
-
- There are two additional tricks you can use when placing traps. The
- first is a <i>manual cascade</i>. If you want to cascade to lower
- traps in the middle of a function, or you want to cascade with a
- different value than the value passed to you (in effect "lying" to
- lower traps), you can use <t>cascade</t>. For example:
-
- <pre>
- <box color="black">
- color ++= function(c) {
- ibex.log.info("refusing to change colors!");
- cascade = "black";
- }
- </box>
- </pre>
-
- This effectively creates a box whose color cannot be changed, and
- which complains loudly if you try to do so.
-
- Do <i>not</i> try to do something like this:
-
- <pre>
- <box color="black">
- color ++= function(z) {
- color = "black"; // INFINITE LOOP! BAD!!!
- }
- </box>
- </pre>
- To prevent automatic cascading, return <t>true</t> from your function:
-
- <pre>
- <box color="black">
- color ++= function(z) {
- return true; // the box's color will not change
- }
- </box>
- </pre>
-
- </section>
-
- <section title="Read Traps">
-
- The other trick is a <i>read-trap</i>. Read traps are just like normal
- traps, except that you use a function that takes zero arguments instead of one. Read traps
- also do not automatically cascade.
-
- <pre>
- <box>
- doublewidth <t>++=</t> function() { return 2 * width; }
- </box>
- </pre>
-
- If another script attempts to read from the <t>doublewidth</t>
- property on this box, the value it gets will be twice the actual width
- of the box. Note that
- the actual <t>doublewidth</t> property on the box never gets written
- to, since the trap does not cascade.
-
- You can manually cascade on read traps as well:
-
- <pre>
- <box>
- text <t>++=</t> function() { return "my text is " + cascade; }
- </box>
- </pre>
-
- Read traps are only rarely needed -- most of the time a write trap
- should be enough.
-
- </section>
-
- <heading title="Prohibited Traps"/>
-
- To prevent confusing and hard-to-debug behaviors, scripts may not
- place traps on any of the properties described in the sections
- <link text="Box Layout Properties" section="Layout Properties"/>, <link
- section="Child-Control Properties"/>, or <link section="Other Box
- Properties"/> except for <t>childadded</t>,
- <t>childremoved</t> and <t>surface</t>. FIXME: remove?
-
- <heading title="Exceptions and Traps "/>
-
- If an uncaught exception is thrown from a trap, Ibex will log the
- exception, but will <i>not</i> propagate it to the code which
- triggered the trap. If the trap was a read trap, the value
- <t>null</t> will be returned.
- FIXME: is this right?
-
- <heading title="Architectural Significance of Traps"/>
-
- Traps are the backbone of Ibex. Since almost all UI programming is
- event/demand driven, traps eliminate the need for separate
- member/getter/setter declarations, often cutting the amount of typing
- you have to do to a third of what it would normally be.
-
- <section title="Cloning">
-
- <i>Cloning</i> is a companion technique for traps; together they can
- be used to simulate any sort of environment you might need. When you
- call <t>ibex.clone(o)</t>, Ibex returns a new object (called the
- <i>clone</i>) which compares with equality (<t>==</t>) to the
- original object. Furthermore, both objects are "equal" as keys in
- hashtables, so:
-
- <pre>
- var hash = {};
- var theclone = ibex.clone(o);
- hash[o] = 5;
- ibex.log.info(hash[theclone]); // prints "5"
- </pre>
-
- Any writes to properties on the clone will actually write to
- properties on the original object, and reads from properties on the
- clone will read properties on the original object. In fact, the only
- thing that can be used to distinguish the original from the clone is
- traps -- a trap placed on the clone is <i>not</i> placed on the
- original object as well.
-
- </section>
-
-
-<!-- ----------------------------------------------------------------------- -->
-<section title="Threads">
-
- <section title="Contexts">
-
- From the perspective of an application writer, Ibex is strictly
- single-threaded. Ibex is always in exactly one of the following three
- <i>contexts</i>:
-
- <list type="unordered">
-
- <b>Rendering Context</b> -- (redrawing the screen)
-
- <b>Event Context</b> (executing javascript traps triggered by an event)
-
- <b>Thread Context</b> (executing a background thread spawned with <t>ibex.thread</t>)
-
- </list>
-
- There are two important restrictions on what can be done in particular contexts:
-
- <list type="unordered">
-
- The <t>box.mouse</t> property and its subproperties
- (<t>x</t>, <t>y</t>, and <t>inside</t>) can only be read
- from within the Event Context, or in a thread context
- <i>after</i> a the <t>box.mouse</t> property on this box or
- an ancestor box has been written to.
-
- Blocking operations (anything that accesses the network or
- disk) can only be performed in the Thread Context.
-
- </list>
-
- </section>
-
- <section title="Background Threads">
-
- Ibex offers easy access to threads. Spawning a background thread is as
- simple as writing a function to the <t>ibex.thread</t> property:
-
- <pre>
- ibex.thread = function() {
- ibex.log.info("this is happening in a background thread!");
- }
- </pre>
-
- The argument set passed to the function is currently undefined and is
- reserved for use in future versions of Ibex. Scripts should not
- depend on the number or content of these arguments.
-
- Ibex is <i>cooperatively multitasked</i>, so threads must not process
- for too long. This was a deliberate choice; cooperatively
- multitasked environments do not require complex locking primitives
- like mutexes and semaphores which are difficult for novices to
- understand. The disadvantage of cooperative multitasking is that one
- thread can hog the CPU. This is unlikely to happen in Ibex for two reasons:
- first, all blocking I/O operations <i>automatically</i> yield the CPU,
- so the overall user interface never becomes unresponsive because it is
- waiting for a disk or network transfer. Second, since Ibex is strictly
- a user interface platform, Ibex scripts are unlikely to perform highly
- compute-intensive operations that keep the CPU busy for more than a
- few milliseconds.
-
- </section>
-</section>
-
-<section title="Events">
-
- Every execution of the Event Context begins with an event, which
- consists of a key/value pair, and a mouse position, which consists of
- an x and y coordinate. The possible keys are <t>_Press[1-3]</t>,
- <t>_Release[1-3]</t>, <t>_Click[1-3]</t>, <t>_DoubleClick[1-3]</t>,
- <t>_Move</t>, <t>_KeyPressed</t>, and <t>_KeyReleased</t>.
-
- Here are two example events:
-
- An event is triggered by writing the key to the value on a box. This
- triggers any trap handlers which may be present. Once these handlers
- have executed, Ibex figures out which child of the current box contains
- the mouse (taking into account that some boxes may cover up others)
- and writes the key and value to that box. If none of the box's
- children contain the mouse position, Ibex removes the leading
- underscore from the key name and writes the value to
- <i>that</i> property. Once all the traps on that property have
- executed, the value is written to the box's parent.
-
- Intuitively, Ibex delivers the underscored event to every box from the
- root to the target, and then delivers the non-underscored event to
- that same set of boxes in reverse order. So the event travels down
- the tree to the target, and then back up to the root. The following
- example prints out "first second third fourth" in that order.
-
- <pre>
- <box>
- _Press1 ++= function(b) { ibex.log.info("first"); }
- Press1 ++= function(b) { ibex.log.info("fourth"); }
- <box>
- _Press1 ++= function(b) { ibex.log.info("second"); }
- Press1 ++= function(b) { ibex.log.info("third"); }
- </box>
- </box>
- </pre>
-
- In general, you should use the <i>non-underscore</i> names to respond
- to user input and use the underscored names when you want to override
- child boxes' behavior or route events to particular boxes (for
- example, when implementing a focus protocol). This is why the
- underscored elements are delivered to parents before children (so
- parents can override their childrens' behavior), but non-underscored
- events are delivered to children before parents (since, visually, a
- mouse click is usually "intended" for the leaf box underneath the
- cursor).
-
- </section>
-
- <heading title="Stopping the Process"/>
-
- At any point in this sequence, a trap handler can choose not to
- cascade (by returning <t>true</t> from the trap handler function).
- This will immediately cease the propagation of the event. This is how
- you would indicate that an event has been "handled".
-
- <heading title="Enter and Leave"/>
-
- Ibex will trigger the <t>Enter</t> and <t>Leave</t> properties as
- it walks down the tree, based on the position of the mouse (or the
- faked position if the <t>mouse</t> property has been written to).
- However, <t>Enter</t> and <t>Leave</t> are not events since they
- do not implicitly cascade up or down the tree.
-
- <section title="Listing of Events">
-
- <property name="Press1 / Press2 / Press3">
- Indicates that the use has pressed a mouse button. On
- platforms with three mouse buttons, the <i>middle</i> button
- is button 3 -- this ensures that applications written to only
- use two buttons (1 and 2) will work intuitively on three button
- platforms.
- </property>
-
- <property name="Release1 / Release2 / Release3">
- Indicates that the use has released a mouse button.
- </property>
-
- <property name="Click1 / Click2 / Click3">
- Indicates that the user has pressed and released the
- mouse button without moving the mouse much (exactly how
- much is platform-dependent).
- </property>
-
- <property name="DoubleClick1 / DoubleClick2 / DoubleClick3">
- Indicates that the user has clicked the
- mouse button twice within a short period of time (exactly how long is platform-dependent).
- </property>
-
- <property name="Move">
- Indicates that the mouse has moved while within this box, or that
- the mouse while outside this box <i>if a button was pressed while within this box and has not yet been released</i>
- </property>
-
- <property name="KeyPressed KeyReleased">
- A string is written to this property when a key is pressed or
- released If the key was any other key, a multi-character
- string describing the key will be put. For simplicity, we use
- the VK_ constants in the <link
- url="http://java.sun.com/products/jdk/1.1/docs/api/java.awt.event.KeyEvent.html#VK_0"
- text=" Java 1.1 API java.awt.event.KeyEvent class"/>. When a
- key is pressed or released, the string put will be the portion
- of its VK_ constant after the underscore, all in lower case.
- If the shift key was depressed immediately before the event
- took place, then the string will be capitalized. Special
- keynames are also capitalized; shift+home is reported as
- "<t>HOME</t>". Symbols are capitalized as they appear on the
- keyboard; for example, on an American QWERTY keyboard, shift+2
- is reported as "<t>@</t>". If the alt, meta, or command key
- was depressed immediately before this key was pressed, then
- the string will be prefixed with the string "<t>A-</t>". If
- the control key was depressed while this key was pressed, then
- the string will be prefixed with the string "<t>C-</t>". If
- both alt and control are depressed, the string is prefixed
- with "<t>C-A-</t>". Ibex does not distinguish between a key
- press resulting from the user physically pushing down a key,
- and a 'key press' resulting from the keyboard's typematic
- repeat. In the rare case that an application needs to
- distinguish between these two events, it should watch for
- KeyReleased messages and maintain an internal key-state
- vector.
- </property>
-
- </section>
-
-</section>
-
-<!-- ----------------------------------------------------------------------- -->
-<section title="Networking">
-
- <section title="XML-RPC">
-
- XML-RPC objects can be created by calling <t>ibex.net.rpc.xml(<i>XML-RPC
- URL</i>)</t>, and then invoking methods on that object. For example,
-
- <pre>
- Press1 += function(v) {
- ibex.thread = function() {
- color = ibex.net.rpc.xml("http://xmlrpc.ibex.org/RPC2/").
- color.getTodaysColor("Friday");
- }
- }
- </pre>
-
- When the user clicks the first mouse button on this box, it will
- contact the server <t>xmlrpc.ibex.org</t>, route to the
- <t>/RPC2/</t> handler and invoke the <t>getTodaysColor()</t>
- method on the <t>color</t> object with a single string argument
- "<t>Friday</t>". The return value will be used to change the color
- of the box the user clicked on.
-
- Note that in this example we spawned a background thread to handle the
- request -- the <t>Press1</t> event is delivered in the foreground
- thread, and XML-RPC methods may only be invoked in background
- threads. This is to prevent the UI from "locking up" if the server
- takes a long time to reply.
-
- If the XML-RPC method faults, an object will be thrown with two
- properties: <t>faultCode</t> and <t>faultString</t>, as defined in
- the <link url="http://www.xmlrpc.org/spec" text="XML-RPC specification"/>. If
- Ibex encounters a network, transport, or session-layer error, it will
- throw a <t>String</t> object describing the error in a
- human-readable format. Scripts should not rely on the contents of
- this string having any special structure or significance.
-
- If an object with an associated non-empty stream is passed as an
- argument to an XML-RPC method, it will be sent as a <base64/>
- element. If a <base64/> element is found in the XML-RPC reply, it
- will be returned as an object with a stream drawn from that byte sequence.
-
- Each object returned by <t>ibex.net.rpc.xml()</t> represents a
- single HTTP connection. The connection will be held open until
- the object is garbage collected or the server closes the
- connection. If a second call is issued on the object before the
- first one returns (usually from a seperate thread), the two calls
- will be <link
- url="http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.1.2.2"
- text="pipelined"/>. This can dramatically improve performance.
-
- Ibex supports HTTP Basic and Digest authentication. To use
- authentication, pass <t>ibex.net.rpc.xml()</t> a URL in the form
- <t>http[s]://user:password@hostname/</t>. Ibex will use Digest
- authentication if the server supports it; otherwise it will use
- Basic authentication. Please be aware that many XML-RPC server
- implementations contain a <link
- url="http://www.ibex.org/faq.html#auth" text="broken implementation of Basic authentication"/>.
-
- </section>
-
- <section title="SOAP">
-
- SOAP methods are invoked the same way as XML-RPC methods, but with three differences:
-
- <list type="ordered">
-
- <t>ibex.net.rpc.soap()</t> is used instead of
- <t>ibex.net.rpc.xml()</t>
-
- Instead of specifying just the URL of the service itself, you
- must specify the URL, the SOAPAction argument, and the
- namespace to use.
-
- The actual method invocation takes only one argument, which
- must be an object. This is necessary since SOAP arguments are
- specified by name, rather than ordering.
-
- </list>
-
- SOAP faults are handled the same way as XML-RPC faults except that the
- capitalization of the <t>faultstring</t> and <t>faultcode</t>
- members is all lower-case, to match the SOAP spec. Here is a
- SOAP example:
-
- <pre>
- Press1 ++= function(v) {
- ibex.thread = function() {
- color = ibex.net.rpc.soap("http://soap.ibex.org/SOAP",
- "GETTODAYSCOLOR",
- "http://ibex.org/namespace"
- ).color.getTodaysColor( {
- whichday : Friday
- } );
- }
- }
- </pre>
-
- As you can see, SOAP is much more verbose, yet does not offer
- substantially improved functionality. We recommend that XML-RPC be
- used whenever possible, and that SOAP be reserved for legacy
- applications.
-
- The current Ibex SOAP stack does not support 'document style' or
- multi-ref (<t>href</t>) data structures.
-
- </section>
-
- <section title="Security">
-
- Applications downloaded from the network (as opposed to those loaded
- from the filesystem) may only make certain kinds of connections to
- certain hosts. See Appendix A for a detailed description of the
- security policy.
-
- </section>
-
- </section>
-<!-- ----------------------------------------------------------------------- -->
-<section title="Error Handling">
-
- If the Ibex Core encounters an error while servicing a function call
- originating in JavaScript, the core will throw a string consisting of
- an error code followed by a colon, a space, and a descriptive message.
- For example:
-
- <pre>
- "ibex.net.dns.unknownhostexception: unable to resolve host foo.com"
- </pre>
-
- The code should be used to determine how the program should respond to
- an error. The codes are organized in a hierarchy, so the
- string.startsWith() method can be used to determine if an error lies
- within a particular subhierarchy. The descriptive message portion of
- the string may be shown to the user.
-
- <property name="ibex.assertion.failed">
- an assertion failed
- </property>
- <property name="ibex.io">
- General I/O exceptions
- </property>
- <property name="ibex.io.encoding">
- Error translating between character encodings.
- </property>
- <property name="ibex.io.zip">
- Attempted to access a corrupt zip archive.
- </property>
- <property name="ibex.io.eof">
- End of file encountered unexpectedly
- </property>
- <property name="ibex.net.security.prohibitedHost">
- A piece of untrusted Ibex code attempted to contact a
- restricted host. See <link appendix="Security Architecture and Considerations"/> for details.
- </property>
- <property name="ibex.net.dns.temporaryFailure">
- An attempt to resolve a hostname failed but it is not known
- for certain that the hostname is invalid.
- </property>
- <property name="ibex.net.dns.unknownHost">
- An attempt to resolve a hostname failed because the hostname
- was invalid.
- </property>
- <property name="ibex.net.socket.closed">
- A socket was closed unexpectedly.
- </property>
- <property name="ibex.net.socket.connectionFailed">
- A connection could not be made to the remote host.
- </property>
- <property name="ibex.net.url.malformed">
- Tried to parse a malformed URL.
- </property>
- <property name="ibex.net.ssl">
- General SSL protocol errors.
- </property>
- <property name="ibex.net.ssl.untrustedCertificate">
- The server's certificate was not signed by a CA trusted by Ibex.
- </property>
- <property name="ibex.net.http.">
- Thrown when an HTTP error code is returned during an
- operation. The three characters <t><i>xyz</i></t> will be
- the three-digit HTTP status code.
- </property>
- <property name="ibex.net.xmlrpc.null">
- The caller attempted to transmit the <t>null</t> value via XML-RPC.
- </property>
- <property name="ibex.net.xmlrpc.circular">
- The caller attempted to transmit a circular data structure via XML-RPC.
- </property>
- <property name="ibex.net.xmlrpc.specialObject">
- The caller attempted to transmit a "special" object via
- XML-RPC (for example, a Box or the Ibex object).
- </property>
- <property name="ibex.null.put">
- A JavaScript attempted to put to a property on the <t>null</t> value
- </property>
- <property name="ibex.null.get">
- A JavaScript attempted to get from a property on the <t>null</t> value
- </property>
- <property name="ibex.null.call">
- A JavaScript attempted to call the <t>null</t> value
- </property>
-
- If an exception is thrown inside a trap, the exception will propagate
- to the script that triggered the trap.
-
- If an uncaught exception is thrown while applying a template, or the
- requested template could not be found, an error will be logged and the
- box to which the template was being applied will be made invisible
- (<t>visible = false</t>). This ensures that half-applied widgets are
- never shown to the user.
-
- </section>
-
-<!-- ----------------------------------------------------------------------- -->
-<section title="Advanced Topics">
-
- <section title="Re-routing events">
-
- At any point in the Event Context, you can write to the <t>mouse</t>
- property on any box. The value written should be an object with two
- properties, <t>x</t> and <t>y</t>. For example:
-
- <pre>
- _Press1 ++= function(p) {
- mouse = { x: 32, y: 77 };
- }
- </pre>
-
- The coordinates specified are relative to the box whose <t>mouse</t>
- property is being written to. There is no need to supply the
- <t>inside</t> property; it is computed automatically. Writing to
- the <t>mouse</t> property causes Ibex to recompute the eventual
- target box, and also alter the values returned by <t>mouse.x</t>,
- <t>mouse.y</t>, and <t>mouse.inside</t> for any <i>descendants</i>
- of the current box. Writing to the <t>mouse</t> property also
- automatically prevents the event from returning to the box's parents
- -- it is equivalent to not cascading on the non-underscored event.
- This ensures that child boxes cannot trick their parent boxes into
- thinking that the mouse has moved.
-
- If you want the event to "skip over" the boxes between the trapee
- and the target, or if you want to re-route an event to a box which
- is not a descendant of the current box, simply write the value to
- the proper key on the target box.
-
- <pre>
- <box>
- _KeyPressed = function(k) { ibex.log.info("first"); }
- KeyPressed = function(k) { ibex.log.info("sixth"); }
- $recipient.target = $target;
- <box id="recipient">
- _KeyPressed = function(k) {
- ibex.log.info("second");
- thisbox.target.KeyPressed = k;
- // inhibit cascade; keep event from going to $excluded
- return true;
- }
- KeyPressed = function(k) { ibex.log.info("fifth"); }
- <box id="excluded">
- _KeyPressed = function(k) {
- ibex.log.info("this never happens");
- }
- </box>
- </box>
- <box id="target">
- _KeyPressed = function(k) { ibex.log.info("third"); }
- KeyPressed = function(k) { ibex.log.info("fourth"); }
- </box>
- </box>
- </pre>
-
- </section>
-
- <section title="Synthesizing Your Own Events">
-
- You can create "fake events" by simply writing to the <t>mouse</t>
- property and then writing a value to one of the underscored properties
- on a box. This will have exactly the same effect as if the use had
- actually pressed a key, clicked a button, or moved the mouse -- they
- are indistinguishable.
-
- </section>
-
- <section title="Ibex self-emulation">
-
- When the core first starts up, it clones the <t>ibex</t> object,
- creates a stream for the initial .ibex, and then places a trap on the
- cloned <t>ibex</t> object so that its empty-string property returns
- the .ibex stream. The cloned Ibex object is then passed as the third
- (optional) argument to <t>ibex.apply()</t>, making it the default
- <t>ibex</t> object for the scripts that are executed as part of the
- template instantiation.
-
- <pre>
- var new_ibex = ibex.clone(ibex);
- var stream = ibex.bless(ibex.stream.url("http://..."));
- new_ibex[""] ++= function() { return stream; }
- ibex.apply(ibex.box, new_ibex..main, new_ibex);
- </pre>
-
- Note that we called <t>ibex.bless()</t> on the stream before tacking
- it on to the new Ibex object. The bless function returns a clone of
- the object passed to it, with a few traps which are explained below.
- Additionally, any sub-streams retrieved by accessing properties of the
- blessed stream will also automatically be blessed (blessed streams are
- <i>monadic</i>).
-
- Blessing a stream serves three purposes:
-
- <list type="unordered">
-
- Blessed clones always return the appropriate static block when
- their empty property is accessed; this ensures that references
- to the static blocks of other templates work properly.
-
- Blessed substreams can return their parent stream by accessing
- a hidden property which is reserved for internal use by Ibex.
- This ensures that Ibex can automatically add filename
- extensions where needed, according to the following rules:
-
- <list>
- If the stream is a template to be applied, the string
- "<t>.ibex</t>" is appended.
-
- If the stream is an image, the string "<t>.png</t>" is
- appended. If no stream is found, "<t>.jpeg</t>" and
- "<t>.gif</t>" are tried, in that order.
-
- If the stream is an font, the string "<t>.ttf</t>" is
- appended.
- </list>
-
- Every call to <t>ibex.bless()</t> returns a different object
- (which happens to be a clone of the object passed to it) with
- a completely separate set of static blocks.
-
- </list>
-
- Ibex can self-emulate by using <t>ibex.clone()</t> on the Ibex object;
- this technique is very similar to the use of ClassLoaders in
- Java. This is useful for a number of applications, including
- debuggers, IDEs, sandboxing untrusted code, remote-control, and
- others. For example:
-
- <pre>
- var newLoadFunction = function(url) { /* ... */ };
- var new_ibex = ibex.clone(ibex);
- new_ibex.load ++= function() { return newLoadFunction; }
- ibex.apply(ibex.box, .main, new_ibex);
- </pre>
- </section>
-</section>
-
-<!-- ----------------------------------------------------------------------- -->
-<appendix title="Security Architecture and Considerations">
-
- Due to the expense and hassle imposed by the commercial PKI code
- signing architecture, and the fact that it <link
- url="http://www.counterpane.com/pki-risks-ft.txt" text="doesn't
- really provide any security anyways"/>, Ibex user interfaces are
- distributed as unsigned, untrusted code. As such, they are handled
- very carefully by the Ibex Core, and assumed to be potentially
- malicious.
-
- Ibex's security architecture is divided into defenses against four
- major classes of attacks:
-
- <heading title="Malicious UI attempts to acquire or alter data on the client"/>
-
- Ibex user interfaces are run in an extremely restrictive sandbox. The
- environment does not provide primitives for accessing any data outside
- the Ibex core except via XML-RPC and SOAP calls. There are no
- facilities to allow Ibex user interfaces to access the client's
- operating system or to interact with other applications on the same
- host (unless they provide a public XML-RPC or SOAP interface).
- An Ibex script may only access a file on the user's hard disk if the
- user explicitly chooses that file from an "open file" or "save file"
- dialog. There is one exception to this rule: if all templates
- currently loaded in the Ibex core originated from the local
- filesystem, those templates can load additional .ibexs from the local
- filesystem.
-
- The Ibex Core is written in Java, so it is not possible for
- scripts to perform buffer overflow attacks against the core
- itself.
-
- Ibex applications may only read from the clipboard when the user
- middle-clicks (X11 paste), presses control-V (Windows paste), or
- presses alt-V (Macintosh paste; the command key is mapped to Ibex
- "alt"). This ensures that Ibex applications are only granted access to
- data that other applications have placed on the clipboard when the user
- specifically indicates that that information should be made available
- to the Ibex application.
-
- <heading title="Malicious UI attempts to use client to circumvent firewalls"/>
-
- Ibex user interfaces may only make XML-RPC or SOAP calls and load .ibex
- archives via HTTP; they cannot execute arbitrary HTTP GET's or open
- regular TCP sockets.
-
- Ibex will not allow a script to connect to a non-public IP address
- (10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16, as specified in <link
- url="http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc1918.html" text="RFC
- 1918"/>). There is one exception -- if all templates currently loaded
- in the core originated from the same IP address, those scripts may
- make calls to that IP address regardless of whether or not it is
- firewalled. If Ibex does not have access to a DNS resolver (because it
- is using a proxy which performs DNS lookups), Ibex will provide the
- proxy with the appropriate <link
- url="http://www.ibex.org/x-requestorigin.html"
- text="X-RequestOrigin"/> header that the proxy needs in order
- to maintain security.
-
- The only remaining possible attack is against a XML-RPC or SOAP
- service running on a firewalled host with a public address. Assigning
- such machines public IP addresses is a poor network security policy,
- and doing so squanders scarce public IPv4 addresses. As such, the onus
- is on the administrators of such machines to explicitly block access
- to clients reporting a <t>User-Agent:</t> header beginning with the
- three characters "<t>Ibex</t>".
-
- <heading title="Malicious UI attempts to trick user into divulging secret information"/>
-
- All top-level windows created by Ibex are <i>scarred</i> -- a stripe
- and a lock is drawn across the corner of the window. There is no way
- for a user interface to remove this scar. Ibex user interfaces may not
- create windows smaller than the size of the scar.
-
- <heading title="Malicious network attempts to snoop or man-in-the-middle transactions"/>
-
- Ibex user interfaces may transmit network data using HTTPS (SSL 3.0)
- for encryption. Ibex will attempt 128-bit encryption, but will
- negotiate down to 40-bit if the server does not support strong
- crypto. Ibex's SSL implementation is currently provided by <link
- url="http://www.ibex.org/tinyssl" text="TinySSL"/> and <link
- url="http://www.bouncycastle.org" text="The Legion of the Bouncy
- Castle."/>
-
- All HTTPS connections must be authenticated by the server using a
- certificate whose name matches the domain name of the HTTPS URL. The
- certificate must be signed by a trusted root CA. Ibex trusts the same
- 93 root CAs whose certificates are included as "trusted" in Microsoft
- Internet Explorer 5.5 SP2. This provides a minimal level of protection
- against man-in-the-middle attacks; you should not trust this
- connection with any data you would not normally trust an SSL-enabled
- web browser with.
-
-</appendix>
-
-<!-- ----------------------------------------------------------------------- -->
-<appendix title="ECMAscript compliance">
-
- Ibex's scripts are written in a modified subset of ECMA-262, revision 3
- (aka JavaScript 1.5). The interpreter strays from the spec in a few
- ways.
-
- <section title="Omissions">
-
- The following ECMA features are not supported:
-
- <list type="unordered">
-
- The <t>undefined</t> value, <t>===</t>, and <t>!==</t>
-
- The <t>new</t> keyword (and ECMAScript object inheritance)
- <t>eval</t>
-
- <t>getter</t> and <t>setter</t>
-
- The ECMA <t>this</t> keyword.
-
- The <t>String</t>, <t>Number</t>, and <t>Boolean</t>
- classes. Note that <t>string</t>, <t>number</t>, and
- <t>boolean</t> values are supported, however.
-
- You may not <t>throw</t> the <t>null</t> value.
-
- </list>
-
- Additionally, you must declare all root-scope variables (with
- <t>var</t>) before using them; failure to do so will result in an
- exception. Box properties are pre-defined in the scope that scripts
- are executed in.
-
- </section>
-
- <section title="Extensions">
-
- <list type="unordered">
-
- The token <t>..</t> is equivalent to <t>[""]</t>.
-
- Trapping
-
- Cloning
-
- Extended <t>catch</t> syntax. The following code:
- <pre>
- } catch(e propname "foo.bar.baz") {
- // ...
- }
- </pre>
- Is equivalent to:
- <pre>
- } catch(e) {
- if (e.propname != null and e.propname >= "foo.bar.baz" and
- "foo.bar.baz/" > e.propname) {
- // ...
- }
- }
- </pre>
- Multiple extended-catch blocks can appear at the end of a single try
- block. However, at most one non-extended catch block may appear, and
- if it does appear, it must be the last one.
-
- Since Ibex ECMAscripts are wrapped in XML, the lexical token
- "<t>lt</t>" is be interpreted as <t><</t>, the lexical
- token "<t>gt</t>" is be interpreted as <t>></t>, and the
- token "<t>and</t>" is interpreted as <t>&&</t>.
- Thus these tokens cannot be used as variable names.
-
- The identifier <t>static</t> is a reserved word in
- ECMAScript, but not in Ibex.
-
- Ibex defines an additional reserved word, "<t>assert</t>",
- which will evaluate the expression which follows it, throwing
- a <t>ibex.assertion.failed</t> exception if the expression
- evaluates to <t>false</t>.
-
- To ensure that Ibex files appear the same in all text editors, tab
- characters are not allowed in Ibex files.
-
- </list>
-
- Some useful tutorials include:
-
- <list type="unordered">
-
- Netscape's <link
- url="http://developer.netscape.com/docs/manuals/communicator/jsref/index.htm"
- text=" JavaScript 1.2 Reference"/>. Although this document is
- out of date, it is arguably the best guide available for free
- on the Internet. The changes from JavaScript 1.2 (aka ECMA-262
- r1) to 1.5 were minimal, and many of them were <link
- url="ecmascriptcompliance" text="omitted"/> from Ibex.
-
- O'Reilly's <link
- url="http://search.barnesandnoble.com/booksearch/isbnInquiry.asp?isbn=0596000480"
- text=" JavaScript: The Definitive Guide"/>, by David Flanagan
- and Paula Ferguson. The latest edition of this book covers
- JavaScript 1.5 (ECMA-262 r3).
-
- The official <link
- url="http://www.ecma.ch/ecma1/STAND/ECMA-262.HTM"
- text="ECMA-262"/> specification. This is an extremely
- technical document.
-
- </list>
- </section>
-</appendix>
-
-<!-- ----------------------------------------------------------------------- -->
-<appendix title="Logging and Command Line Invocation">
-
- Very early in the loading process, Ibex begins logging messages about
- what it is doing. Where this output is logged to differs by platform;
- currently it goes to standard output when running inside a JVM, and to
- <t>$TMPDIR\ibex-log.txt</t> on Win32 (where <t>$TMPDIR</t> is the
- value returned by <t>GetTempPath()</t>). The logs contain a lot of
- valuable debugging information and performance hints; if you are
- having trouble developing an Ibex application, be sure to check the
- logs.
-
- If Ibex encounters a serious problem before it starts logging
- information, or if it is unable to open the log file, it will abort
- immediately with a critical abort, which will be displayed on the
- console for POSIX-native cores and in a dialog box for JVM-based and
- Win32-native cores.
-
- You can invoke Ibex directly from the command line during
- development. When using a JVM, the invocation format is:
-
- <pre>
- java -jar path-to-ibex-jar [-sv] source-location [initial-template]
- </pre>
-
- Where <t><i>path-to-ibex-jar</i></t> is the path to <t>ibex.jar</t>,
- which can be downloaded <link url="http://www.ibex.org/dist/ibex.jar" text="here"/>.
-
- On Win32, the invocation format is:
-
- <pre>
- ibex.exe [-v] source-location [initial-template]
- </pre>
-
- The file <t>ibex.exe</t> is placed in Windows' ActiveX cache
- directory the first time Ibex is used on the machine. The ActiveX
- cache location depends on what version of Windows you are using;
- on newer versions of Windows it is <t>C:\WINDOWS\DOWNLOADED
- PROGRAM FILES\</t>. You can also extract <t>ibex.exe</t> from
- <t>ibex.cab</t>, which is available <link
- url="http://www.ibex.org/dist/ibex.cab" text="here"/>.
-
- The <t><i>source-location</i></t> parameter can be either the path
- to an .ibex archive, the http url of an .ibex archive, or the path to a
- directory comprising an unpacked .ibex archive.
-
- The <t><i>initial-template</i></t> parameter is the stream name of
- a template to be used as the initial template. If ommitted, it
- defaults to <t>main</t>.
-
- The <t>-v</t> option causes Ibex to enable verbose logging; this will
- cause it to log <i>lots</i> of information to the log file. This
- option will also substantially decrease Ibex's performance.
-
- </appendix>
-
-<!-- ----------------------------------------------------------------------- -->
- <!--
-<appendix title="Grammars">
-
- <i>Grammar support is experimental in this release
- and may not work properly. It may change in incompatible ways or
- disappear completely from future releases</i>
-
- Grammars are defined with a statement in the following form:
-
- <pre>
- a ::= b { c }
- </pre>
- A grammar is really just another function; once defined you can't tell
- it apart from an ordinary function. A grammar takes one argument,
- which can be a string or stream. The argument is parsed and the
- result of executing the code block 'c' is returned.
-
- The property 'a' is read; if the value is a grammar, a new production
- rule (ie a new alternative, as with '<t>|</t>') is added to that grammar
- (this is a destructive update). This allows you to add productions to
- pre-existing grammars (for example, adding a new type of expression to
- a programming language by extending the 'expr' grammar). If the old
- value is not a grammar, the value is discarded and a new grammar
- object is created.
-
- The value 'b' is a pattern, which may consist of seven simple
- primitives:
-
- <list type="unordered">
- string literals
-
- grouping parens <t>()</t>
-
- combinators: <t> | + * ?</t>
-
- references to other grammars
- </list>
-
- The value 'c' and the braces surrounding it are an *optional* code
- block, in which the following identifiers are bound:
-
- <list type="unordered">
-
- The identifier 'whole' is bound to the string matched by the
- entire expression. If the code block is omitted it behaves
- as if it were "<t>{ return whole; }</t>".
-
- For every reference to another grammar which was matched in the
- pattern, the *name used to reference that other grammar* will
- be bound to the value returned by its code block. Here's an
- example of this important distinction:
-
- <pre>
- var foo ::= 'a' | 'b';
- var bar ::= foo;
- var baz ::= 'c' | bar { /* foo is not defined here, but bar is */ };
- </pre>
-
- On the last line, the identifier 'bar' serves two purposes: it
- pulls in the definition of the pattern *and* acts as a binder
- within the scope of the braces.
-
- If a reference is matched multiple times (either because it
- appears multiple times in the pattern or because the * or +
- operator was applied to it) then its name will be bound to an
- array containing the matches.
-
- </list>
-
- Here is the metacircular definition of the grammar facility:
-
- <pre>
- grammar ::= identifier '::=' pattern (';' | '{' code '}' ';'?)
- identifier ::= ('a'..'z' | 'A'..'Z' | '_' | '$') (identifier | '0'..'9')*
- char ::= '\0x0000'..'\0xffff'
- literal ::= '\'' char+ '\''
- | '\'' char '\'' '..' '\'' char '\''
- pattern ::= identifier
- | literal
- | '(' pattern ')'
- | pattern '+'
- | pattern '?'
- | pattern '*'
- | pattern pattern
- | pattern '|' pattern
- </pre>
- -->
-
-<i>
-Copyright (C) 2004 Adam Megacz, verbatim redistribution permitted.
-Ibex is a trademark of Adam Megacz
-</i>
-
-</ibex-doc>
\ No newline at end of file