X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=doc%2Freference%2Freference.xml;h=37148d6e4e650186d9c48fc08de526544594220f;hb=c73e5d8c4f7487b4b1fef34c0b70521f033882fb;hp=844bad61a0c47f32acdb2934b9b50da2990b53cc;hpb=ff2b086d176f8b2323bfd73fb4830cd237b7fa6c;p=org.ibex.core.git diff --git a/doc/reference/reference.xml b/doc/reference/reference.xml index 844bad6..37148d6 100644 --- a/doc/reference/reference.xml +++ b/doc/reference/reference.xml @@ -1,34 +1,120 @@ - +
- ** - 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 produced - with LaTeX. - ** + + ** 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 produced ** + ** with LaTeX. ** + + Ibex is a software platform based on the philosophy that the most + useful systems consist of both **statically typed** and + **dynamically typed** languages, working in concert. + + + + - Statically typed languages (such as Java) are well suited for + high-performance, reliable, reusable code. Unfortunately + programs written in statically typed languages often take + longer to develop, and their commitment to a specific type + system makes interoperating with other languages cumbersome. + + - Dynamically typed languages (such as JavaScript) typically + perform poorly (due to runtime checks and inadequate static + information for optimization), tend to admit more errors (due + to less static checking), and export APIs which are not + precisely defined (due to the huge number of possible + type/method combinations). However, writing programs in + dynamically typed languages is a much more rapid process, and + the implicit coercions in such languages make interoperability + between similar languages very easy. + + + + The architectural incarnation of this philosophy is the Ibex Object + Model, a universal interface to dynamically typed languages. The + IOM serves as a common interface between statically typed languages + and dynamically typed languages both locally and over the network. + +
- This document is a __reference__. It is not a - __specification__ or a - __tutorial__. + The Ibex Object Model consists of three primitive types: + + + - __number__ -- a floating point number + - __string__ -- a unicode string + - __boolean__ -- either [[true]] or [[false]] + + + From these primitives, more complex structures can be built from + two aggregate types: + + + - __array__ -- a collection of objects indexed by a non-negative integer + - __hash__ -- a collection of objects indexed by objects (often strings) + - 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). + Any of the following actions can be performed on an object: - 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. + + - __get(key)__ -- attempts to retrieve the object indexed by + [[key]]. Returns an object. + + - __put(key, val)__ -- attempts to add object [[val]] with key + [[key]] to an object. Does not return a value. + + - __call(args)__ -- attempts to call the object as if it were a + function. The [[args]] value is a list of arguments. May or + may not return a value. + - 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 . + The keys of some objects may be enumerated by attempting to "call" + the object; the return value will be an array of the object's keys. + + Finally, an object may be **coerced** to any of the three + primitive types, although this coercion may fail. Objects may + also be coerced to the **bytestream** type, which represents an + unbounded stream of octets. Dynamically typed code may not + explicitly manipulate bytestreams, although it can pass objects + to statically typed code which in turn coerces those objects to + bytestreams. + Any of the above operations may **throw** an exception, which is + itself an object. + + Any entity in the statically typed world which supports these + operations may expose itself to the dynamically typed world. + Furthermore, it can expect that any values passed to it will support + all of the operations shown above. +
+ +
+ - relation to XML + - cover templates here with David's isomorphism? +
+ +
+ + The remainder of this document describes the three major + systems founded on the Ibex Object Model: + + + - The Ibex User Interface + - The Ibex Persistent Storage Service + - The Ibex Mail Server + - IbexDoc + + + Currently, all four of these systems use Java as the statically + typed language and IbexScript (a derivitave of JavaScript) as + the dynamically typed language. However, since they interact + strictly via the Ibex Object Model, either component can be + rewritten in a different language. + +
+
@@ -80,32 +166,34 @@
+
+
A user typically begins an Ibex session by clicking on a link to - an Ibex application. This link serves the {\tt launch.html} file - to the user's browser, which in turn downloads the appropriate - {\it Wildebeest} -- currently either an ActiveX Control + an Ibex application. This link serves the [[launch.html]] file + to the user's browser (1), which in turn downloads the appropriate + **Wildebeest** (2)-- currently either an ActiveX Control (Win32/MSIE), XPInstaller (Mozilla), or Signed Applet (all others). The Wildebeest downloads the appropriate core for the user's - machine and verifies its digital signature. It then launches the - core, which downloads the UI (an [[.ibex]] archive), loads it, - applies the [[main.t]] template (found in the archive), and - renders it onto the screen, running any associated JavaScript - code. + machine and verifies its digital signature (3). It then launches + the core, which downloads the UI (4), (an [[.ibex]] archive), + loads it, applies the [[main.t]] template (found in the archive), + and renders it onto the screen, running any associated JavaScript + code (5). 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. + mouse, and by pressing keys on the keyboard (5). 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 (5), or it + can modify the structure and properties of the user interface to + change its appearance, thereby giving feedback to the user. The Ibex core quits when the last remaining surface has been destroyed. @@ -164,16 +252,15 @@ of Ibex.
-
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 **applying**, since unlike - **instantiation** in object-oriented programming systems, you - always apply a template to a pre-existing box, and you can apply - multiple templates to the same box. + construction process **applying**, since unlike **instantiation** in + object-oriented programming systems, 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 [[scrollbar]] @@ -255,8 +342,7 @@ and written) from both static scripts as well as instance scripts in a particular template. FIXME - -
+
@@ -400,68 +486,317 @@
-
+
-
- - 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 [[clip]] attribute is [[false]], 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. - - Each box has two major visual components, each with subcomponents: + FIXME: needs way, way, way more diagrams of nonrectangular boxes. + + Each box occupies a region on the surface. The visual + appearance of a surface is created by rendering each box in its + tree. Unless the [[clip]] attribute is [[false]], 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. - FIXME: diagram + + + Until now we've tactily assumed that boxes are rectangular. In + fact, unlike its predecessor (XWT), Ibex boxes can be **any + shape at all**. We refer to the outline of a box as its path, + which may be composed of lines and curves (arcs and splines). + If the path is not set (or set to [[null]]), the box's path is + **implicitly** a rectangle. + + A key step in understanding how Ibex works, and understanding + how operations on rectangular boxes generalize to arbitrary + boxes is to realize that "the path **is** the box". Just as a + rectangular box clips its children to the inside of the + rectangle, a circular box will clip its children to the inside + of the circle. + + In fact, Ibex's integration of vector graphics with + constraint-based user interface layout runs quite deep -- boxes + which "contain" text are actually boxes whose outline path + **is** the actual letters of the text. This means that you can + assign children to a text-shaped box, and the children's + appearance will be cliped to the **inside** of the text letters. + + The only time rectangular and non-rectangular boxes act + differently is when box packing takes place; when packing boxes, + Ibex only looks at the **bounding box** of a path (the smallest + rectangle that completely encloses the box's path). In the case + of rectangular boxes (which have not been rotated or sheared), + this bounding box happens to be exactly the same as the box's + path. So Ibex is actually treating these boxes the same, but + the chosen treatment favors rectangular boxes. + +
+ + The appearance of a box consists of three visual elements: its + path, stroke, and fill. - - - A box's [[path]] 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. [**Note: Vector Graphics support (including the ability - to set the [[path]] property to anything other than the - default) is currently not implemented**]. - - A path also has: - - - an associated [[strokecolor]], which is a color - - an associated [[strokewidth]], which is a number - specifying the width of the stroke. [**Note: Vector - Graphics support (including the [[strokewidth]] - property) is currently not implemented**] - - a [[fill]], which is either a color, gradient, or - texture - - - - - - Each box also has a single line of [[text]], whose - appearance is determined by its: - - - associated [[font]], which can be any font supported by - the - library. - - an associated [[fontsize]] in **pixels** - - an associated [[textcolor]] - - - - 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. -
+ + A box's [[path]] consists of zero or more contours, each of + which consists of one or more lines, bezier curves (cubic or + quadradic), or generalized elliptic arcs. The grammar and + feature set supported are identical to that specified in . + + One of the most common sources of frustration when working with + text representations of vector paths, or programs that manipulate + them, is making a mistake when setting a transform which causes + the entire path to be off the screen. Since no part of the path + is visible, you have no idea which direction it went! To minimize + the chance of this happening, and generally make dealing with + vectors a more enjoyable experience, Ibex always **recenters** a + path. When you set a box's path (either by writing to its + [[path]] or [[text]] properties), Ibex translates the entire path + so that it is lined up with the X and Y axes, as close to the + origin as possible, in the positive-X, positive-Y quadrant. Ibex + will note this translation by setting the box's [[transform]] to + the transformation used to do this. If you do not desire this + behavior, just set the [[transform]] back to the identity + transform. + + + + The color with which to stroke the path. Ibex paths may + only be stroked with a single color, solid line (not + dashed), of "hairline width" (meaning that the line is never more than one + antialiased pixel wide no matter what magnification it is + viewed at). + + This property can be set to a 5-character hex string + ([[#RGB]]), 7-character hex string ([[#RRGGBB]]), + 9-character hex string ([[#AARRGGBB]]), specifying the box's + hexadecimal color. Any other string is compared against the + colors (the same set of color names supported + by SVG). If this property is set to [[null]], the stroke + color will be set to clear ([[#00000000]]). + + Other vector formats (notably SVG and PDF) support "thick" + lines, dashed lines, lines stroked with a gradient or + texture, and an assortment of special caps and joins for + these thick lines (hairline lines do not need joins or + caps). Fortunately, all of these constructs can be + converted into **filled** paths rather easily, making it + possible for Ibex to support the same functionality with a + much simpler API (and more efficient rendering engine). + + + + The graphic element with which to fill the path. This + property can be set to any of the values specified for + [[stroke]], as well as to a texture (an image) or a + gradient. Paths which self-intersect are filled according + to the SVG guidelines. + + When an image (texture) is written to this property, the + box's [[minwidth]] and [[minheight]] properties will be + automatically set to the dimensions of the image (they can + be changed later if desired). + +
+ +
+ + Ibex treats text exactly the same way it treats other paths. + Writing to the [[text]] property actually sets the box's path to + the outline of the rendered form of the text, and text is + subject to the same rotation, shearing, and scaling + transformations as all other boxes. You can even **read back** + the curves from which the text is composed by reading from the + [[path]] property (the string returned will be in SVG Path + syntax), modify it, and write it to the [[path]] property of + another box. + + + The box's text; writing [[null]] to this property sets it to + [[""]]. In order to help eliminate common chores when working + with text, Ibex will automatically take the following actions + when you write to the [[text]] property: + + + + The text is converted to curves using the Freetype library, + and the resulting curve becomes the box's path. + + If the box's [[strokecolor]] is [[null]], it is set to black + ([[#FF000000]]). When first created, a box has an invisible + stroke; automatically setting the stroke to a visible color + helps eliminate confusing errors. You can change the stroke + color back to clear after writing to the [[text]] property. + + The box's [[aspect]] property is automatically set to the + correct aspect ratio for the chosen string in the chosen + font. This ensures that resizing will not warp the text. + + + + Fonts are rendered using the [[stroke]] assigned to the box, + using the font assigned to the [[font]] property. When an + object is written to this property, it is coerced to a stream which is interpreted using + the , and the resulting font is used to render the box's + [[text]]. + + To choose the size of a font, just set the box's [[height]] + property to the desired height **in pixels**. Conversion + functions from points to pixels are available. + +
+ +
+ The [[transform]] property allows the user to specify an + arbitrary affine transformation to be applied to the box's path, + text, and children. The syntax and features supported are + identical to those described in , and include rotation, shearing, scaling, and + translation. + + + FIXME + + + One tricky part about transformations is their interaction with + box packing and dimension properties. A box's size properties + (such as [[minwidth]] or [[height]]) are **always** measured in + the box's own coordinate space (ie after applying the box's + [[transform]]). This means that the sum of the [[width]]s of a + box's children may not be equal to the parent box's [[width]], + even if the children appear (on screen) to completely fill its + width. + + One other consequence of combining transformations with + constraint-based layout is that when a box is rotated, its width + and height are no longer completely independent (remember, the + box's width is measured in the rotated coordinate space). If a + box is turned at a 45 degree angle and then forced into a space + 10 pixels wide, enlarging the box's width will force a reduction + in its height (in order to cram it in the 10 pixel space). In + situations like this, Ibex will first look to the box's + [[aspect]], if explicitly set, and obey that. If the box's + [[aspect]] is unspecified, Ibex will use the ratio between the + box's [[minwidth]] and [[minheight]] to guide the tradeoff. If + either of these properties is [[0]], Ibex will simply attempt to + make the ratio as close to [[1:1]] as possible. + + When we talk about a box's **bounding box**, we are referring to + the smallest rectangle in the **parent's** coordinate space + which completely encloses the child box's path. This is the + only time we will deal with the size of a child using a + coordinate space other than its own. +
+ +
+ + We will cover the layout algorithm in detail in the next section, + but we introduce the properties at play here and give an intuition + about their purpose. + + + The layout strategy for this box. If set to [[true]], the + box occupies no cells and is laid out independently of its + siblings. + + + + This property controls the strategy Ibex uses for changing the + box's width and height in response to layout constraints. + + If [[zoom]] is set to [[false]] (the default), then the box's + [[path]] will be altered by multiplying all the vertices by a + scaling factor in order to make the path's bounding box meet + the required constraints. The box's [[transform]] will not be + affected, and the scaling of the box's children will not be + affected. + + If [[zoom]] is set to [[true]], the box's [[path]] will not be + altered in response to layout constraints; rather, its + [[transform]] will be altered in order to "zoom in" or "zoom + out" and bring all of the path's vertices within the desired + region. Since the box's [[transform]] also applies to its + descendants, they too will be magnified or reduced. + + + + If set to [[true]], this box will shrink + (horizontally/vertically/both) to the smallest size allowed by + its children and the bounding box of its path. + + + + If the box is a root box, writing to these properties moves + the surface; reading from them returns the position of the + surface. + + On non-root boxes, writing to these properties is a shorthand + for adding a [["translate(x, y)"]] to the box's [[transform]]. + Reading from these properties will return FIXME. + + + + The desired minimum width and height. See the [[zoom]] + property for a description of how the box is altered to meet + these constraints. + + + + The desired maximum width and height. See the [[zoom]] + property for a description of how the box is altered to meet + these constraints. + + + + When read, this is the current (width/height) of this box. + Writing to this property is equivalent to writing to + **both** the minimum and maximum (width/height). + + + + 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 [[rows]] or [[cols]] must be zero. If + [[0]] is written to [[cols]] when [[rows]] is + [[0]], the write is ignored. If a nonzero value is + written to [[cols]] when [[rows]] is nonzero, + [[rows]] is set to [[0]], and vice versa. + + + + The number of (columns/rows) that this box spans within its parent. + + + + The width-to-height ratio constraint for this box; can be set + either as a floating point number ([[0.5]]) or a ratio + ([["1:2"]]). Setting this to [[0.0]] disables the ratio + constraint. + + Note packed boxes always **shrink** in order to satisfy aspect + constraints, while unpacked boxes always **grow** in order to + satisfy them -- even if this means growing larger than the box's + parent. + + + + 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 [[false]] will + be returned if this box **or any of its ancestors** is not + visible. Thus it is possible to write [[true]] to a box's + [[visible]] property and then read back [[false]]. + +
-
+
+ +
The size and position of every box is determined by its properties, its childrens' sizes, and its parent's size and @@ -481,40 +816,6 @@ not the same thing as the property [[minwidth]], although they are closely related. - - - When the user resizes a window, Ibex changes the root box's - [[maxwidth]] and [[maxheight]] 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 - [[minwidth]] and [[minheight]]. If the [[hshrink]] or - [[vshrink]] 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. - - - - - - When talking about positioning, we will often refer to the - **alignment point**. - - If the [[align]] property is "[[center]]", then the - alignment point is the center of the box. - - If the [[align]] property is "[[topleft]]", - "[[bottomleft]]", "[[topright]]", or - "[[bottomright]]", then the alignment point is - corresponding corner of the box. - - If the [[align]] property is "[[top]]", - "[[bottom]]", "[[right]]", or "[[left]]", then - the alignment point is middle of the corresponding edge of the - box. -
A grid of **cells** is created within the parent. If the @@ -522,22 +823,47 @@ infinite number of columns. Either [[cols]] or [[rows]] must be zero, but not both. - If a child's [[visible]] property is [[false]], it does - not occupy any cells (and is not rendered). Otherwise, each child - occupies a rectangular set of cells [[child.colspan]] cells - wide and [[child.rowspan]] cells high. + + + A box's target region is the portion of its parent which the + layout algorithm has determined that the box should occupy. A + box's target region is determined mainly by the value of its + [[pinned]] property: + + + If a box's [[pinned]] property is [[null]], it is said to be + "unpinned" or "not pinned". In this case, the box's target + region will be the set of cells in its parent which it + occupies. + + If a box's [[pinned]] region is set to some other box, then + this box's target region will be the projection of that + other box's actual dimensions and position, projected onto + this box's parent. The net effect is that the pinned box + will "track" the size and position of the box it is pinned + to. A box may not be pinned to one of its descendants, nor + may boxes be pinned in a cycle (A is pinned to B, B is + pinned to C, and C is pinned to A). + + + If a child's [[visible]] property is [[false]], it does not + occupy any cells (and is not rendered). If a box's [[pinned]] + property (described below) is non-[[null]], it does not occupy + any cells and is exempt from the packing process. Otherwise, + each child occupies a rectangular set of cells [[child.colspan]] + cells wide and [[child.rowspan]] cells high. The Core iterates over the cells in the grid in the following order: if [[rows]] 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 **first - remaining unplaced child's** 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 [[colspan]] 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). + remaining unplaced, packed child's** 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 [[colspan]] 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).
       
@@ -547,52 +873,104 @@
           
           
       
-
-
-
       
- Each box's minimum width is computed recursively as the maximum of: Its [[minwidth]] - The width of the box's [[text]] (after applying the - box's [[transform]]) [**Note: Vector Graphics support - (including the [[transform]] property) is currently not - implemented**]. + The width of its [[path]] - The width of the box's path (after applying the box's - [[transform]]) **if the box is [[packed]]**. - - The minimum width of the children in each row. + The sum of the widths of the bounding boxes enclosing its + children, when those children are sized to **their own** + minimum widths. + + The box's minimum **height** multiplied by its [[aspect]], + if its aspect is not [[0]] (unspecified). - + If a box's [[hshrink]] property is set to [[true]], the box's maximum width is the same as its minimum width; otherwise it is the box's [[maxwidth]]. -
- -
+ + + + Once the box's size and the size and position of its target + region have been computed, the box is placed relative to its + **target origin**, which is determined by by the [[origin]] + property: + + + Determines which corner of the box's target region should be + treated as the origin for layout purposes. + + If the [[origin]] property is "[[center]]", then the + target origin is at the center of the target region. + + If the [[origin]] property is "[[topleft]]", + "[[bottomleft]]", "[[topright]]", or "[[bottomright]]", then + the target origin is at the corresponding corner of the + target region. + + If the [[origin]] property is "[[top]]", "[[bottom]]", + "[[right]]", or "[[left]]", then the target origin is middle + of the corresponding edge of the target region. + + + + Determines the offset from the box's origin at which it will + be placed. + + + If the box's [[hshrink]] property is not set, it is expanded to + its maximum width, but no larger than its parent's width. + + Finally, if the child has a nonzero [[aspect]], one of its + dimensions (either width or height) will **grow** in order to + ensure that [[width == height * aspect]]. This may cause the + child to exceed the paren't size. + + + + First, the coordinate space in which the child is positioned is + translated so that the origin coincides with the + corner/edge/center of the box's parent corresponding to the + child's [[align]] property. The child's [[transform]] attribute + is applied to the coordinate space, and the child is positioned + in this transformed space with its aligment point at the origin. + + The following diagram may be helpful: + + FIXME: diagram + + + + Thoughout this section, when we refer to the [[minwidth]], + [[maxwidth]], or minimum width of a child box, we are referring + to the corresponding dimension of the child's **bounding box** + -- the smallest rectangle **in the parent's coordinate space** + that completely encloses the child's path. Ibex formulates a set of constraints for placing a box's **packed** children as follows: - - A box's width can be no greater than the sum of the + A box's width can be no greater than the sum of the columns it occupies - - The sum of a set of colums cannot be smaller than the + + The sum of a set of colums cannot be smaller than the minimum width of a box that spans them. - - The sum of the widths of the parents' columns will be at + + The sum of the widths of the parents' columns will be at least as large as the parent's width is (but possibly larger). @@ -602,70 +980,41 @@ prioritized from most important to least important: - - (__Most Important__) The sum of all columns will be a close + (__Most Important__) The sum of all columns will be a close to the parent's with as possible (ie as small as possible) - - Ibex will attempt to make a set of columns no wider than + + Ibex will attempt to make a set of columns no wider than the [[maxwidth]] of a box spanning them. - - (__Least Important__) Ibex will attempt to make all - columns the same width. + + Ibex will attempt to make all + columns the same width. (**least important**) Each packed box is then placed within the set of cells that it spans. Usually the box will exactly fill this rectangle; if it - does not (due to [[maxwidth]] or minimum width constraints), the - box's will be placed so that its alignment point coincides with - the alignment point of that rectangle of cells. -
+ does not (due to [[maxwidth]], minimum width, or aspect + constraints), the box's will be placed so that its alignment + point coincides with the alignment point of that rectangle of + cells. -
- Each non-packed box is transformed according to the parent's - [[transform]] property and then positioned so that its alignment - point is [[(child.x, child.y)]] pixels from the corresponding - edge/corner/center of its parent. -
- -
+ -
- - Boxes are rendered in a depth-first, pre-order traversal. Note that - this may cause a non-packed box to overlap its siblings. - - - - If the box's [[transform]] property is non-null, the - coordinate space is transformed accordingly for the rest of - this phase and for the rendering of all children. [**Note: - Vector Graphics support (including the [[transform]] - property) is currently not implemented**]. - - If the box is packed and has a non-[[null]] 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 [[align]] - property). - - If a box has a path, that path is filled with the color, - gradient, or image specified by the [[fill]] property and - stroked with the color and width specified by the - [[strokecolor]] and [[strokewidth]] properties. - - If the box has a non-null [[text]] attribute, - the text is rendered in [[font]] with size - [[fontsize]] and color [[textcolor]]. 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 [[align]] - property). - - The box's children are rendered (pre-order traversal). - - - -
- + When the user resizes a window, Ibex changes the root box's + [[maxwidth]] and [[maxheight]] 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 + [[minwidth]] and [[minheight]]. If the [[hshrink]] or + [[vshrink]] 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. +
+
+
@@ -674,139 +1023,6 @@ meaning, which will be explained later. Each box's numeric properties hold its **child boxes**. -
- - 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. - - - - If the value is a 5-character hex string ([[#RGB]]), - 7-character hex string ([[#RRGGBB]]), 9-character hex - string ([[#AARRGGBB]]), the box's stroke color will be set - to that color. - - If the value is one of the colors (the same set of color names - supported by SVG), the stroke color be set to that color. - - If the value is [[null]], the stroke color will be set - to clear ([[#00000000]]). - - - - The width (in pixels) to stroke the path with. - - - - This property can be set to any of the values specified for - [[strokecolor]]. - 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 - [[minwidth]] and [[minheight]] properties will be - automatically set to the dimensions of the image. - - - - The box's path. The grammar and feature set supported are - identical to that specified in . - - - - The box's text; writing [[null]] to this property sets it - to [[""]]. - - - - The color in which to render the font; accepts the same values as [[strokecolor]]. - - - - When an object is written to this property, its stream is read - using the , - and the resulting font is used to render the - box's [[text]]. - - - - The size (in points) to render the text. - - -
- -
- - - If set to [[true]], this box will shrink - (horizontally/vertically/both) to the smallest size allowed by - its children and the bounding box of its path. - - - - 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 the corresponding corner/edge/center of - its parent. - - - - The desired minimum width and height. - - - - The desired maximum width and height. - - - - When read, this is the current (width/height) of this box. - Writing to this property is equivalent to writing to - **both** the minimum and maximum (width/height). - - - - 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 [[rows]] or [[cols]] must be zero. If - [[0]] is written to [[cols]] when [[rows]] is - [[0]], the write is ignored. If a nonzero value is - written to [[cols]] when [[rows]] is nonzero, - [[rows]] is set to [[0]], and vice versa. - - - - The number of (columns/rows) that this box spans within its parent. - - - - Determines the box's alignment point for positioning its text, - texture, path, and children. - - - - 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 [[false]] will - be returned if this box **or any of its ancestors** is not - visible. Thus it is possible to write [[true]] to a box's - [[visible]] property and then read back [[false]]. - - - - The layout strategy for this box. If set to [[true]], the - box occupies no cells and is laid out independently of its - siblings. - - -
-
@@ -855,7 +1071,6 @@ - FIXME If this box has a parent, this property returns [[**parent**.surface]]; otherwise it returns null. This property is a simple building block that the widget @@ -933,26 +1148,18 @@ windows. - + The value [[true]] is put to this property on the root box - when the surface is maximized, and [[false]] when the surface - is un-maximized. Reading from this value will return [[true]] - if the surface is maximized and [[false]] if it is - not. Putting [[true]] to this property will maximize the - window, and putting [[false]] to this property will - unmaximize the window. + when the surface is maximized/minimized, and [[false]] when + the surface is un-maximized/minimized. Reading from this value + will return [[true]] if the surface is maximized/minimized and + [[false]] if it is not. Putting [[true]] to this property will + maximize/minimize the window, and putting [[false]] to this + property will unmaximize/unminimize the window. + Note that not all platforms support maximization. - - The value [[true]] is put to this property on the root box - when the surface is minimized, and [[false]] when the surface - is unminimized. Reading from this value will return [[true]] - if the surface is minimized and [[false]] if it is - not. Putting [[true]] to this property will minimize the - window, and putting [[false]] will unminimize it. - - When the user attempts to close a surface, the value [[true]] will be put to this property. Scripts may trap @@ -963,21 +1170,243 @@ property. - - The surface's icon. This is usually displayed on the titlebar of a - window. The value should be an object whose stream is a PNG image. Note - that not all platforms support this property. + + The surface's titlebar text and icon. If a string is written + to this property, the surface's titlebar text is set to that + string; if a stream yielding an image is written, the + surface's icon is set to that image. Note that not all + platforms support this property. Only ASCII characters + 0x20-0x7F are permitted. - - The surface's titlebar text. Note that not all platforms support - this property. Only ASCII characters 0x20-0x7F are permitted. +
+ +
+ + +
+ + 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 [[_Press[1-3]]], + [[_Release[1-3]]], [[_Click[1-3]]], [[_DoubleClick[1-3]]], + [[_Move]], [[_KeyPressed]], and [[_KeyReleased]]. + + 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 + **that** 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. + +
+    
+        _Press1 ++= function(b) { ibex.log.info("first"); }
+         Press1 ++= function(b) { ibex.log.info("fourth"); }
+        
+          _Press1 ++= function(b) { ibex.log.info("second"); }
+           Press1 ++= function(b) { ibex.log.info("third"); }
+        
+    
+    
+ + In general, you should use the **non-underscore** 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). + + + + At any point in this sequence, a trap handler can choose not to + cascade (by returning [[true]] 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". + + + + Ibex uses the following events to notify a box about changes that + only matter to that particular box. These events do not propagate + either up or down the tree. + + + The value [[true]] is written to this property when the mouse (enters/leaves) the box. + + + + The value [[true]] is put to this property after the size + of this box changes. + + + When a child is added or removed, that child is written to + this property. The write is always performed **after** the + addition or removal, so these two cases can be distinguished + by checking [[indexof(child)]]. + + Note that if the parent's redirect target is set to another + box, this trap will only be invoked when children are + manipulated by reading and writing to the parent. Reads and + writes directly to the redirect target will **not** trigger + this trap. + + Note also that this traps is still triggered if a box's + [[redirect]] target is **null**. This is useful for + boxes that need to accept children and then relocate them + elsewhere. + + +
+ + + Indicates that the use has pressed a mouse button. On + platforms with three mouse buttons, the **middle** button + is button 3 -- this ensures that applications written to only + use two buttons (1 and 2) will work intuitively on three button + platforms. + + + + Indicates that the use has released a mouse button. + + + + Indicates that the user has pressed and released the + mouse button without moving the mouse much (exactly how + much is platform-dependent). + + + + Indicates that the user has clicked the + mouse button twice within a short period of time (exactly how long is platform-dependent). + + + + Indicates that the mouse has moved while within this box, or that + the mouse while outside this box **if a button was pressed while within this box and has not yet been released** + + + + + 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 . 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 + "[[HOME]]". Symbols are capitalized as they appear on the + keyboard; for example, on an American QWERTY keyboard, shift+2 + is reported as "[[@]]". + + If the alt, meta, or command key was depressed immediately + before this key was pressed, then the string will be prefixed + with the string "[[A-]]". If the control key was depressed + while this key was pressed, then the string will be prefixed + with the string "[[C-]]". If both alt and control are + depressed, the string is prefixed with "[[C-A-]]". + + 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. + + +
+
+ + At any point in the Event Context, you can write to the [[mouse]] + property on any box. The value written should be an object with two + properties, [[x]] and [[y]]. For example: + +
+    _Press1 ++= function(p) {
+        mouse = { x: 32, y: 77 };
+    }
+    
+ + The coordinates specified are relative to the box whose [[mouse]] + property is being written to. There is no need to supply the + [[inside]] property; it is computed automatically. Writing to + the [[mouse]] property causes Ibex to recompute the eventual + target box, and also alter the values returned by [[mouse.x]], + [[mouse.y]], and [[mouse.inside]] for any **descendants** + of the current box. Writing to the [[mouse]] 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. + +
+    
+        _KeyPressed = function(k) { ibex.log.info("first"); }
+         KeyPressed = function(k) { ibex.log.info("sixth"); }
+        $recipient.target = $target;
+        
+            _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"); }
+            
+                _KeyPressed = function(k) {
+                   ibex.log.info("this never happens");
+                }
+            
+        
+         
+            _KeyPressed = function(k) { ibex.log.info("third"); }
+             KeyPressed = function(k) { ibex.log.info("fourth"); }
+        
+    
+    
+ +
+ +
+ + You can create "fake events" by simply writing to the [[mouse]] + 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.
+
-
+ +
@@ -1502,9 +1931,6 @@
- -
-
From the perspective of an application writer, Ibex is strictly @@ -1568,165 +1994,6 @@
- -
- - 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 [[_Press[1-3]]], - [[_Release[1-3]]], [[_Click[1-3]]], [[_DoubleClick[1-3]]], - [[_Move]], [[_KeyPressed]], and [[_KeyReleased]]. - - 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 - **that** 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. - -
-    
-        _Press1 ++= function(b) { ibex.log.info("first"); }
-         Press1 ++= function(b) { ibex.log.info("fourth"); }
-        
-          _Press1 ++= function(b) { ibex.log.info("second"); }
-           Press1 ++= function(b) { ibex.log.info("third"); }
-        
-    
-    
- - In general, you should use the **non-underscore** 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). - -
- - - - At any point in this sequence, a trap handler can choose not to - cascade (by returning [[true]] 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". - - - - Ibex uses the following events to notify a box about changes that - only matter to that particular box. These events do not propagate - either up or down the tree. - - - The value [[true]] is written to this property when the mouse (enters/leaves) the box. - - - - The value [[true]] is put to this property after the size - of this box changes. - - - - When a child is added or removed, that child is written to - this property. The write is always performed **after** the - addition or removal, so these two cases can be distinguished - by checking [[indexof(child)]]. - - Note that if the parent's redirect target is set to another - box, this trap will only be invoked when children are - manipulated by reading and writing to the parent. Reads and - writes directly to the redirect target will **not** trigger - this trap. - - Note also that this traps is still triggered if a box's - [[redirect]] target is **null**. This is useful for - boxes that need to accept children and then relocate them - elsewhere. - - -
- - - Indicates that the use has pressed a mouse button. On - platforms with three mouse buttons, the **middle** button - is button 3 -- this ensures that applications written to only - use two buttons (1 and 2) will work intuitively on three button - platforms. - - - - Indicates that the use has released a mouse button. - - - - Indicates that the user has pressed and released the - mouse button without moving the mouse much (exactly how - much is platform-dependent). - - - - Indicates that the user has clicked the - mouse button twice within a short period of time (exactly how long is platform-dependent). - - - - Indicates that the mouse has moved while within this box, or that - the mouse while outside this box **if a button was pressed while within this box and has not yet been released** - - - - - 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 . 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 - "[[HOME]]". Symbols are capitalized as they appear on the - keyboard; for example, on an American QWERTY keyboard, shift+2 - is reported as "[[@]]". - - If the alt, meta, or command key was depressed immediately - before this key was pressed, then the string will be prefixed - with the string "[[A-]]". If the control key was depressed - while this key was pressed, then the string will be prefixed - with the string "[[C-]]". If both alt and control are - depressed, the string is prefixed with "[[C-A-]]". - - 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. - - - -
- -
-
@@ -1947,75 +2214,6 @@
- -
- -
- - At any point in the Event Context, you can write to the [[mouse]] - property on any box. The value written should be an object with two - properties, [[x]] and [[y]]. For example: - -
-    _Press1 ++= function(p) {
-        mouse = { x: 32, y: 77 };
-    }
-    
- - The coordinates specified are relative to the box whose [[mouse]] - property is being written to. There is no need to supply the - [[inside]] property; it is computed automatically. Writing to - the [[mouse]] property causes Ibex to recompute the eventual - target box, and also alter the values returned by [[mouse.x]], - [[mouse.y]], and [[mouse.inside]] for any **descendants** - of the current box. Writing to the [[mouse]] 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. - -
-    
-        _KeyPressed = function(k) { ibex.log.info("first"); }
-         KeyPressed = function(k) { ibex.log.info("sixth"); }
-        $recipient.target = $target;
-        
-            _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"); }
-            
-                _KeyPressed = function(k) {
-                   ibex.log.info("this never happens");
-                }
-            
-        
-         
-            _KeyPressed = function(k) { ibex.log.info("third"); }
-             KeyPressed = function(k) { ibex.log.info("fourth"); }
-        
-    
-    
- -
- -
- - You can create "fake events" by simply writing to the [[mouse]] - 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. - -
@@ -2084,7 +2282,7 @@ new_ibex.load ++= function() { return newLoadFunction; } ibex.apply(ibex.box, .main, new_ibex); -
+
@@ -2431,5 +2629,5 @@ Copyright (C) 2004 Adam Megacz, verbatim redistribution permitted. Ibex is a trademark of Adam Megacz ** - +
\ No newline at end of file