initial checkin master
authorAdam Megacz <adam@megacz.com>
Sun, 10 Oct 2010 20:18:26 +0000 (20:18 +0000)
committerAdam Megacz <adam@megacz.com>
Sun, 10 Oct 2010 20:18:26 +0000 (20:18 +0000)
180 files changed:
doc/AUTHORS.txt [new file with mode: 0644]
doc/COPYING.txt [new file with mode: 0644]
doc/README.txt [new file with mode: 0644]
doc/skel.t [new file with mode: 0644]
src/games.t [new file with mode: 0644]
src/ibex/lib/cardpane.t [new file with mode: 0644]
src/ibex/lib/clickable.t [new file with mode: 0644]
src/ibex/lib/focusable.t [new file with mode: 0644]
src/ibex/lib/focusmanager.t [new file with mode: 0644]
src/ibex/lib/polarizable.t [new file with mode: 0644]
src/ibex/lib/redirect.t [new file with mode: 0644]
src/ibex/lib/repeatable.t [new file with mode: 0644]
src/ibex/lib/scrollbar.t [new file with mode: 0644]
src/ibex/lib/scrollpane.t [new file with mode: 0644]
src/ibex/lib/selectable.t [new file with mode: 0644]
src/ibex/lib/slider.t [new file with mode: 0644]
src/ibex/lib/spin.t [new file with mode: 0644]
src/ibex/lib/surface.t [new file with mode: 0644]
src/ibex/lib/tabpane.t [new file with mode: 0644]
src/ibex/lib/text/block.t [new file with mode: 0644]
src/ibex/lib/text/edit.t [new file with mode: 0644]
src/ibex/lib/text/flow.t [new file with mode: 0644]
src/ibex/theme/button.t [new file with mode: 0644]
src/ibex/theme/clickable.t [new file with mode: 0644]
src/ibex/theme/edit.t [new file with mode: 0644]
src/ibex/theme/focusable.t [new file with mode: 0644]
src/ibex/theme/radio.t [new file with mode: 0644]
src/ibex/theme/repeatable.t [new file with mode: 0644]
src/ibex/theme/selectable.t [new file with mode: 0644]
src/ibex/theme/surface.t [new file with mode: 0644]
src/ibex/util/group.t [new file with mode: 0644]
src/ibex/util/list.t [new file with mode: 0644]
src/ibex/util/queue.t [new file with mode: 0644]
src/ibex/util/vector.t [new file with mode: 0644]
src/ibex/widget/bevel.t [new file with mode: 0644]
src/ibex/widget/border.t [new file with mode: 0644]
src/ibex/widget/button.t [new file with mode: 0644]
src/ibex/widget/cardpane.t [new file with mode: 0644]
src/ibex/widget/check.t [new file with mode: 0644]
src/ibex/widget/label.t [new file with mode: 0644]
src/ibex/widget/margin.t [new file with mode: 0644]
src/ibex/widget/pad.t [new file with mode: 0644]
src/ibex/widget/radio.t [new file with mode: 0644]
src/ibex/widget/redirect.t [new file with mode: 0644]
src/ibex/widget/scrollbar.t [new file with mode: 0644]
src/ibex/widget/scrollpane.t [new file with mode: 0644]
src/ibex/widget/slider.t [new file with mode: 0644]
src/ibex/widget/spin.t [new file with mode: 0644]
src/ibex/widget/tab.t [new file with mode: 0644]
src/ibex/widget/tabpane.t [new file with mode: 0644]
src/ibex/widget/textarea.t [new file with mode: 0644]
src/ibex/widget/textfield.t [new file with mode: 0644]
src/main.t [new file with mode: 0644]
src/org/ibex/games/checkers/main.t [new file with mode: 0644]
src/org/ibex/games/chess/main.t [new file with mode: 0644]
src/org/ibex/games/reversi/board.t [new file with mode: 0644]
src/org/ibex/games/reversi/dark_stone.png [new file with mode: 0644]
src/org/ibex/games/reversi/light_stone.png [new file with mode: 0644]
src/org/ibex/games/reversi/main.t [new file with mode: 0644]
src/org/ibex/games/reversi/square.t [new file with mode: 0644]
src/org/ibex/sampler/clipboard.t [new file with mode: 0644]
src/org/ibex/sampler/color_picker.t [new file with mode: 0644]
src/org/ibex/sampler/dialog.t [new file with mode: 0644]
src/org/ibex/sampler/fonts.t [new file with mode: 0644]
src/org/ibex/sampler/html.t [new file with mode: 0644]
src/org/ibex/sampler/spreadsheet.t [new file with mode: 0644]
src/org/ibex/sampler/transparency.t [new file with mode: 0644]
src/org/ibex/sampler/window_manager_interaction.t [new file with mode: 0644]
src/org/ibex/test/alpha1.t [new file with mode: 0644]
src/org/ibex/test/alpha2.t [new file with mode: 0644]
src/org/ibex/test/button.t [new file with mode: 0644]
src/org/ibex/test/check.t [new file with mode: 0644]
src/org/ibex/test/clickable.t [new file with mode: 0644]
src/org/ibex/test/flow.t [new file with mode: 0644]
src/org/ibex/test/label.t [new file with mode: 0644]
src/org/ibex/test/main.t [new file with mode: 0644]
src/org/ibex/test/radio.t [new file with mode: 0644]
src/org/ibex/test/tab.t [new file with mode: 0644]
src/org/ibex/test/tabtest.t [new file with mode: 0644]
src/org/ibex/test/text.t [new file with mode: 0644]
src/org/ibex/theme/base/bevel.t [new file with mode: 0644]
src/org/ibex/theme/base/border-img.t [new file with mode: 0644]
src/org/ibex/theme/base/clickable.t [new file with mode: 0644]
src/org/ibex/theme/base/focusable.t [new file with mode: 0644]
src/org/ibex/theme/base/margin.t [new file with mode: 0644]
src/org/ibex/theme/base/pad.t [new file with mode: 0644]
src/org/ibex/theme/base/selectable.t [new file with mode: 0644]
src/org/ibex/theme/win2k/bevel.t [new file with mode: 0644]
src/org/ibex/theme/win2k/border.t [new file with mode: 0644]
src/org/ibex/theme/win2k/button.t [new file with mode: 0644]
src/org/ibex/theme/win2k/cardpane.t [new file with mode: 0644]
src/org/ibex/theme/win2k/check.t [new file with mode: 0644]
src/org/ibex/theme/win2k/clickable.t [new file with mode: 0644]
src/org/ibex/theme/win2k/draggable.t [new file with mode: 0644]
src/org/ibex/theme/win2k/edit.t [new file with mode: 0644]
src/org/ibex/theme/win2k/focusable.t [new file with mode: 0644]
src/org/ibex/theme/win2k/image/arrowdown.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/arrowleft.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/arrowright.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/arrowup.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevel1down/ee.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevel1down/ne.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevel1down/nn.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevel1down/nw.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevel1down/se.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevel1down/ss.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevel1down/sw.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevel1down/ww.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevel1up/ee.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevel1up/ne.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevel1up/nn.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevel1up/nw.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevel1up/se.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevel1up/ss.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevel1up/sw.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevel1up/ww.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelabove/ee.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelabove/ne.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelabove/nn.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelabove/nw.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelabove/se.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelabove/ss.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelabove/sw.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelabove/ww.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/beveldown/ee.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/beveldown/ne.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/beveldown/nn.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/beveldown/nw.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/beveldown/se.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/beveldown/ss.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/beveldown/sw.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/beveldown/ww.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelflat/ee.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelflat/ne.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelflat/nn.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelflat/nw.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelflat/se.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelflat/ss.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelflat/sw.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelflat/ww.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/beveltabtop/ee.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/beveltabtop/ne.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/beveltabtop/nn.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/beveltabtop/nw.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/beveltabtop/se.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/beveltabtop/ss.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/beveltabtop/sw.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/beveltabtop/ww.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelup/ee.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelup/ne.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelup/nn.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelup/nw.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelup/se.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelup/ss.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelup/sw.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/bevelup/ww.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/check.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/check_highlighted.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/check_mixed.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/radio.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/radio_highlighted.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/radio_mixed.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/radiobg.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/radiobg_active.png [new file with mode: 0644]
src/org/ibex/theme/win2k/image/scrollbg.png [new file with mode: 0644]
src/org/ibex/theme/win2k/margin.t [new file with mode: 0644]
src/org/ibex/theme/win2k/pad.t [new file with mode: 0644]
src/org/ibex/theme/win2k/polarizable.t [new file with mode: 0644]
src/org/ibex/theme/win2k/radio.t [new file with mode: 0644]
src/org/ibex/theme/win2k/redirect.t [new file with mode: 0644]
src/org/ibex/theme/win2k/repeatable.t [new file with mode: 0644]
src/org/ibex/theme/win2k/scrollbar.t [new file with mode: 0644]
src/org/ibex/theme/win2k/scrollpane.t [new file with mode: 0644]
src/org/ibex/theme/win2k/selectable.t [new file with mode: 0644]
src/org/ibex/theme/win2k/slider.t [new file with mode: 0644]
src/org/ibex/theme/win2k/spin.t [new file with mode: 0644]
src/org/ibex/theme/win2k/surface.t [new file with mode: 0644]
src/org/ibex/theme/win2k/tab.t [new file with mode: 0644]
src/org/ibex/theme/win2k/tabpane.t [new file with mode: 0644]
src/sampler.t [new file with mode: 0644]

diff --git a/doc/AUTHORS.txt b/doc/AUTHORS.txt
new file mode 100644 (file)
index 0000000..7fb6444
--- /dev/null
@@ -0,0 +1,7 @@
+TODO: this file is grossly inadequate
+
+Charles Goodwin
+- Most of the widgets
+
+David Crawshaw
+- Workings of the key widgets
diff --git a/doc/COPYING.txt b/doc/COPYING.txt
new file mode 100644 (file)
index 0000000..38ae815
--- /dev/null
@@ -0,0 +1,870 @@
+================================================================================
+The contents of this distribution are copyrighted and licensed as follows: 
+================================================================================
+
+- The XWT Standard Library (all files except org/gimp/tigert/**) is
+  Copyright by various authors; it is licensed to the public under the
+  GNU Library General Public License.
+
+- The files in the subdirectory org/gimp/tigert/** are Copyright
+  Tigert Labs, and are licensed under the GNU General Public
+  License. "The icons are released under the Gnu General Public
+  License, meaning you can use them in free software projects free of
+  charge. If you wish to use these for other things (or if you need
+  other icons for your project) contact me." [from
+  http://tigert.gimp.org/gnome/gnome-stock/]
+
+
+
+========================================================================
+The GNU General Public License
+
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+
+
+========================================================================
+The GNU Lesser General Public License
+
+                 GNU LESSER GENERAL PUBLIC LICENSE
+                      Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+                 GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                           NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
diff --git a/doc/README.txt b/doc/README.txt
new file mode 100644 (file)
index 0000000..d4c309a
--- /dev/null
@@ -0,0 +1 @@
+TODO: readme file
diff --git a/doc/skel.t b/doc/skel.t
new file mode 100644 (file)
index 0000000..3890e55
--- /dev/null
@@ -0,0 +1,11 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        Author: Name
+    </meta:doc>
+
+    <ui:box>
+
+    </ui:box>
+</ibex>
diff --git a/src/games.t b/src/games.t
new file mode 100644 (file)
index 0000000..e38847f
--- /dev/null
@@ -0,0 +1,21 @@
+<ibex  xmlns:theme="ibex.theme"  \r
+       xmlns="org.ibex.theme.win2k" \r
+       xmlns:games="org.ibex.games">\r
+  <theme:surface />\r
+  <ui:box fill="#d4d0c8" maxwidth="600" maxheight="600" cols="1">\r
+    \r
+    ibex.ui.frame = thisbox;\r
+\r
+ <!--   <ui:box text="menus aren't implemented" height="20" align="left"/> -->\r
+    <tabpane>\r
+      <games:reversi.main tabtext="Reversi"/>      \r
+      <games:checkers.main tabtext="Checkers"/>\r
+      <games:chess.main tabtext="Chess"/>      \r
+<!--      <sampler:color_picker tabtext="Color Picker"/>      \r
+      <sampler:transparency tabtext="Transparency"/> \r
+      <sampler:fonts tabtext="Fonts"/>      \r
+      <sampler:html tabtext="HTML"/>      \r
+      <sampler:spreadsheet tabtext="Spreadsheet"/>            -->\r
+    </tabpane> \r
+  </ui:box>\r
+</ibex>
\ No newline at end of file
diff --git a/src/ibex/lib/cardpane.t b/src/ibex/lib/cardpane.t
new file mode 100644 (file)
index 0000000..a47c427
--- /dev/null
@@ -0,0 +1,119 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        See ibex.widget.cardpane for details
+
+        <todo>
+            Make cardpane aware of 'enabled' cards
+        </todo>
+    </meta:doc>
+    <ui:box>
+
+        // public interface
+
+        thisbox.nextcard;
+        thisbox.nextstep;
+        thisbox.prevcard;
+        thisbox.prevstep;
+        thisbox.show;
+
+        // private variables
+
+        var steps = [];
+        var stepmarker = 0;
+        var stepping = false;
+
+        // childadded write trap
+        childadded ++= function(v) {
+            // show v if it is the first card
+            if (numchildren > 1) v.visible = false;
+            else { cascade = v; show = v; }
+        }
+
+        // childremoved write trap
+        childremoved ++= function(v) {
+            // if v is the shown card, attempt to show another
+            if (show == v) {
+                if (next) next = true;
+                else if (prev) prev = true;
+            }
+        }
+
+        // write trap to show the next card in the cardpane
+        nextcard ++= function(v) {
+            if (nextcard) nextcard.show = true;
+        }
+
+        // read trap to fetch the next card in the cardpane
+        nextcard ++= function() {
+            if (show and numchildren - 1 > show) return thisbox[show + 1];
+            else return null;
+        }
+
+        // write trap to step forward to the next in the show-chain
+        nextstep ++= function(v) {
+            stepping = true;
+            if (nextstep) nextstep.show = true;
+            stepping = false;
+        }
+
+        // read trap to fetch the next step in the show-chain
+        nextstep ++= function() {
+            if (steps.length - 1 > stepmarker) return steps[stepmarker + 1];
+            else return false;
+        }
+
+        // write trap to show the previous card in the cardpane
+        prevcard ++= function(v) {
+            if (prevcard) prevcard.show = true;
+        }
+
+        // read trap to fetch the previous card in the cardpane
+        prevcard ++= function() {
+            if (show and show > 0) return thisbox[show - 1];
+            else return false;
+        }
+
+        // write trap to step back to the previous in the show-chain
+        prevstep ++= function(v) {
+            stepping = true;
+            if (prevstep) prevstep.show = true;
+            stepping = false;
+        }
+
+        // read trap to fetch the previous step in the show-chain
+        prevstep ++= function() {
+            if (stepmarker > 0) return steps[stepmarker - 1];
+            else return false;
+        }
+
+        // write trap to show a card by box or index
+        show ++= function(v) {
+            var card;
+            
+            if (typeof(v) == "number" and numchildren > v) card = thisbox[v];
+            else if (typeof(v) == "object" and (thisbox.indexof(v) or thisbox.indexof(v) == 0)) card = v;
+
+            if (card) {
+                // hide the previously shown card and show the new one
+                //if (cascade) cascade.visible = false;
+                for (var i=0; numchildren > i; i++) { thisbox[i].visible = false; }
+                card.visible = true;
+
+                // remember where we are
+                if (!stepping) {
+                    stepmarker ++;
+                    if (stepmarker != steps.length) steps.splice(stepmarker, steps.length - stepsmarker);
+                    if (stepmarker > 100) steps.splice(0);
+                    steps[stepmarker] = card;
+                }
+
+                cascade = card;
+            }
+            else return;
+        }
+
+    </ui:box>
+</ibex>
diff --git a/src/ibex/lib/clickable.t b/src/ibex/lib/clickable.t
new file mode 100644 (file)
index 0000000..63161ed
--- /dev/null
@@ -0,0 +1,103 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        See ibex.theme.clickable for details
+    </meta:doc>
+
+    <ibex.lib.repeatable />
+    <ui:box>
+
+        // template properties
+        thisbox.enabled;    // self explanatory
+        thisbox.repeats;    // if a repeating action is desired
+
+        // event triggers
+        thisbox.action;     // action trigger
+
+        // state properties
+        thisbox.primed;     // track activation irrespective of mouse.inside
+
+        // physical state triggers
+        thisbox.active;     // active state (mouse.inside and primed)
+        thisbox.hover;      // hover state (mouse.inside and !primed)
+        thisbox.normal;     // normal state (!mouse.inside)
+
+        enabled ++= function(v) {
+            cascade = v;
+            // deprime us when disabled
+            if (!v) { primed = false; normal = true; }
+        }
+
+        focused ++= function(v) {
+            cascade = v;
+            // unprime if defocused
+            if (!v and primed) primed = false;
+        }
+
+        primed ++= function(v) {
+            if (enabled) {
+                // determine physical state and activate trigger
+                v ? active = true : (mouse.inside ? hover = true : normal = true);
+                // set repeat state if necessary
+                if (repeats) repeat = v;
+            }
+            // do nothing when not enabled
+            else cascade = false;
+        }
+
+        KeyPressed ++= function(v) {
+            if (v == "enter" or v == " ") primed = true;
+            else if (v == "escape") primed = false;
+        }
+
+        KeyReleased ++= function(v) {
+            if (v == "enter" or v == " ")
+                if (primed and enabled)
+                    { action = true; primed = false; }
+        }
+
+        Enter ++= function(v) {
+            if (enabled) {
+                if (primed) {
+                    active = true;
+                    if (repeats) repeat = true;
+                }
+                else hover = true;
+            }
+        }
+
+        Leave ++= function(v) {
+            if (enabled) {
+                normal = true;
+                if (repeats) repeat = false;
+            }
+        }
+
+        Press1 ++= function(v) {
+            if (enabled) {
+                primed = true;
+
+                surface.Release1 ++= function(v) {
+                    // clean up
+                    if (enabled) {
+                        if (primed) {
+                            if (mouse.inside) repeats ? repeat = false : action = true;
+                            primed = false; // important: must occur _after_ action
+                        }
+                    }
+
+                    surface.Release1 --= callee;
+                }
+            }
+        }
+
+        // initialise as normal state
+        // FIXME: redo this using better method (?)
+        SizeChange ++= function(v) {
+            normal = true;
+            SizeChange --= callee;
+        }
+
+    </ui:box>
+</ibex>
diff --git a/src/ibex/lib/focusable.t b/src/ibex/lib/focusable.t
new file mode 100644 (file)
index 0000000..c974e7a
--- /dev/null
@@ -0,0 +1,60 @@
+<!-- Copyright 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        See ibex.theme.focusable for more details
+
+        <author>Charles Goodwin</author>
+        <author>David Crawshaw</author>
+    </meta:doc>
+
+    <ui:box>
+
+        thisbox.enabled;    // whether a focusable is enabled
+        thisbox.focusable;  // whether a focusable may be focused
+        thisbox.focused;    // whether a focusable is focused
+        thisbox.nextfocus;  // read for the focus after thisbox on the surface
+        thisbox.prevfocus;  // read for the focus before thisbox on the surface
+
+        // private function to assign to traps
+        var checkfocus = function(v) { if (!v and focused) focused = false; }
+
+        enabled ++= checkfocus;     // disabling prevents focus
+        focusable ++= checkfocus;   // making unfocusable prevents focus
+
+        // read trap to return focusable state
+        focusable ++= function() { return enabled and cascade; }
+
+        // write trap to set focused state
+        focused ++= function(v) {
+            if (v and surface and focusable) {
+                if (surface.focus) {
+                    surface.focus.focused = false;
+                }
+                surface.focus = thisbox;
+            }
+            else if (!v and surface and surface.focus == thisbox)
+                surface.focus = null;
+            else cascade = false;
+        }
+
+        // read trap to return the focus after thisbox on the surface
+        nextfocus ++= function() { return surface.nextFocus(thisbox); }
+
+        // read trap to return the focus before thisbox on the surface
+        prevfocus ++= function() { return surface.prevFocus(thisbox); }
+
+        // write trap to handle surface change
+        surface ++= function(v) {
+            // drop from current surface if there is one
+            if (cascade) cascade.dropFocus(thisbox);
+
+            // add to new surface
+            v.addFocus(thisbox);
+        }
+
+        // write trap to focus on Press1
+        Press1 ++= function(v) { if (!focused and focusable) focused = true; }
+
+    </ui:box>
+</ibex>
diff --git a/src/ibex/lib/focusmanager.t b/src/ibex/lib/focusmanager.t
new file mode 100644 (file)
index 0000000..8d00d2d
--- /dev/null
@@ -0,0 +1,73 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        Authors: Charles Goodwin, David Crawshaw
+
+        For documentation, see ibex.theme.surface
+    </meta:doc>
+
+    <ui:box>
+
+        var focus = null;   // the current focus
+
+        // the focus list for this surface
+        var fvector = ibex..ibex.util.vector..newVector();
+        //var fvector = ibex..ibex.util.vector(ibex.box);
+
+        // read trap to access the focused child
+        surface.focus ++= function() { return focus; }
+
+        surface.setFocus ++= function(v) {
+            if (v and v.focusable and fvector.contains(v)) {
+                if (focus and focus != v) focus.focused = false;
+                return true;
+            }
+            else if (!v and focus) {
+                focus.focused = false;
+                return true;
+            }
+            else return false;
+        }
+
+        // function to add a focus to the focus vector, optionally after w
+        surface.addFocus = function(v, w) {
+            // make sure we're not already in the focus list
+            surface.dropFocus(v);
+            
+            if (w and fvector.contains(w))
+                return fvector.insert(v, w);
+            else return fvector.push(v);
+        }
+
+        // function to drop a focus from the focus vector for this surface
+        surface.dropFocus = function(v) {
+            if (fvector.contains(v)) {
+                if (focus == v) focus = v.nextfocus;
+                return fvector.remove(v);
+            }
+            else return false;
+        }
+
+        // function to return the next-in-line for focus after v
+        surface.nextFocus ++= function(v) {
+            var nf = fvector.after(v);
+            while (!nf.focusable and nf != v) nf = fvector.after(nf);
+            return nf;
+        }
+
+        // function to return the previous-in-line for focus after v
+        surface.prevFocus ++= function(v) {
+            var pf = fvector.after(v);
+            while (!pf.focusable and pf != v) pf = fvector.before(pf);
+            return pf;
+        }
+
+        // private function to map events from this root ui:box onto the focused child
+        var passEvent = function(v) { if (focus) focus[trapname] = v; }
+
+        _KeyPressed ++= passEvent;      // pass keypress events to focused child
+        _KeyReleased ++= passEvent;     // pass keyrelease events to focused child
+
+    </ui:box>
+</ibex>
diff --git a/src/ibex/lib/polarizable.t b/src/ibex/lib/polarizable.t
new file mode 100644 (file)
index 0000000..76b60a5
--- /dev/null
@@ -0,0 +1,56 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        Author: Charles Goodwin
+    </meta:doc>
+
+    static.flip = function(f) {
+        if (f == "width") return "height";
+        else if (f == "height") return "width";
+        else if (f == "x") return "y";
+        else if (f == "y") return "x";
+        else if (f == "maxwidth") return "maxheight";
+        else if (f == "maxheight") return "maxwidth";
+        else if (f == "minwidth") return "minheight";
+        else if (f == "minheight") return "minwidth";
+        else if (f == "horizontal") return "vertical";
+        else if (f == "vertical") return "horizontal";
+        else if (f == "hshrink") return "vshrink";
+        else if (f == "vshrink") return "hshrink";
+        else if (f == "cols") return "rows";
+        else if (f == "rows") return "cols";
+        return null;
+    }
+
+    <ui:box>
+
+        thisbox.dim = "width";
+        thisbox.globalpos = "globalx";
+        thisbox.mindim = "minwidth";
+        thisbox.maxdim = "maxwidth";
+        thisbox.pos = "x";
+        thisbox.shr = "hshrink";
+        thisbox.flip = static.flip;
+
+        thisbox.orient ++= function(v) {
+            if (v == "horizontal") {
+                if (cols) rows = cols;
+                dim       = "width";
+                maxdim    = "maxwidth";
+                mindim    = "minwidth";
+                pos       = "x";
+                shr       = "hshrink";
+            }
+            else {
+                if (rows) cols = rows;
+                dim       = "height";
+                maxdim    = "maxheight";
+                mindim    = "minheight";
+                pos       = "y";
+                shr       = "vshrink";
+            }
+        }
+
+    </ui:box>
+</ibex>
diff --git a/src/ibex/lib/redirect.t b/src/ibex/lib/redirect.t
new file mode 100644 (file)
index 0000000..162a0e6
--- /dev/null
@@ -0,0 +1,72 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        See xwt.theme.redirect for details
+    </meta:doc>
+
+    <ui:box>
+
+        var locks = {};
+        var redirects = {};
+
+        thisbox.redirectTo = function(v) {
+            if (v == null) {
+                ibex.log.warn("Attempted to redirect properties to a null value");
+                return false;
+            }
+
+            for (var i=1; arguments.length > i; i++) {
+                // get property from arguments
+                var p = arguments[i];
+
+                // remove the trap if it already exists
+                if (redirects[p]) dropRedirect(v, p);
+
+                // create and store redirecting functions
+                redirects[p] = [v,
+                                function(w) {
+                                    if (!locks[p]) { locks[p] = true; cascade = w; thisbox[p] = w; locks[p] = null; }
+                                },
+                                function(w) {
+                                    if (!locks[p]) { locks[p] = true; v[p] = w; locks[p] = null; }
+                                    return true;
+                                },
+                                function() { return v[p]; }];
+
+                // assign redirecting traps
+                try { // try/catch for properties that can't have write traps
+                    thisbox[p] ++= redirects[p][2];
+                    v[p] ++= redirects[p][1];
+                } catch(e) {
+                    redirects[p][1] = null;
+                    redirects[p][2] = null;
+                }
+                // try/catch for properties that can't have read traps
+                try { thisbox[p] ++= redirects[p][3]; }
+                catch(e) { redirects[p][3] = null; }
+            }
+
+            // report success
+            return true;
+        }
+
+        thisbox.dropRedirect = function(v) {
+            for (var i=1; arguments.length > i; i++) {
+                // get property from arguments
+                var p = arguments[i];
+
+                // remove redirect traps and reference
+                if (redirects[p]) {
+                    if (redirects[p][1]) redirects[p][0] --= redirects[p][1];
+                    if (redirects[p][2]) thisbox[p] --= redirects[p][2];
+                    if (redirects[p][3]) thisbox[p] --= redirects[p][3];
+                    redirects[p] = null;
+                }
+            }
+
+            return true;
+        }
+
+    </ui:box>
+</ibex>
diff --git a/src/ibex/lib/repeatable.t b/src/ibex/lib/repeatable.t
new file mode 100644 (file)
index 0000000..7a78ed8
--- /dev/null
@@ -0,0 +1,41 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        Author: Charles Goodwin
+
+        See ibex.theme.repeatable for details
+    </meta:doc>
+
+    <ui:box>
+
+        thisbox.counter = 0;        // consecutive repetition counter
+        thisbox.interval = 100;     // repetition interval (ms)
+        thisbox.initialinterval;    // the initial interval of a repeating action
+        thisbox.repeat;             // repeating state 
+
+        interval ++= function() {
+            // return interval for counter > 0 or initialinterval otherwise
+            return counter ? cascade : initialinterval ? initialinterval : cascade;
+        }
+
+        repeat ++= function(v) {
+            if (v) {
+                // only start if previously false
+                if (!repeat) {
+                    cascade = v;
+                    ibex.thread = function() {
+                        while (repeat) {
+                            action = true;
+                            counter ++;
+                            ibex.thread.sleep(interval);
+                        }
+                    }
+                }
+            }
+            else counter = 0;
+        }
+
+    </ui:box>
+</ibex>
diff --git a/src/ibex/lib/scrollbar.t b/src/ibex/lib/scrollbar.t
new file mode 100644 (file)
index 0000000..42f4e1e
--- /dev/null
@@ -0,0 +1,167 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        Author: Charles Goodwin
+    </meta:doc>
+
+    <ui:box>
+
+        // public variables
+        thisbox.amount;
+        thisbox.hide;
+        thisbox.page;
+        thisbox.shift;
+        thisbox.slave;
+        thisbox.smart;
+
+        // theme box variables
+        thisbox.th_back;
+        thisbox.th_next;
+        thisbox.th_thumb;
+        thisbox.th_track;
+
+        // private variables
+        var listeners = {};
+        var motion;
+        var movefun1 = function(v) { th_thumb.action = true; }
+        var movefun2 = function(v) { recall["track"] = th_track.mouse[pos]; }
+        var recall = {};
+        var percent;
+
+        // attempt to shift slave by given amount
+        shift ++= function(v) {
+            motion = true;
+            slave[0][pos] = ibex.math.min(0, ibex.math.max(slave[dim] - slave[0][dim], slave[0][pos] - v));
+            syncThumb();
+            motion = false;
+        }
+
+        // set up slave
+        slave ++= function(v) {
+            v.SizeChange ++= slaveFunc;
+            v[0].PosChange ++= slaveFunc;
+            v[0].SizeChange ++= slaveFunc;
+
+            cascade = v;
+            syncThumb();
+        }
+
+        smart ++= function(v) { cascade = v; syncThumb(); }
+
+        th_back ++= function(v) { v.action ++= function(w) { shift = -1*amount; } }
+        th_next ++= function(v) { v.action ++= function(w) { shift = amount; } }
+
+        th_track ++= function(v) {
+            v.action ++= function(w) {
+                if (th_thumb[pos] > recall["track"]) shift = -1*page;
+                else if (recall["track"] > th_thumb[pos] + th_thumb[dim]) shift = page; 
+            }
+
+            v.repeat ++= function(w) {
+                if (w) { Move ++= movefun2; movefun2(); }
+                else { Move --= movefun2; recall["track"] = null; }
+            }
+
+            v.SizeChange ++= function(w) { syncThumb(); }
+        }
+
+        th_thumb ++= function(v) {
+            v.action ++= function(w) {
+                th_thumb[pos] = ibex.math.max(0,
+                                    ibex.math.min(th_track[dim] - th_thumb[dim],
+                                        recall["thumb"] + (surface.mouse[pos] - recall["start"])));
+                syncSlave();
+            }
+
+            v.Press1 ++= function(w) {
+                motion = true;
+                recall["start"] = surface.mouse[pos];
+                recall["thumb"] = th_thumb[pos];
+                surface.Move ++= movefun1;
+                surface.Release1 ++= function(w) {
+                    motion = false;
+                    surface.Move --= movefun1;
+                    surface.Release1 --= callee;
+                }
+            }
+        }
+
+        // public functions
+
+        thisbox.addListener = function(v) {
+            listeners[v] = [v, v[0]];
+            v.SizeChange ++= listenerFunc;
+            v[0].PosChange ++= listenerFunc;
+            v[0].SizeChange ++= listenerFunc;
+            syncAllListeners();
+        }
+
+        thisbox.removeListener = function(v) {
+            if (listeners[v] != null) {
+                listeners[v][0].SizeChange --= listenerFunc;
+                listeners[v][1].PosChange --= listenerFunc;
+                listeners[v][1].SizeChange --= listenerFunc;
+                listeners[v] = null;
+            }
+        }
+
+        // sync functions
+
+        var syncAllListeners = function(v) {
+            if (motion) {
+                for (key in listeners) {
+                    if (v == listeners[key][0]) continue;
+                    syncListener(listeners[key][0]);
+                }
+            }
+        }
+
+        var syncListener = function(v) {
+            percent = slave[0][pos] / (slave[dim] - slave[0][dim]);
+            if (v and v[0]) v[0][pos] = percent * (v[dim] - v[0][dim]);
+        }
+
+        var syncSlave = function() {
+            if (slave) {
+                percent = th_thumb[pos] / (th_track[dim] - th_thumb[dim]);
+                slave[0][pos] = percent * (slave[dim] - slave[0][dim]);
+            }
+        }
+
+        var syncThumb = function() {
+            if (slave == null || slave[0] == null || slave[dim] >= slave[0][dim]) {
+                if (enabled) enabled = false;
+                th_thumb[dim] = th_track[dim];
+                th_thumb[pos] = 0;
+            }
+            else {
+                if (!enabled) enabled = true;
+                th_thumb[dim] = ibex.math.min(th_track[dim], (slave[dim] / slave[0][dim]) * th_track[dim]);
+                percent = slave[0][pos] / (slave[dim] - slave[0][dim]);
+                th_thumb[pos] = ibex.math.max(0, (th_track[dim] - th_thumb[dim]) * percent);
+            }
+        }
+
+        // reusable functions
+
+        var listenerFunc = function(v) {
+            if (!motion and trapee.constrain) {
+                motion = true;
+                syncAllListeners(trapee);
+                syncSlave();
+                motion = false;
+            }
+        }
+
+        var slaveFunc = function(v) {
+            if (!motion) {
+                motion = true;
+                syncThumb();
+                syncAllListeners();
+                motion = false;
+            }
+        }
+
+    </ui:box>
+</ibex>
diff --git a/src/ibex/lib/scrollpane.t b/src/ibex/lib/scrollpane.t
new file mode 100644 (file)
index 0000000..b56a41f
--- /dev/null
@@ -0,0 +1,20 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        Author: Charles Goodwin
+    </meta:doc>
+
+    <ui:box>
+
+        thisbox.th_hscroll;
+        thisbox.th_vscroll;
+        thisbox.th_viewport;
+
+        th_viewport ++= function(v) {
+            th_hscroll.slave = v;
+            th_vscroll.slave = v;
+        }
+
+    </ui:box>
+</ibex>
diff --git a/src/ibex/lib/selectable.t b/src/ibex/lib/selectable.t
new file mode 100644 (file)
index 0000000..358fbab
--- /dev/null
@@ -0,0 +1,137 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        Author: Charles Goodwin
+
+        See ibex.theme.selectable for documentation
+
+        TODO:
+            1..n selection model with rolling selection
+    </meta:doc>
+
+    // static content
+
+    var groups = {};    // the groups of selectables
+
+    static.toGroup = function(v, oldg, g) {
+
+        // no group given, create group
+        if (3 > arguments.length) {
+            g = { members : (ibex..ibex.util.vector..newVector(v)),
+                  selected : null, selection : [] };
+            //groups[g] = g;
+            groups[g] = g;
+        }
+        // validate group
+        else if (g and groups[g] != g) {
+            ibex.log.warn("Invalid group passed to toGroup: " + g + " " + groups[g]);
+            return oldg;
+        }
+
+        // remove v from oldg
+        if (oldg and g != oldg) {
+            oldg.members.remove(v);
+
+            // clean up group info
+            if (oldg.selection[v]) v.selected = false;
+
+            // clean up groups list
+            if (!oldg.members.length) groups[oldg] = null;
+        }
+
+        // add to group
+        if (g) {
+            if (g != oldg) g.members.push(v);
+            return g;
+        }
+        else return null;
+    }
+
+    // end of static content
+
+    <ui:box>
+
+        thisbox.mixed;      // mixed status
+        thisbox.nextselect; // next group member to select
+        thisbox.prevselect; // previous group member to select
+        thisbox.selected;   // selection status
+
+        var groupref;       // internal reference to group
+
+        // group read trap
+        thisbox.group ++= function() {
+            // if no group, get one
+            if (!groupref) groupref = static.toGroup(thisbox);
+            return groupref;
+        }
+
+        // group write trap
+        thisbox.group ++= function(v) {
+            // add us to group v
+            groupref = static.toGroup(thisbox, groupref, v);
+        }
+
+        // selected read trap
+        thisbox.selected ++= function() {
+            if (mixed) return true;
+            else return cascade;
+        }
+
+        // selected write trap
+        thisbox.selected ++= function(v) {
+            if (groupref) {
+                if (v) {
+                    if (groupref.selected != thisbox) {
+                        if (groupref.selected) groupref.selected.selected = false;
+                        groupref.selected = thisbox;
+                    }
+                }
+                else if (groupref.selected == thisbox) groupref.selected = null;
+            }
+        }
+
+        // find the next selectable member
+        thisbox.nextselect ++= function() {
+            var ns = thisbox;
+            do {
+                ns = groupref.members.after(ns);
+                if (!ns) ns = groupref.members.first;
+            } while (!ns.enabled and ns != thisbox);
+            
+            return ns.enabled ? ns : null;
+        }
+
+        // find the previous selectable member
+        thisbox.prevselect ++= function() {
+            var ps = thisbox;
+            do {
+                ps = groupref.members.before(ps);
+                if (!ps) ps = groupref.members.last;
+            } while (!ps.enabled and ps != thisbox);
+
+            return ps.enabled ? ps : null;
+        }
+
+        // integration with clickable
+        action ++= function(v) { selected = true; }
+
+        // integration with clickable and focusable
+        focusable ++= function() { return cascade and (primed or selected); }
+
+        // integration with focusable
+        nextfocus ++= function() {
+            var nf = cascade;
+            while (nf.group == groupref and nf != thisbox) nf = cascade;
+            return nf;
+        }
+
+        // integration with focusable
+        prevfocus ++= function() {
+            var pf = cascade;
+            while (pf.group == groupref and pf != thisbox) pf = cascade;
+            return pf;
+        }
+
+    </ui:box>
+</ibex>
diff --git a/src/ibex/lib/slider.t b/src/ibex/lib/slider.t
new file mode 100644 (file)
index 0000000..f0507ca
--- /dev/null
@@ -0,0 +1,103 @@
+<!-- Copyright 2004 - see COPYING for details [LGPL] -->\r
+\r
+<ibex>\r
+    <meta:doc>\r
+        Author: Charles Goodwin\r
+    </meta:doc>\r
+\r
+    <ui:box>\r
+\r
+        // public variables\r
+\r
+        thisbox.interval;   // user defined interval between steps\r
+        thisbox.lowerlimit; // the lower limit of the value range\r
+        thisbox.upperlimit; // the upper limit of the value range\r
+        thisbox.step;       // the current step (integer)\r
+        thisbox.value;      // the current value\r
+\r
+        // theme box traps\r
+\r
+        thisbox.th_track;   // the track in which the slider runs\r
+        thisbox.th_handle;  // the slider handle\r
+\r
+        // private variables\r
+\r
+        var numsteps;       // the number of steps\r
+\r
+        // write trap adjust the step according to the mouse position\r
+        action ++= function(v) {\r
+            step = ibex.math.round(numsteps * (track[mousepos] - handle[dim] / 2) / (track[dim] - handle[dim]));\r
+        }\r
+\r
+        var synclimits = function(v) {\r
+            cascade = v;\r
+\r
+            // we need all of the following to be set\r
+            if (interval == null || lowerlimit == null || upperlimit == null) return;\r
+\r
+            // interval should to be a factor of (upperlimit - lowerlimit)\r
+            if ((upperlimit - lowerlimit) % interval)\r
+                ibex.println("WARNING: limit difference is not divisible by interval");\r
\r
+            // work out the number of steps\r
+            numsteps = (upperlimit - lowerlimit) / interval;\r
+        }\r
+\r
+        interval ++= synclimits;\r
+        lowerlimit ++= synclimits;\r
+        upperlimit ++= synclimits;\r
+\r
+        orient ++= function(v) {\r
+            arguments.cascade(v);\r
+            track[mindim] = 0;\r
+            track[flip(mindim)] = handle[flip(dim)];\r
+        }\r
+\r
+        step ++= function(v) {\r
+            // make sure step has a valid value\r
+            arguments.cascade((0 > v) ? 0 : (v > numsteps) ? numsteps : v);\r
+            // adjust the handle position according to the step\r
+            handle[pos] = step * (track[dim] - handle[dim]) / numsteps;\r
+        }\r
+\r
+        // read trap to return value based on current step\r
+        value ++= function() {\r
+            return ibex.math.min(lowerlimit + step * interval, upperlimit);\r
+        }\r
+\r
+        // write trap to set the step according to the given value\r
+        value ++= function(v) {\r
+            step = ibex.math.round((v - lowerlimit) / interval);\r
+        }\r
+\r
+        // theme box traps\r
+\r
+        handle ++= function(v) {\r
+            // always absolute so we can be moved\r
+            v.packed = false;\r
+\r
+            // make sure the widget always has the correct flip(dim)\r
+            v.SizeChange ++= function(v) {\r
+                track[flip(dim)] = handle[flip(dim)];\r
+            }\r
+        }\r
+\r
+        KeyPressed ++= function(v) {\r
+            if (v == "left" or v == "down") step -= 1;\r
+            else if (v == "right" or v == "up") step += 1;\r
+        }\r
+\r
+        Press1 ++= function(v) {\r
+            // activate the slider handle\r
+            var shift = surface.addEvent("_Move", thisbox, "Move");\r
+\r
+            /* argh what to do? */\r
+            if (root.Move == null) {\r
+                action = true;\r
+                root.Move = function() { action = true; }\r
+                root.Release1 = function() { root._Move = null; root._Release1 = null; }\r
+            }\r
+        }\r
+\r
+    </ui:box>\r
+</ibex>\r
diff --git a/src/ibex/lib/spin.t b/src/ibex/lib/spin.t
new file mode 100644 (file)
index 0000000..df00263
--- /dev/null
@@ -0,0 +1,59 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        Author: Charles Goodwin
+
+        FIXME: 
+            - be more restrictive of puts to value
+            - value needs to be trappable
+    </meta:doc>
+
+    <ui:box>
+
+        // public variables
+
+        thisbox.interval;   // interval by which up/down in/de-crement the result
+        thisbox.maxvalue;   // maximum value of the result
+        thisbox.minvalue;   // minimum value of the result
+        thisbox.precision;  // number of decimal places of result
+
+        var is_int;         // parse integeters or floats
+
+        // theme box variables
+
+        thisbox.th_less;   // the button to decrement
+        thisbox.th_more;   // the button to increment
+        thisbox.th_output; // the th_output for the result
+
+        // private function to get the value from a string
+        var parse = function(v) { return is_int ? ibex.math.parseInt(v) : ibex.math.parseFloat(v); }
+
+        // write trap to establish is_int based on interval
+        interval ++= function(v) { is_int = !(v % 1); }
+
+        KeyPressed ++= function(v) {
+            if (v == "down" or v == "DOWN") th_less.action = true;
+            else if (v == "up" or v == "UP") th_more.action = true;
+        }
+
+        value ++= function() { return ibex.string.parse(th_output.text); }
+
+        value ++= function(v) { th_output.text = "" + v; }
+
+        // theme box traps
+
+        th_less ++= function(v) {
+            v.action ++= function(v) {
+                th_output.text = "" + ibex.math.max(parse(th_output.text) - interval, minvalue);
+            }
+        }
+
+        th_more ++= function(v) {
+            v.action ++= function(v) {
+                th_output.text = "" + ibex.math.min(parse(th_output.text) + interval, maxvalue);
+            }
+        }
+
+    </ui:box>
+</ibex>
diff --git a/src/ibex/lib/surface.t b/src/ibex/lib/surface.t
new file mode 100644 (file)
index 0000000..61eea80
--- /dev/null
@@ -0,0 +1,33 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        Surface:
+            Applied to every new surface (frame/window)
+    </meta:doc>
+
+    <ibex.lib.redirect />
+    <ui:box>
+
+        var s = {};
+
+        // proxy to the surface object
+        thisbox.surface ++= function() { return s; };
+
+        // root.distanceTo proxy function
+        s.distanceto = function(v) { return distanceto(v); }
+
+        // access to the surface mouse object
+        s.mouse ++= function() { return thisbox.mouse; }
+
+        // redirect events to the surface object for access
+        redirectTo(surface,
+            "Click1", "Click2", "Click3",
+            "DoubleClick1", "DoubleClick2", "DoubleClick3",
+            "KeyPressed", "KeyReleased",
+            "Move", "PosChange", "SizeChange",
+            "Press1", "Press2", "Press3",
+            "Release1", "Release2", "Release3");
+
+    </ui:box>
+</ibex>
diff --git a/src/ibex/lib/tabpane.t b/src/ibex/lib/tabpane.t
new file mode 100644 (file)
index 0000000..18ad903
--- /dev/null
@@ -0,0 +1,49 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        Author: Charles Goodwin
+    </meta:doc>
+
+    <ui:box>
+
+        thisbox.th_head;
+        thisbox.th_content;
+
+        var tabgroup;
+
+        th_content ++= function(v) {
+            v.childadded ++= function(c) {
+                // create the tab if needed
+                if (!c.tab) {
+                    if (!c.tab) c.tab = ibex..ibex.widget.tab(ibex.box);
+
+                    if (!tabgroup) tabgroup = c.tab.group;
+                    else c.tab.group = tabgroup;
+                    c.tab.selected ++= function(s) {
+                        cascade = s;
+                        if (c.tab.selected and !c.visible) th_content.show = c;
+                    }
+
+                    c.tab.text = c.tabtext;
+
+                    c.tabtext ++= function(t) {
+                        c.tab.text = t;
+                    }
+                }
+
+                // place the tab
+                th_head[v.indexof(c)] = c.tab;
+            }
+
+            v.show ++= function(c) {
+                cascade = c;
+                if (c.visible and !c.tab.selected) c.tab.selected = true;
+            }
+
+            th_content --= callee;
+        }
+
+    </ui:box>
+</ibex>
diff --git a/src/ibex/lib/text/block.t b/src/ibex/lib/text/block.t
new file mode 100644 (file)
index 0000000..75feede
--- /dev/null
@@ -0,0 +1,61 @@
+<ibex xmlns:lib="ibex.lib">
+    // WARNING: more HACKs than a lumberjack
+
+    <org.ibex.theme.win2k.edit />
+    <ui:box shrink="true">
+        thisbox.splitable = true; // tells flow code that this object can be split or joined with another block
+        thisbox.block = true;     // tells text code that this object exists inside a subfocus
+
+        thisbox.split = function(w) {
+            ibex.log.info("split called");
+            var pos = ibex..ibex.lib.text.edit..static.getpos(text, w, width, font, fontsize);
+            //var pos = static.getpos(text, w, width, font, fontsize);
+
+            // give new box requested text range
+            var newbox = ibex.box;
+            ibex.log.info("split called, box made");
+            ibex..ibex.lib.text.block(newbox);
+            newbox.text = text.substring(0, pos);
+            ibex.log.info("split called, applied block template and text given");
+
+            // give this box the remaining text
+            text = text.substring(pos);
+            ibex.log.info("split called, updated old box");
+
+            return newbox;
+        }
+    </ui:box>
+
+
+    // TODO: share with ibex.lib.text.edit
+    static.getpos = function(t, pxpos, pxlen, tfont, tsize) {
+        // short circuit extremes
+        if (0 >= pxpos) return 0;
+        if (pxpos >= pxlen) return t.length;
+
+        // inital guess based on average character width
+        var guessch = ibex.math.min(t.length, ibex.math.floor(pxpos / (pxlen / t.length)));
+        var guesspx = ibex.ui.font.width(tfont, tsize, t.substring(0, guessch));
+
+        if (guesspx > pxpos) {
+            while (guesspx > pxpos) {
+                // textwidth of individual character must account for font kerning
+                guesspx -= ibex.ui.font.width(tfont, tsize, t.substring(guessch -1, guessch +1));
+                guesspx += ibex.ui.font.width(tfont, tsize, t.charAt(guessch));
+                guessch--;
+            }
+        } else if (pxpos > guesspx) {
+            while (pxpos > guesspx) {
+                guessch++;
+                if (guessch >= t.length) break;
+                guesspx += ibex.ui.font.width(tfont, tsize, t.substring(guessch -1, guessch+1));
+                guesspx -= ibex.ui.font.width(tfont, tsize, t.charAt(guessch));
+            }
+            guessch--;  // round down
+        }
+
+        return guessch;
+    }
+
+
+</ibex>
diff --git a/src/ibex/lib/text/edit.t b/src/ibex/lib/text/edit.t
new file mode 100644 (file)
index 0000000..750908d
--- /dev/null
@@ -0,0 +1,202 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+
+    // Returns number of chars the pixel position pos is into text t.
+    //
+    // Always rounds down.
+    //
+    //  t     : string -- basis for character counting
+    //  pxpos : int    -- pixel position on the text from string t
+    //  pxlen : int    -- pixel width of text t (often box width)
+    //  tfont : font   -- name of font used for width of text
+    //  tsize : int    -- size of font used for width of text
+    static.getpos = function(t, pxpos, pxlen, tfont, tsize) {
+        // short circuit extremes
+        if (0 >= pxpos) return 0;
+        if (pxpos >= pxlen) return t.length;
+
+        // inital guess based on average character width
+        var guessch = ibex.math.min(t.length, ibex.math.floor(pxpos / (pxlen / t.length)));
+        var guesspx = ibex.ui.font.width(tfont, tsize, t.substring(0, guessch));
+
+        if (guesspx > pxpos) {
+            while (guesspx > pxpos) {
+                // textwidth of individual character must account for font kerning
+                guesspx -= ibex.ui.font.width(tfont, tsize, t.substring(guessch -1, guessch +1));
+                guesspx += ibex.ui.font.width(tfont, tsize, t.charAt(guessch));
+                guessch--;
+            }
+        } else if (pxpos > guesspx) {
+            while (pxpos > guesspx) {
+                guessch++;
+                if (guessch >= t.length) break;
+                guesspx += ibex.ui.font.width(tfont, tsize, t.substring(guessch -1, guessch+1));
+                guesspx -= ibex.ui.font.width(tfont, tsize, t.charAt(guessch));
+            }
+            guessch--;  // round down
+        }
+
+        return guessch;
+    }
+
+
+    <ui:box shrink="true">
+
+        // add and remove cursor traps as the cursor box changes
+        thisbox.cur ++= function(newcur) {
+            if (cur) {
+                cur.pos  --= cur_pos;
+                cur.posx --= cur_posx_read;
+                cur.posx --= cur_posx_write;
+            }
+            if (newcur) {
+                newcur.pos  ++= cur_pos;
+                newcur.posx ++= cur_posx_read;
+                newcur.posx ++= cur_posx_write;
+            }
+        }
+
+        // add and remove selection traps as the selection box changes
+        thisbox.sel ++= function(newsel) {
+            if (sel) {
+                sel.pos1 --= sel_pos1;
+                sel.pos2 --= sel_pos2;
+            }
+            if (newsel) {
+                newsel.pos1 ++= sel_pos1;
+                newsel.pos2 ++= sel_pos2;
+            }
+        }
+
+        // designed to trap cur.pos -- updates position of the cursor
+        // based on the character position stored in cur.pos
+        var cur_pos = function(newpos) {
+            //ibex.log.info("cur.pos trap put "+newpos+", text.length="+text.length);
+            if (newpos > text.length) newpos = text.length;
+            else if (0 > newpos) newpos = 0;
+
+            if (newpos > 0) ibex.thread = function() {
+                ibex.ui.font.wait(font, fontsize, text);
+                cur.x = ibex.ui.font.width(font, fontsize, text.substring(0, newpos));
+            } else cur.x = 0;
+
+            if (focused) cur.visible = true;
+        }
+
+        // designed to trap cur.posx --
+        // returns the pixel based position of the cursor
+        var cur_posx_read = function() { return cur.x; }
+
+        // designed to trap cur.posx -- updates cur.pos
+        // based on the pixel value stored in cur.posx
+        //
+        // this two-step put to the x value is designed to normalise
+        // the position of the cursor to being between characters
+        var cur_posx_write = function(newx) {
+            // calculate the cursor position in terms of characters
+            ibex.thread = function() {
+                ibex.ui.font.wait(font, fontsize, text);
+
+                // short circuit limits
+                if (0 >= newx) { cur.pos = 0; return; }
+                if (newx > width) { cur.pos = text.length; return; }
+
+                var pos = static.getpos(text, newx, width, font, fontsize);
+
+                // getpos always rounds down see if we can get closer
+                // to the mark by skipping over a char
+                if (text.length > pos) {
+                    var diff = newx - ibex.ui.font.width(font, fontsize, text.substring(0, pos));
+                    if (diff > ibex.ui.font.width(font, fontsize, text.charAt(pos)) / 2) pos++;
+                }
+    
+                cur.pos = pos;
+            }
+        }
+
+        // designed to trap sel.pos1 -- resets the selection and
+        // prepares it to start again from the given character position
+        var sel_pos1 = function(v) {
+            sel.text = null;
+        }
+
+        // designed to trap sel.pos2 -- obtains the second selection
+        // position and 
+        var sel_pos2 = function(v) {
+            ibex.log.info("pos2 trapped, new value="+v+", (pos1="+sel.pos1+")");
+            var p1, p2;
+            if (v > sel.pos1) { p1 = sel.pos1; p2 = v; }
+            else              { p2 = sel.pos1; p1 = v; }
+
+            // update selected text
+            sel.text = text.substring(p1, p2);
+            sel.x = ibex.ui.font.width(font, fontsize, text.substring(0, p1));
+        }
+
+        // designed to be applied to thisbox.Move
+        var move = function(v) {
+            cur.posx = mouse.x;
+            ibex.thread = function() { sel.pos2 = cur.pos; }
+        }
+
+        focused ++= function(v) {
+            cur.visible = v;
+        }
+
+        Press1 ++= function(v) {
+            ibex.log.info("Press1 in ibex.lib.text");
+            cur.posx = mouse.x;
+            // TODO: enable selection
+            ibex.thread = function() {
+                sel.pos1 = cur.pos;
+                Move ++= move;
+            }
+        }
+
+        // TODO: use surface.Release1
+        Release1 ++= function(v) {
+            ibex.log.info("Release1 in ibex.lib.text");
+            Move --= move;
+        }
+
+        KeyPressed ++= function(v) {
+            ibex.log.info("KeyPressed called with value: "+v);
+
+            // TODO: check for casing and for prefix modifers (eg. C-Y, a-g)
+            if (v.length > 1) switch (v) {
+                // TODO
+                case "left":  cur.pos--; return;
+                case "C-LEFT":
+                case "c-left": return;
+
+                case "right": cur.pos++; return;
+                case "C-RIGHT":
+                case "c-right": return;
+
+                case "home":  cur.pos = 0; return;
+                case "end":   cur.pos = text.length; return;
+                case "DELETE":
+                case "back_space":
+                    text = text.substring(0, cur.pos - 1) + text.substring(cur.pos);
+                    cur.pos--;
+                    return;
+                case "BACK_SPACE":
+                case "delete":
+                    text = text.substring(0, cur.pos) + text.substring(cur.pos + 1);
+                    return;
+                case "shift":  ibex.log.warn("not-yet-implemented"); return;
+                case "alt":    ibex.log.warn("not-yet-implemented"); return;
+                case "ctrl":   ibex.log.warn("not-yet-implemented"); return;
+                case "insert": ibex.log.warn("not-yet-implemented"); return;
+                case "tab":    ibex.log.warn("not-yet-implemented"); return;
+            }
+
+            if (v.length == 1) {
+                ibex.log.info("KeyPressed resulting in text insertion of "+v);
+                text = text.substring(0, cur.pos) + v + text.substring(cur.pos);
+                cur.pos += v.length;
+            }
+        }
+   </ui:box>
+</ibex>
diff --git a/src/ibex/lib/text/flow.t b/src/ibex/lib/text/flow.t
new file mode 100644 (file)
index 0000000..cef4ba5
--- /dev/null
@@ -0,0 +1,226 @@
+<ibex>
+    <org.ibex.theme.win2k.focusable /> // HACK: should be in a better place
+    <ui:box align="topleft" fill="green" packed="false">
+        <ui:box id="content" rows="0" cols="1" shrink="true" align="topleft" fill="yellow" />
+
+        var packing = -1;
+
+        SizeChange ++= function(v) {
+            ibex.thread = function() { $content.maxwidth = thisbox.width; }
+            pack(0);
+        }
+        // TODO: align ++= function(a) { for (var i=0; $content.numchildren > i; i++) $content[i].align = a; }
+
+
+        var currentfocus = null; // HACK: for subfocus model
+        thisbox._KeyPressed ++= function(v) { 
+            if (currentfocus) currentfocus.KeyPressed = v;
+            return true;
+        }
+
+        // creates an empty row, ready for insertion into $content
+        thisbox.row = function() {
+            var b = ibex.box;
+            b.shrink = true;
+            //b.align = thisbox.align;
+            b.align = "topleft";
+
+            var packtrap = function(v) { pack($content.indexof(b)); }
+            b.SizeChange ++= packtrap;
+
+            // ------------------------------------------------------
+            // HACK: quick and dirty subfocusing for text
+
+            var block_prevfocus = function() {
+                // find prev focusable in current row
+                var index = b.indexof(trapee);
+                if (index > 0) return b[index - 1];
+
+                // look in prev row
+                var r = $content.indexof(b);
+                if (r > 0 and $content[r - 1].numchildren > 0) return $content[r - 1][($content[r - 1].numchildren)];
+            }
+            var block_nextfocus = function() {
+                ibex.log.info("block_nextfocus: finding next focus");
+                // find next focusable in current row
+                var index = b.indexof(trapee);
+                if (b.numchildren - 1 > index) return b[index + 1];
+
+                // look in next row
+                var r = $content.indexof(b);
+                if ($content.numchildren - 1 > r and $content[r + 1].numchildren > 0) return $content[r + 1][0];
+            }
+            var block_curpos = function(v) {
+                if (0 > v) {
+                    var movefocus = trapee.parent.prevfocus; // usage of HACK mentioned below
+                    if (movefocus) {
+                        trapee.parent.focused = false; movefocus.cur.pos = movefocus.text.length;
+                        movefocus.focused = true; currentfocus = movefocus;
+                    }
+                } else if (v > trapee.parent.text.length) {
+                    ibex.log.info("stepped over right-hand block boundry");
+                    var movefocus = trapee.parent.nextfocus;
+                    if (movefocus) {
+                        ibex.log.info("changing focus");
+                        trapee.parent.focused = false; movefocus.cur.pos = 0;
+                        movefocus.focused = true; currentfocus = movefocus;
+                    }
+                }
+            }
+            var block_press1 = function(c) {
+                if (currentfocus != trapee) {
+                    if (currentfocus) currentfocus.focused = false;
+                    trapee.focused = true;
+                    currentfocus = trapee;
+                }
+            }
+            b.childadded ++= function(c) {
+                c.prevfocus ++= block_prevfocus;
+                c.nextfocus ++= block_nextfocus;
+                c.cur.pos ++= block_curpos;
+                c.Press1 ++= block_press1;
+                c.cur.parent = c; // HACK: need for block_curpos above
+            }
+            b.childremoved ++= function(c) {
+                c.prevfocus --= block_prevfocus;
+                c.nextfocus --= block_nextfocus;
+                c.cur.pos --= block_curpos;
+                c.Press1 --= block_press1;
+            }
+            // ------------------------------------------------------
+
+            return b;
+        }
+
+        // HACK: clean this up conceptually
+        childadded ++= function(newc) { if (thisbox.indexof(newc) >= 0) add(newc); }
+
+        // add a block of text to the flow element
+        thisbox.add = function(b) {
+            if (1 > $content.numchildren) $content[0] = row();
+            var r = $content[$content.numchildren -1];
+
+            // HACK: for subfocus model
+            if (currentfocus) b.focused = false;
+            else { b.focused = true; currentfocus = b; }
+
+            r[r.numchildren] = b;
+        }
+
+        // launch the packNow function in a background thread
+        var pack = function(ind) {
+            if (packing == -1) {
+                packing = ind;
+                ibex.thread = packNow;
+            } else if (packing > ind) {
+                // background thread already queued, so just
+                // update location from which to start
+                packing = ind;
+            }
+        }
+
+        // pack the contents of this flow starting at row matching value of packing
+        var packNow = function() {
+            var ind = packing;
+            if (0 > ind) return;
+
+            // work through each row, packing them
+            ROW: for (; $content.numchildren > ind; ind++) {
+                ibex.log.debug("tag 2, ind="+ind);
+                var r = $content[ind];
+
+                // calculate excess width of row contents (negative to represent free space)
+                var w = 0;
+                for (var i=0; r.numchildren > i; i++) w += r[i].width;
+                w -= $content.maxwidth;
+
+                var nextr = ind+1;
+                ibex.log.debug("tag 3, w="+w+", nextr="+nextr+", $content.numchildren="+$content.numchildren);
+
+                if (0 > w and $content.numchildren > nextr) {
+                    // attempt to pack contents from next row into current row
+                    w  = -1 * w;
+
+                    // find first non-empty following row
+                    var n = $content[nextr];
+                    ibex.log.debug("tag 4, n==null?"+(n==null));
+                    while (n != null and 1 > n.numchildren and $content.numchildren > nextr) {
+                        n.thisbox = null; n = $content[nextr];
+                    }
+                    ibex.log.debug("tag 5 n.numchildren="+(n==null?-1:n.numchildren));
+                    if (n == null || 1 > n.numchildren) break ROW;
+
+                    // move up excess blocks
+                    while (w > n[0].width) {
+                        ibex.log.debug("r["+r.numchildren+"] = n[0] (n.numchildren="+n.numchildren+")");
+                        w -= n[0].width; r[r.numchildren] = n[0];
+                        debugState();
+                        while (n.numchildren == 0) {
+                            $content[nextr] = null;
+                            debugState();
+                            if (nextr >= $content.numchildren) break ROW;
+                            n = $content[nextr];
+                        }
+                    }
+
+                    ibex.log.debug("tag 6");
+
+                    // attempt to split up final block
+                    if (n.numchildren > 0 and n[0].splitable) {
+                        var splitb = n[0].split(w);
+                        if (splitb) r[r.numchildren] = splitb;
+                    }
+
+                } else if (w > 0) {
+                    // push row contents to next row
+                    if (nextr == $content.numchildren) $content[$content.numchildren] = row();
+
+                    // move off excess blocks
+                    var b;
+                    for (b = r[r.numchildren -1]; b != null and w > b.width; b = r[r.numchildren -1]) {
+                        $content[nextr][0] = b;
+                        w -= b.width;
+                    }
+
+                    if (b == null) continue ROW;
+
+                    if (b.splitable) {
+                        // attempt to split up final block
+                        var newb = b.split(b.width - w);
+                        if (newb != null) {
+                            b.thisbox = null;
+                            r[r.numchildren] = newb;
+                            $content[nextr][0] = b;
+                            continue;
+                        }
+                    }
+
+                    // split failed
+                    if (r.numchildren > 1) $content[nextr][0] = b;
+                    else ibex.log.warn("box exceeds window limit"); // FIXME: how do we handle this?
+
+                    ibex.log.debug("tag 10");
+                }
+
+            }
+
+            //ibex.log.debug(debugState());
+            packing = -1;
+        }
+
+        var debugState = function() {
+            var str = "---- DEBUG $content child="+$content.numchildren
+                + "maxwidth="+$content.width+", width="+$content.width+", height="+$content.height+"\n";
+            for (var i=0; $content.numchildren > i; i++) {
+                str += "$content["+i+"].numchildren="+$content[i].numchildren + "\n";
+                for (var j=0; $content[i].numchildren > j; j++) {
+                    str += "$content["+i+"]["+j+"] text="+$content[i][j].text
+                        + " width="+$content[i][j].width+", height="+$content[i][j].height+"\n";
+                }
+            }
+            str += "----";
+            return str;
+        }
+
+    </ui:box>
+</ibex>
diff --git a/src/ibex/theme/button.t b/src/ibex/theme/button.t
new file mode 100644 (file)
index 0000000..576a352
--- /dev/null
@@ -0,0 +1,4 @@
+<ibex xmlns:win2k="org.ibex.theme.win2k" xmlns:lib="ibex.lib">
+    <lib:clickable enabled="true" />
+    <win2k:button enabled="true" repeats="false" />
+</ibex>
diff --git a/src/ibex/theme/clickable.t b/src/ibex/theme/clickable.t
new file mode 100644 (file)
index 0000000..44e8e0a
--- /dev/null
@@ -0,0 +1,29 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns:lib="ibex.lib" xmlns:theme="ibex.theme">
+    <meta:doc>
+        Clickable:
+            A template for a clickable widget that also integrates
+            well with focusable widgets
+
+        Usage:
+            - Trap action to implement the action of your widget
+            - Trap active, hover, and normal to set the visible state
+
+        Properties:
+            action ---- : the widgets action
+            active ---- : the active state
+            activated - : when activated but not necessarily active
+            enabled --- : enables/disables widget
+            hover ----- : when the mouse hovers over the widget
+            normal ---- : the normal state of the widget
+            repeats --- : whether this is a repeating action on mousedown
+
+        See also:
+            ibex.theme.focusable
+            ibex.theme.repeatable
+    </meta:doc>
+
+    <theme:repeatable /> 
+    <lib:clickable enabled="true" repeats="false" />
+</ibex>
diff --git a/src/ibex/theme/edit.t b/src/ibex/theme/edit.t
new file mode 100644 (file)
index 0000000..2e02e53
--- /dev/null
@@ -0,0 +1,20 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        Simple text widget. Provides standard cursor and selection tools
+        for editing the text contents of this template.
+
+        Single line, single font, single size.
+
+        Designed to have focusable applied.
+
+        Properties:
+            text : string : Text to edit.
+            font : font : Font to use displaying the text.
+            fontsize : integer : Size of the font to use displaying the text.
+            textcolor : color : Color to use displaying the text.
+    </meta:doc>
+
+    <ui:box />
+</ibex>
diff --git a/src/ibex/theme/focusable.t b/src/ibex/theme/focusable.t
new file mode 100644 (file)
index 0000000..712c01a
--- /dev/null
@@ -0,0 +1,23 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="ibex.lib">
+    <meta:doc>
+        Registers a ui:box as focusable with its surface.
+
+        When a ui:box is focused, it holds the event focus for the surface
+        (capable of receiving key and mouse events).
+
+        A ui:box may have its focused state changed at any time by the
+        surface manging the focus, unless the property focusable is set to
+        false.
+
+        Properties:
+            focused : boolean : True if thisbox has the event focus.
+            focusable : boolean : True if thisbox may accept the event focus.
+
+        See also:
+            ibex.theme.surface
+    </meta:doc>
+
+    <focusable />
+</ibex>
diff --git a/src/ibex/theme/radio.t b/src/ibex/theme/radio.t
new file mode 100644 (file)
index 0000000..f548f30
--- /dev/null
@@ -0,0 +1,5 @@
+<ibex>
+    <ui:box>
+        ibex.log.warn("this shouldn't happen either");
+    </ui:box>
+</ibex>
diff --git a/src/ibex/theme/repeatable.t b/src/ibex/theme/repeatable.t
new file mode 100644 (file)
index 0000000..5edce4e
--- /dev/null
@@ -0,0 +1,19 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="ibex.lib">
+    <meta:doc>
+        Repeater:
+            Invokes an action repeatedly
+
+        Usage:
+            - Implement action += with the desired behaviour
+            - Put [true|false] to repeat to [start|stop]
+
+        Properties:
+            initialinterval - : if you want an initial pause
+            interval -------- : repeat after this many ms
+            repeat ---------- : repeating state
+    </meta:doc>
+
+    <repeatable />
+</ibex>
diff --git a/src/ibex/theme/selectable.t b/src/ibex/theme/selectable.t
new file mode 100644 (file)
index 0000000..b352073
--- /dev/null
@@ -0,0 +1,22 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="ibex.lib">
+    <meta:doc>
+        Selectable:
+            Enables a widget as part of a group of selectable widgets
+            which may be mutually selectable either exclusively or as
+            as an (optionally limited) exclusive group
+
+        Usage:
+            Group selectable widgets together by putting a group to
+            $widget.group (order is important):
+
+                $sel3.group = $sel2.group = $sel1.group;
+
+        Properties:
+            group ---- : the selection group a widget belongs to
+            selected - : if a widget is selected
+    </meta:doc>
+
+    <selectable />
+</ibex>
diff --git a/src/ibex/theme/surface.t b/src/ibex/theme/surface.t
new file mode 100644 (file)
index 0000000..b81e5a6
--- /dev/null
@@ -0,0 +1,7 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="ibex.lib">
+    <redirect />
+    <surface />
+    <focusmanager />
+</ibex>
diff --git a/src/ibex/util/group.t b/src/ibex/util/group.t
new file mode 100644 (file)
index 0000000..9419ec6
--- /dev/null
@@ -0,0 +1,48 @@
+<!-- Copyright 2003 Charles Goodwin
+     LGPL - see COPYING for details -->
+
+<ibex>
+    <meta:doc>
+        ibex.util.group
+            A utility for grouping together widgets that wish to be affiliated
+            with each other in an arbitrary fashion
+
+        Usage
+            Call ibex.util.group..newGroup((str)name) to create a new 'super
+            group' and use to ibex.util.group..syncGroup() to create and group
+            widgets together
+    </meta:doc>
+
+    // reference for super groups
+    var groups = {};
+
+    // v - widget to group
+    // s - super group
+    // g - sub group
+    memberInsert = function(v, s, g) {
+
+        // if necessary, create the supergroup
+        if (!groups[s]) groups[s] = [];
+
+        // if no subgroup specified, create one
+        if (3 > arguments.length)
+            groups[s][groups[s].length] = g = { members : ibex.util.vector..newVector([m]) };
+    }
+
+    memberPosition = function(v, s, g) {
+        /* TODO */
+    }
+
+    // v - widget to group
+    // s - super group
+    // g - sub group
+    memberRemove = function(v, s, g) {
+        /* TODO */
+    }
+
+    <ui:box>
+
+        /* TODO */
+
+    </ui:box>
+</ibex>
diff --git a/src/ibex/util/list.t b/src/ibex/util/list.t
new file mode 100644 (file)
index 0000000..b2ea065
--- /dev/null
@@ -0,0 +1,99 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        ibex.util.list
+            An ordered array for quick removal and retreival of elements.  It uses
+            binary insertion to keep the array ordered, and a binary retrieval to
+            quickly find an elements position in the ordered array.
+
+        Usage
+            Call ibex.util.list..newList() to create and return a new list, optionally
+            passing it an array of elements to initialise the list with.
+    </meta:doc>
+
+    // inserts an element at the correct position in the list
+    elementInsert = function(v, list) {
+        // initial checks to see whether position lies within the list
+        if (list[0] > v) list.unshift(v);
+        else if (v >= list[list.length - 1]) list.push(v);
+        // find insertion position in the list
+        else {
+            var low, mid = 0;
+            var end = list.length - 1;
+
+            while (true) {
+                mid = ibex.math.floor(low + (end - low) / 2);
+
+                if (list[mid] > v)
+                    if (v > list[low]) end = mid;
+                    else list.splice(low + 1, 0, [v]);
+                else if (v > list[mid]) low = mid;
+                else list.splice(mid + 1, 0, [v]);
+            }
+        }
+    }
+
+    // returns an elements position in the list
+    elementPosition = function(v, list) {
+        // initial check to see whether v is in the list
+        if (list[0] > v || v > list[list.length - 1]) return null;
+        // find our position within the list
+        else {
+            var low, mid = 0;
+            var end = list.length - 1;
+
+            while (true) {
+                mid = ibex.math.floor(low + (end - low) / 2);
+
+                if(list[mid] > v)
+                    if (v > list[low]) end = mid;
+                    else return low;
+                else if (v > list[mid])
+                    if (lost[end] > v) low = mid;
+                    else return end;
+                else return mid;
+            }
+        }
+    }
+
+
+    // removes an element from the list
+    elementRemove = function(v, list) {
+        var pos = elementPosition(v, list);
+        if (pos) list.splice(pos, 1);
+    }
+
+    // creates and returns a new list, with optional initial elements
+    newList += function(v) {
+        // create and store list
+        var nl = ibex..ibex.util.list(ibex.box);
+
+        // insert elements if given
+        if (arguments.length)
+            for (var i = 0; v.length > i; i++)
+                nl.elementInsert(v[i]);
+
+        // return newly created list
+        return nl;
+    }
+
+    <ui:box>
+
+        // store elements in this array
+        var elements = [];
+
+        // returns the length of the list
+        thisbox.length ++= function() { return elements.length; }
+
+        // inserts argument v into the list
+        thisbox.insert ++= function(v) { static.elementInsert(v, elements); cascade = null; }
+
+        // removes argument v from the list
+        thisbox.remove ++= function(v) { static.elementRemove(v, elements); cascade = null; }
+
+        // returns the position of v in the list
+        thisbox.position ++= function() { return static.elementPosition(thisbox, elements); }
+
+    </ui:box>
+</ibex>
diff --git a/src/ibex/util/queue.t b/src/ibex/util/queue.t
new file mode 100644 (file)
index 0000000..670c4f7
--- /dev/null
@@ -0,0 +1,12 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        Maintainer: 
+        Contributer:
+    </meta:doc>
+
+    <ui:box>
+
+    </ui:box>
+</ibex>
diff --git a/src/ibex/util/vector.t b/src/ibex/util/vector.t
new file mode 100644 (file)
index 0000000..ef2d81f
--- /dev/null
@@ -0,0 +1,146 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        Author: Charles Goodwin
+
+        TODO:
+            Add move(v) function
+    </meta:doc>
+
+    // start of static content
+
+    newVector = function(v) {
+        var new_vec = ibex.box;
+        ibex..ibex.util.vector(new_vec);
+        if (v) new_vec.push(v);
+        return new_vec;
+    }
+
+    // end of static content
+
+    <ui:box>
+
+        var elements = {};  // hash containing all our elements
+        var obj1;           // the first (#1) object in elements
+        var objn;           // the nth (last) object in elements
+        var count = 0;      // counts the number of elements
+
+        // private function to add to an empty elements
+        var addtoempty = function(v) {
+            elements[v] = { self: v };
+            obj1 = objn = v;
+            ++count;
+            return true;
+        }
+
+        // private function to leave elements empty
+        var makesempty = function(v) {
+            elements[v] = null;
+            obj1 = objn = null;
+            --count;
+            return true;
+        }
+
+        // read trap to return the first object in elements
+        thisbox.first ++= function() { return obj1; }
+
+        // read trap to return the last object in elements
+        thisbox.last ++= function() { return objn; }
+
+        // read trap to return the length of elements
+        thisbox.length ++= function() { return count; }
+
+        // function to return the object after v in elements
+        thisbox.after = function(v) { return elements[v].next ? elements[v].next.self : null; }
+
+        // function to return the object before v in elements
+        thisbox.before = function(v) { return elements[v].prev ? elements[v].prev.self : null; }
+
+        // function to check where elements contains v
+        thisbox.contains = function(v) { return elements[v] ? true : false; }
+
+        // function to insert v optionally after w
+        thisbox.insert = function(v, w) {
+            if (arguments.length == 1) return push(v);
+            else if (!elements[v] and elements[w]) {
+                elements[v] = { next: elements[w].next, prev: w, self: v };
+                elements[elements[w].next].prev = v;
+                elements[w].next = v;
+                ++count;
+                return true;
+            }
+            else return false;
+        }
+
+        // function to remove v
+        thisbox.remove = function(v) {
+            if (elements[v]) {
+                if (count == 1) return makesempty(v);
+                else {
+                    elements[elements[v].prev].next = elements[v].next;
+                    elements[elements[v].next].prev = elements[v].prev;
+                    elements[v] = null;
+                    --count;
+                    return true;
+                }
+            }
+            else return false;
+        }
+
+        // function to pop last object from elements
+        thisbox.pop = function() {
+            if (count == 1) return makesempty(objn);
+            else if (count) {
+                var drop = objn;
+                elements[elements[objn].prev].next = null;
+                elements[drop] = null;
+                objn = elements[elements[drop].prev].self;
+                --count;
+                return drop;
+            }
+            else return null;
+        }
+
+        // function to push v onto the end of elements
+        thisbox.push = function(v) {
+            if (!count) return addtoempty(v);
+            else if (!elements[v]) {
+                elements[v] = { prev: elements[objn], self: v };
+                elements[objn].next = elements[v];
+                objn = v;
+                ++count;
+                return true;
+            }
+            return false;
+        }
+
+        // function to shift first object from elements
+        thisbox.shift = function() {
+            if (count == 1) return makesempty(obj1);
+            else if (count) {
+                var drop = obj1;
+                elements[elements[drop].next].prev = null;
+                elements[drop] = null;
+                obj1 = elements[elements[drop].next].self;
+                --count;
+                return drop;
+            }
+            else return null;
+        }
+
+        // function to unshfit v onto the front of elements
+        thisbox.unshift = function(v) {
+            if (!count) return addtoempty(v);
+            else if (!elements[v]) {
+                elements[v] = { next: elements[obj1], self: v };
+                elements[obj1].prev = elements[v];
+                obj1 = v;
+                ++count;
+                return true;
+            }
+            else return false;
+        }
+
+    </ui:box>
+</ibex>
diff --git a/src/ibex/widget/bevel.t b/src/ibex/widget/bevel.t
new file mode 100644 (file)
index 0000000..4c2ad6e
--- /dev/null
@@ -0,0 +1,31 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="org.ibex.theme.win2k">
+    <meta:doc>
+        <name>Basic Button</name>
+        <desc>Creates a button widget</desc>
+        <usage>
+            Put to the text property of a button for a basic label,
+            or simply wrap the button around more complex content
+        </usage>
+    </meta:doc>
+
+    <redirect />
+    <margin redirect="$content">
+        <bevel form="up" id="widget">
+            <pad id="pad">
+                <ui:box id="content" />
+            </pad>
+        </bevel>
+
+        // glue code
+
+        redirectTo($content, "fill", "text", "textcolor");
+        redirectTo($pad, "padding", "padding-left", "padding-right", "padding-top", "padding-bottom");
+        redirectTo($widget, "form");
+
+        if ($widget.margin) thisbox.margin = $widget.margin;
+        if ($widget.padding) $content.padding = $widget.padding;
+        
+    </margin>
+</ibex>
diff --git a/src/ibex/widget/border.t b/src/ibex/widget/border.t
new file mode 100644 (file)
index 0000000..ffd105d
--- /dev/null
@@ -0,0 +1,21 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns:theme="org.ibex.theme.win2k">
+    <meta:doc>
+        <name>Border Widget</name>
+        <desc>Adds a border to your boxes</desc>
+        <usage>
+            For Images: 
+                Putting to image will create a border from the contents of
+                a directory of the same name; the directory is expected
+                to contain 8 images - nw, nn, ne, ww, ee, sw, ss, se -
+                which combine to form the border
+
+            Fill and depth:
+                putting to fill and depth will create a border the colour
+                of fill and the size of depth
+        </usage>
+    </meta:doc>
+
+    <theme:border />
+</ibex>
diff --git a/src/ibex/widget/button.t b/src/ibex/widget/button.t
new file mode 100644 (file)
index 0000000..99c49ee
--- /dev/null
@@ -0,0 +1,35 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="org.ibex.theme.win2k">
+    <meta:doc>
+        <name>Basic Button</name>
+        <desc>Creates a button widget</desc>
+        <usage>
+            Put to the text property of a button for a basic label,
+            or simply wrap the button around more complex content
+        </usage>
+    </meta:doc>
+
+    <redirect />
+    <margin redirect="$content" shrink="true">
+        <button id="widget">
+            .clickable(thisbox);
+            .focusable(thisbox);
+            <pad id="pad">
+                <ui:box id="content" />
+            </pad>
+        </button>
+
+        // glue code
+
+        redirectTo($content, "text", "textcolor");
+        redirectTo($pad, "padding", "padding-left", "padding-right", "padding-top", "padding-bottom");
+        redirectTo($widget, "action", "enabled", "fill");
+
+        if ($widget.margin) thisbox.margin = $widget.margin;
+        if ($widget.padding) $pad.padding = $widget.padding;
+
+        $widget.textcolor ++= function(v) { $content.textcolor = v; }
+        
+    </margin>
+</ibex>
diff --git a/src/ibex/widget/cardpane.t b/src/ibex/widget/cardpane.t
new file mode 100644 (file)
index 0000000..b3b53d8
--- /dev/null
@@ -0,0 +1,9 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        Author: Charles Goodwin
+    </meta:doc>
+
+    <org.ibex.theme.win2k.cardpane />
+</ibex>
diff --git a/src/ibex/widget/check.t b/src/ibex/widget/check.t
new file mode 100644 (file)
index 0000000..1717692
--- /dev/null
@@ -0,0 +1,35 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="org.ibex.theme.win2k">
+    <meta:doc>
+        <name>Check Box</name>
+        <desc>Creates a check box widget</desc>
+        <usage>
+            Put to the text property of a check for a basic label,
+            or simply wrap the check around more complex content
+        </usage>
+    </meta:doc>
+
+    <redirect />
+    <margin redirect="$content" shrink="true">
+        <check id="widget">
+            .clickable(thisbox);
+            .focusable(thisbox);
+            <pad id="pad">
+                <ui:box id="content" />
+            </pad>
+        </check>
+
+        // glue code
+
+        redirectTo($content, "text", "textcolor");
+        redirectTo($pad, "padding", "padding-left", "padding-right", "padding-top", "padding-bottom");
+        redirectTo($widget, "enabled", "fill", "group", "selected");
+
+        if ($widget.margin) thisbox.margin = $widget.margin;
+        if ($widget.padding) $pad.padding = $widget.padding;
+
+        $widget.textcolor ++= function(v) { $content.textcolor = v; }
+
+    </margin>
+</ibex>
diff --git a/src/ibex/widget/label.t b/src/ibex/widget/label.t
new file mode 100644 (file)
index 0000000..2574938
--- /dev/null
@@ -0,0 +1,22 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns:theme="org.ibex.theme.win2k">
+    <meta:doc>
+        <name>Label Widget</name>
+        <desc>A label with text flow and inline images</desc>
+        <author>David Crawshaw</author>
+    </meta:doc>
+
+    <theme:redirect />
+    <theme:focusable />
+    <theme:margin focusable="true" focused="false" vshrink="true">
+        <theme:pad id="pad">
+            <theme:edit id="widget" />
+        </theme:pad>
+
+        // glue code
+        redirectTo($pad, "padding", "padding-left", "padding-right", "padding-top", "padding-bottom");
+        redirectTo($widget, "focusable", "focused", "text", "textcolor", "font", "fontsize", "editable");
+
+    </theme:margin>
+</ibex>
diff --git a/src/ibex/widget/margin.t b/src/ibex/widget/margin.t
new file mode 100644 (file)
index 0000000..6471586
--- /dev/null
@@ -0,0 +1,9 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        Author: Charles Goodwin
+    </meta:doc>
+
+    <ibex.theme.margin />
+</ibex>
diff --git a/src/ibex/widget/pad.t b/src/ibex/widget/pad.t
new file mode 100644 (file)
index 0000000..f924ec4
--- /dev/null
@@ -0,0 +1,9 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        Author: Charles Goodwin
+    </meta:doc>
+
+    <ibex.theme.pad />
+</ibex>
diff --git a/src/ibex/widget/radio.t b/src/ibex/widget/radio.t
new file mode 100644 (file)
index 0000000..abf0f40
--- /dev/null
@@ -0,0 +1,36 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="org.ibex.theme.win2k">
+    <meta:doc>
+        <name>Radio Button</name>
+        <desc>Creates a radio button widget</desc>
+        <usage>
+            Put to the text property of a radio for a basic label,
+            or simply wrap the radio around more complex content
+        </usage>
+    </meta:doc>
+    
+    <redirect />
+    <margin redirect="$content" shrink="true">
+        <radio id="widget">
+            .clickable(thisbox);
+            .focusable(thisbox);
+            .selectable(thisbox);
+            <pad id="pad">
+                <ui:box id="content" />
+            </pad>
+        </radio>
+
+        // glue code
+
+        redirectTo($content, "text", "textcolor");
+        redirectTo($pad, "padding", "padding-left", "padding-right", "padding-top", "padding-bottom");
+        redirectTo($widget, "enabled", "fill", "group", "selected");
+
+        if ($widget.margin) thisbox.margin = $widget.margin;
+        if ($widget.padding) $pad.padding = $widget.padding;
+
+        $widget.textcolor ++= function(v) { $content.textcolor = v; }
+
+    </margin>
+</ibex>
diff --git a/src/ibex/widget/redirect.t b/src/ibex/widget/redirect.t
new file mode 100644 (file)
index 0000000..94dc3bc
--- /dev/null
@@ -0,0 +1,16 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns:theme="org.ibex.theme.win2k">
+    <meta:doc>
+        <name>Property Redirect</name>
+        <desc>A widget used to redirect properties to another box</desc>
+        <usage>
+            Pass the a {property:target} list to addredirect:
+                $redirect.addredirect = {p1:$t1, p2:$t2, p3:$t3};
+
+            Similarly use delredirect to remove redirections.
+        </usage>
+    </meta:doc>
+
+    <theme:redirect />
+</ibex>
diff --git a/src/ibex/widget/scrollbar.t b/src/ibex/widget/scrollbar.t
new file mode 100644 (file)
index 0000000..c4dd11d
--- /dev/null
@@ -0,0 +1,34 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns:theme="org.ibex.theme.win2k">
+    <meta:doc>
+        <name>Scrollbar</name>
+        <desc>A scrollbar widget, commonly found in scrollpanes</desc>
+        <usage>
+            Put to the text property of a button for a basic label,
+            or simply wrap the button around more complex content
+        </usage>
+    </meta:doc>
+
+    <theme:redirect />
+    <theme:margin redirect="null" orient="horizontal">
+        <theme:scrollbar id="widget">
+            ibex..org.ibex.theme.win2k.polarizable(thisbox);
+        </theme:scrollbar>
+
+        // glue code
+
+        redirectTo($widget, "orient", "slave");
+
+        if ($widget.margin) thisbox.margin = $widget.margin;
+        if ($widget.padding) $content.padding = $widget.padding;
+
+        //var shrfun = function(v) { ibex.log.info(trapname); }
+        //$widget.shrink ++= shrfun;
+        //$widget.hshrink ++= shrfun;
+        //$widget.vshrink ++= shrfun;
+
+        $widget.SizeChange ++= function(v) { thisbox.hshrink = $widget.hshrink; thisbox.vshrink = $widget.vshrink; }
+    </theme:margin>
+</ibex>
diff --git a/src/ibex/widget/scrollpane.t b/src/ibex/widget/scrollpane.t
new file mode 100644 (file)
index 0000000..5de8419
--- /dev/null
@@ -0,0 +1,30 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns:theme="org.ibex.theme.win2k">
+    <meta:doc>
+        <name>Scrollbar</name>
+        <desc>A scrollbar widget, commonly found in scrollpanes</desc>
+        <usage>
+            Put to the text property of a button for a basic label,
+            or simply wrap the button around more complex content
+        </usage>
+    </meta:doc>
+
+    <theme:redirect />
+    <theme:margin redirect="$content">
+        <theme:scrollpane id="widget">
+            <theme:pad id="pad">
+                <ui:box id="content" />
+            </theme:pad>
+        </theme:scrollpane>
+
+        // glue code
+
+        addredirect = { fill: $content };
+        addredirect = { padding: $pad };
+
+        if ($widget.margin) thisbox.margin = $widget.margin;
+        if ($widget.padding) $pad.padding = $widget.padding;
+    </theme:margin>
+</ibex>
diff --git a/src/ibex/widget/slider.t b/src/ibex/widget/slider.t
new file mode 100644 (file)
index 0000000..65b101c
--- /dev/null
@@ -0,0 +1,31 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="org.ibex.theme.win2k">
+    <meta:doc>
+        <name>Slider Widget</name>
+        <desc>Creates a sliding value selector</desc>
+        <usage>
+        </usage>
+    </meta:doc>
+
+    <redirect />
+    <margin redirect="null" shrink="true">
+        <pad id="pad">
+            <slider id="widget">
+                .clickable(thisbox);
+                .focusable(thisbox);
+            </slider>
+        </pad>
+
+        // glue code
+
+        redirectTo($pad, "fill", "padding", "padding-left", "padding-right", "padding-top", "padding-bottom");
+        redirectTo($widget, "enabled", "maxvalue", "minvalue", "value");
+
+        if ($widget.margin) thisbox.margin = $widget.margin;
+        if ($widget.padding) $pad.padding = $widget.padding;
+
+        $widget.textcolor ++= function(v) { $content.textcolor = v; }
+        
+    </margin>
+</ibex>
diff --git a/src/ibex/widget/spin.t b/src/ibex/widget/spin.t
new file mode 100644 (file)
index 0000000..fe57053
--- /dev/null
@@ -0,0 +1,32 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="org.ibex.theme.win2k">
+    <meta:doc>
+        <name>Spin Widget</name>
+        <desc>Creates a spin value selector</desc>
+        <usage>
+        </usage>
+    </meta:doc>
+
+    <redirect />
+    <margin redirect="null" shrink="true">
+        <spin id="widget">
+            .clickable(thisbox);
+            .focusable(thisbox);
+            th_output = $content;
+            <pad id="pad">
+                <ui:box id="content" />
+            </pad>
+        </spin>
+
+        // glue code
+
+        redirectTo($content, "textcolor");
+        redirectTo($pad, "fill", "padding", "padding-left", "padding-right", "padding-top", "padding-bottom");
+        redirectTo($widget, "enabled", "interval", "maxvalue", "minvalue", "value");
+
+        if ($widget.margin) thisbox.margin = $widget.margin;
+        if ($widget.padding) $pad.padding = $widget.padding;
+    </margin>
+</ibex>
diff --git a/src/ibex/widget/tab.t b/src/ibex/widget/tab.t
new file mode 100644 (file)
index 0000000..f590d34
--- /dev/null
@@ -0,0 +1,34 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="org.ibex.theme.win2k">
+    <meta:doc>
+        <name>Tab</name>
+        <desc>A tab for use in a tabpane</desc>
+        <usage>
+            Tabpane automatically manages tabs, so for most circumstances
+            you will not be wanting to use this widget manually
+        </usage>
+    </meta:doc>
+
+    <redirect />
+    <margin redirect="$content" selected="false">
+        <tab id="widget">
+            .clickable(thisbox);
+            .focusable(thisbox);
+            .selectable(thisbox);
+            <pad id="pad">
+                <ui:box id="content" />
+            </pad>
+        </tab>
+
+        // glue code
+
+        redirectTo($content, "text", "textcolor");
+        redirectTo($pad, "fill", "padding", "padding-left", "padding-right", "padding-top", "padding-bottom");
+        redirectTo($widget, "group", "selected");
+
+        if ($widget.margin) thisbox.margin = $widget.margin;
+        if ($widget.padding) $pad.padding = $widget.padding;
+
+    </margin>
+</ibex>
diff --git a/src/ibex/widget/tabpane.t b/src/ibex/widget/tabpane.t
new file mode 100644 (file)
index 0000000..58205ff
--- /dev/null
@@ -0,0 +1,32 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="org.ibex.theme.win2k">
+    <meta:doc>
+        <name>Tabpane</name>
+        <desc>Creates a tabpane wigdet for tabbing between views</desc>
+        <usage>
+            Each child box of a tabpane is used as a card with a tab,
+            with the tabtext property of each card defining tab text
+        </usage>
+    </meta:doc>
+
+    <redirect />
+    <margin redirect="$content">
+        <tabpane id="widget">
+            th_content = $content;
+            <pad id="pad">
+                <cardpane id="content" />
+            </pad>
+        </tabpane>
+
+        // glue code
+
+        redirectTo($content, "show");
+        redirectTo($pad, "padding", "padding-left", "padding-right", "padding-top", "padding-bottom");
+        redirectTo($widget, "fill");
+        
+        if ($widget.margin) thisbox.margin = $widget.margin;
+        if ($widget.padding) $pad.padding = $widget.padding;
+
+    </margin>
+</ibex>
diff --git a/src/ibex/widget/textarea.t b/src/ibex/widget/textarea.t
new file mode 100644 (file)
index 0000000..3186223
--- /dev/null
@@ -0,0 +1,7 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <box>
+        ibex..ibex.theme.textarea(.focusable(thisbox));
+    </box>
+</ibex>
diff --git a/src/ibex/widget/textfield.t b/src/ibex/widget/textfield.t
new file mode 100644 (file)
index 0000000..c510097
--- /dev/null
@@ -0,0 +1,14 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns:theme="org.ibex.theme.win2k">
+    <theme:redirect />
+    <theme:focusable />
+    <theme:margin fill="white" vshrink="true">
+        <theme:bevel id="pad" form="down">
+            <theme:edit id="widget" />
+        </theme:bevel>
+
+        redirectTo($pad, "padding", "padding-left", "padding-right", "padding-top", "padding-bottom");
+        redirectTo($widget, "focusable", "focused", "text", "textcolor", "font", "fontsize");
+    </theme:margin>
+</ibex>
diff --git a/src/main.t b/src/main.t
new file mode 100644 (file)
index 0000000..e90daec
--- /dev/null
@@ -0,0 +1,26 @@
+<ibex>
+    <org.ibex.test.alpha1 />
+/*
+        ibex.log.info("Starting widget test suite...");
+
+        // clone the ibex resource to create our environment
+        var ibex_world = ibex.clone(ibex);
+        ibex.log.info("Successfully cloned environment");
+
+        // clone the ibex namespace within our environent
+        var ibex_res = ibex.clone(ibex..ibex);
+        ibex.log.info("Succesfully did resource clone");
+
+        // trap the theme namespace to return the desired theme
+        ibex_res.theme ++= function() { return ibex..org.ibex.theme.win2k; }
+        ibex.log.info("Successfully themed environment");
+
+        // trap the ibex namespace to return our themed namespace
+        ibex_world..ibex ++= function() { return ibex_res; }
+        ibex.log.info("Successfully themed resource environment");
+
+        // instantiate our application in the themed environment
+        ibex_world..org.ibex.test.alpha(ibex.box);
+        ibex.log.info("Successfully initiated test suite");
+*/
+</ibex>
diff --git a/src/org/ibex/games/checkers/main.t b/src/org/ibex/games/checkers/main.t
new file mode 100644 (file)
index 0000000..cd8a792
--- /dev/null
@@ -0,0 +1,5 @@
+<ibex>\r
+       <ui:box text="Checkers">\r
+       \r
+       </ui:box>\r
+</ibex>
\ No newline at end of file
diff --git a/src/org/ibex/games/chess/main.t b/src/org/ibex/games/chess/main.t
new file mode 100644 (file)
index 0000000..f0d7560
--- /dev/null
@@ -0,0 +1,5 @@
+<ibex>\r
+       <ui:box text="Chess">\r
+       \r
+       </ui:box>\r
+</ibex>
\ No newline at end of file
diff --git a/src/org/ibex/games/reversi/board.t b/src/org/ibex/games/reversi/board.t
new file mode 100644 (file)
index 0000000..d54115b
--- /dev/null
@@ -0,0 +1,19 @@
+<ibex  xmlns:theme="ibex.theme"  
+       xmlns="org.ibex.theme.win2k" 
+       xmlns:games="org.ibex.games"
+       xmlns:reversi="org.ibex.games.reversi">
+<ui:box cols="8" >
+for (var i = 1; i lt 9; i++) {
+  for (var j= 1; j lt 9;j++) {
+    
+ thisbox[thisbox.numchildren] = ibex.box;
+ var child = ibex..org.ibex.games.reversi.square(thisbox[thisbox.numchildren - 1]);
+   child.boardx=i;
+   child.boardy=j;
+   child.pos=j + (i -1) * 8; 
+  }
+}
+
+
+</ui:box>
+</ibex>
\ No newline at end of file
diff --git a/src/org/ibex/games/reversi/dark_stone.png b/src/org/ibex/games/reversi/dark_stone.png
new file mode 100644 (file)
index 0000000..c2fa2c0
Binary files /dev/null and b/src/org/ibex/games/reversi/dark_stone.png differ
diff --git a/src/org/ibex/games/reversi/light_stone.png b/src/org/ibex/games/reversi/light_stone.png
new file mode 100644 (file)
index 0000000..0e64bc9
Binary files /dev/null and b/src/org/ibex/games/reversi/light_stone.png differ
diff --git a/src/org/ibex/games/reversi/main.t b/src/org/ibex/games/reversi/main.t
new file mode 100644 (file)
index 0000000..eb8df44
--- /dev/null
@@ -0,0 +1,26 @@
+<ibex  xmlns:theme="ibex.theme"  \r
+       xmlns="ibex.widget"\r
+       xmlns:games="org.ibex.games"\r
+       xmlns:reversi="org.ibex.games.reversi">\r
+\r
+       <ui:box cols="3" shrink="false">\r
+       <ui:box fill="white" shrink="false"/>\r
+       <ui:box fill="white" shrink="false"/>\r
+       <ui:box fill="white" shrink="false"/>\r
+       <ui:box fill="white" shrink="false" cols="1">\r
+               <button text="New Game" >\r
+               Press1 ++= function(f) {\r
+                 ibex.log.info("starting new game");\r
+//               $reversiboard[31].fill=".org.ibex.games.reversi.dark_stone";\r
+               }\r
+               </button>\r
+\r
+       </ui:box>\r
+       <reversi:board fill="white"/>\r
+       <ui:box fill="white" shrink="false"/>\r
+       <ui:box fill="white" shrink="false"/>\r
+       <ui:box fill="white" shrink="false"/>\r
+       <ui:box fill="white" shrink="false"/>\r
+       <ui:box/>\r
+       </ui:box>\r
+</ibex>
\ No newline at end of file
diff --git a/src/org/ibex/games/reversi/square.t b/src/org/ibex/games/reversi/square.t
new file mode 100644 (file)
index 0000000..9c5a7f3
--- /dev/null
@@ -0,0 +1,33 @@
+<ibex  xmlns:theme="ibex.theme"  \r
+       xmlns="org.ibex.theme.win2k" \r
+       xmlns:games="org.ibex.games"\r
+       xmlns:reversi="org.ibex.games.reversi">\r
+\r
+<ui:box shrink="true" fill="black">\r
+Press1 ++= function (f) {\r
+ibex.log.info("caught click: " + f + " on box");\r
+ibex.log.info("color is: " + thisbox.color);\r
+}\r
+\r
+pos ++= function(p)\r
+{\r
+//if both are even or both are odd, be lighter color\r
+if ( (thisbox.boardx/2 == ibex.math.round(thisbox.boardx/2) and\r
+     thisbox.boardy/2 == ibex.math.round(thisbox.boardy/2)) or\r
+     (thisbox.boardx/2 != ibex.math.round(thisbox.boardx/2) and\r
+     thisbox.boardy/2 != ibex.math.round(thisbox.boardy/2))\r
+      )  {\r
+  thisbox.fill="#1E9393";\r
+  } \r
+else {\r
+  thisbox.fill="#0D8080";\r
+  }\r
+}\r
+\r
+<bevel form="up">\r
+<ui:box width="50" height="50" />\r
+\r
+\r
+</bevel>\r
+</ui:box>\r
+</ibex>
\ No newline at end of file
diff --git a/src/org/ibex/sampler/clipboard.t b/src/org/ibex/sampler/clipboard.t
new file mode 100644 (file)
index 0000000..ca5677e
--- /dev/null
@@ -0,0 +1,8 @@
+<ibex xmlns:widget="org.ibex.theme.win2k" xmlns="org.ibex.test">
+  <ui:box cols="1">
+    
+    <ui:box cols="1" text="no text widget, no copy"/>
+    <ui:box cols="1" text="no text widget, no paste"/>
+  </ui:box> 
+</ibex>
+
diff --git a/src/org/ibex/sampler/color_picker.t b/src/org/ibex/sampler/color_picker.t
new file mode 100644 (file)
index 0000000..079f156
--- /dev/null
@@ -0,0 +1,6 @@
+<ibex xmlns:widget="org.ibex.theme.win2k" xmlns="org.ibex.test">
+  <ui:box cols="1">
+    <ui:box cols="1" text="no color picker"/>
+  </ui:box> 
+</ibex>
+
diff --git a/src/org/ibex/sampler/dialog.t b/src/org/ibex/sampler/dialog.t
new file mode 100644 (file)
index 0000000..47088d4
--- /dev/null
@@ -0,0 +1,38 @@
+<ibex xmlns:widget="org.ibex.theme.win2k" xmlns="org.ibex.test">
+  <ui:box cols="3">
+    
+    <ui:box cols="1">
+      <ui:box text="no tree widget">
+      </ui:box>
+      <ui:box height="4" fill="black"/>
+      <ui:box>
+        <ui:box cols="3">
+          <ui:box text="Group"/>
+          <ui:box shrink="true" cols="1">
+            $r2.group = $r1.group;
+            $r3.group = $r1.group;
+            $r4.group = $r1.group;
+            // r1.group = $r2.group = $r3.group = $r4;
+            <radio text="radio button 1" id="r1"/>
+            <radio text="radio button 2" id="r2"/>
+            <radio text="radio button 3" id="r3"/>
+            <radio text="radio button 4" id="r4"/>
+          </ui:box>
+          <ui:box cols="1">
+            <check text="checkbox 1"/>
+            <check text="checkbox 2"/>
+            <check text="checkbox 3"/>
+            <check text="checkbox 4"/>
+          </ui:box>
+        </ui:box>
+      </ui:box>
+    </ui:box>
+    
+    <ui:box width="4" fill="black"/> 
+    <ui:box>
+      <ui:box text="none of these widgets work yet">    
+      </ui:box> 
+    </ui:box>
+  </ui:box>
+</ibex>
+
diff --git a/src/org/ibex/sampler/fonts.t b/src/org/ibex/sampler/fonts.t
new file mode 100644 (file)
index 0000000..85270f8
--- /dev/null
@@ -0,0 +1,5 @@
+<ibex xmlns:widget="org.ibex.theme.win2k" xmlns="org.ibex.test">
+  <ui:box cols="1">
+    <ui:box cols="1" text="how do you get a list of available fonts?"/>
+  </ui:box> 
+</ibex>
\ No newline at end of file
diff --git a/src/org/ibex/sampler/html.t b/src/org/ibex/sampler/html.t
new file mode 100644 (file)
index 0000000..647ab5e
--- /dev/null
@@ -0,0 +1,9 @@
+<ibex xmlns:widget="org.ibex.theme.win2k" xmlns="org.ibex.test">
+  <ui:box cols="1">
+    <ui:box cols="1" text="no text widget"/>  
+    <ui:box cols="1">
+      <button text="Update HTML"/>
+    </ui:box>
+    <ui:box cols="1" text="no html widget"/>
+  </ui:box> 
+</ibex>
\ No newline at end of file
diff --git a/src/org/ibex/sampler/spreadsheet.t b/src/org/ibex/sampler/spreadsheet.t
new file mode 100644 (file)
index 0000000..a90294b
--- /dev/null
@@ -0,0 +1,5 @@
+<ibex xmlns:widget="org.ibex.theme.win2k" xmlns="org.ibex.test">
+  <ui:box cols="1">
+    <ui:box cols="1" text="lack of a text widget makes a spreadsheet difficult"/>
+  </ui:box> 
+</ibex>
\ No newline at end of file
diff --git a/src/org/ibex/sampler/transparency.t b/src/org/ibex/sampler/transparency.t
new file mode 100644 (file)
index 0000000..e68f197
--- /dev/null
@@ -0,0 +1,5 @@
+<ibex xmlns:widget="org.ibex.theme.win2k" xmlns="org.ibex.test">
+  <ui:box cols="1">
+    <ui:box cols="1" text="not a clue how to implement draggable, transparent images"/>
+  </ui:box> 
+</ibex>
diff --git a/src/org/ibex/sampler/window_manager_interaction.t b/src/org/ibex/sampler/window_manager_interaction.t
new file mode 100644 (file)
index 0000000..e8fbd93
--- /dev/null
@@ -0,0 +1,19 @@
+<ibex xmlns:widget="org.ibex.theme.win2k" xmlns="org.ibex.test">
+  <ui:box cols="3">
+
+    <ui:box cols="1">
+      <button text="Minimize"/>
+      Press1 ++= function (f) {
+      ibex.log.info("minimizing window");
+      root.Minimized=true;
+      }
+      <button text="Maximize"/>
+      <button text="Unminimize"/>
+      <button text="UnMaximize"/>
+    </ui:box>
+    <ui:box cols="1" width="5" fill="black"/>
+    <ui:box cols="1" fill="white" text="no widget = no status">
+    </ui:box> 
+  </ui:box>
+</ibex>
+
diff --git a/src/org/ibex/test/alpha1.t b/src/org/ibex/test/alpha1.t
new file mode 100644 (file)
index 0000000..715397b
--- /dev/null
@@ -0,0 +1,74 @@
+<ibex xmlns:theme="ibex.theme" xmlns="ibex.widget">
+    <theme:surface />
+    <ui:box cols="1" fill="#d4d0c8" maxwidth="400" maxheight="300">
+
+        ibex.ui.frame = thisbox;
+
+        // $r4.group = $r3.group = $r2.group = $r1.group;
+        $r2.group = $r1.group;
+        $r3.group = $r1.group;
+        $r4.group = $r1.group;
+
+        $bg.fill ++= function(v) {
+            cascade = v;
+            if (v == "white") $r1.selected = true;
+            else if (v == "red") $r2.selected = true;
+            else if (v == "green") $r3.selected = true;
+            else if (v == "blue") $r4.selected = true;
+            else if (v == null and $r1.group.selected) $r1.group.selected.selected = false;
+        }
+
+        $b1.action ++= function(v) {
+            if ($r1.group.selected and $r1.group.selected.nextselect)
+                $r1.group.selected.nextselect.selected = true;
+            else for (var i=0; $radios.numchildren > i; i++)
+                if ($radios[i].enabled) { $radios[i].selected = true; break; }
+        }
+        
+        $b2.action ++= function(v) {
+            var targets = [];
+            for (var i=0; 4 > i; i++) if ($radios[i].enabled) targets[targets.length] = $radios[i];
+
+            if (targets.length > 0) {
+                var n = ibex.math.floor(targets.length * ibex.math.random());
+                targets[n].selected = true;
+            }
+            else ibex.log.info("No enabled colors to choose from!");
+        }
+
+        $b3.action ++= function(v) { $bg.fill = null; }
+
+        $c1.selected ++= function(v) { $r1.enabled = !v; }
+        $c2.selected ++= function(v) { $r2.enabled = !v; }
+        $c3.selected ++= function(v) { $r3.enabled = !v; }
+        $c4.selected ++= function(v) { $r4.enabled = !v; }
+
+        $r1.selected ++= function(v) { if (v and $bg.fill != "#ffffff") $bg.fill = "white"; }
+        $r2.selected ++= function(v) { if (v and $bg.fill != "#ff0000") $bg.fill = "red"; }
+        $r3.selected ++= function(v) { if (v and $bg.fill != "#008000") $bg.fill = "green"; }
+        $r4.selected ++= function(v) { if (v and $bg.fill != "#0000ff") $bg.fill = "blue"; }
+
+        <ui:box>
+            <ui:box id="buttons" cols="1">
+                <button id="b1" margin="10 5 0 5" text="cycle" />
+                <button id="b2" margin="10 5 0 5" text="random" />
+                <button id="b3" margin="10 5 0 5" text="reset" />
+            </ui:box>
+
+            <ui:box id="checks" cols="1">
+                <check id="c1" margin="10 5 0 5" text="disable white button" />
+                <check id="c2" margin="10 5 0 5" text="disable red button" />
+                <check id="c3" margin="10 5 0 5" text="disable green button" />
+                <check id="c4" margin="10 5 0 5" text="disable blue button" />
+            </ui:box>
+            <ui:box id="radios" cols="1">
+                <radio id="r1" margin="10 5 0 5" text="white bg" />
+                <radio id="r2" margin="10 5 0 5" text="red bg" />
+                <radio id="r3" margin="10 5 0 5" text="green bg" />
+                <radio id="r4" margin="10 5 0 5" text="blue bg" />
+            </ui:box>
+        </ui:box>
+        <bevel id="bg" form="down" margin="10" />
+    </ui:box>
+</ibex>
diff --git a/src/org/ibex/test/alpha2.t b/src/org/ibex/test/alpha2.t
new file mode 100644 (file)
index 0000000..0f1e549
--- /dev/null
@@ -0,0 +1,27 @@
+<ibex xmlns:widget="ibex.widget" xmlns:theme="ibex.theme">
+    <theme:surface />
+    <ui:box fill="#d4d0c8" maxwidth="200" maxheight="200">
+        ibex.ui.frame = thisbox;
+        ibex.log.info($c.clip);
+        <widget:scrollpane fill="white" margin="10" padding="10">
+            <ui:box id="c" cols="4" width="800" height="800">
+                <ui:box fill="black" />
+                <ui:box fill="red" />
+                <ui:box fill="green" />
+                <ui:box fill="blue" />
+                <ui:box fill="blue" />
+                <ui:box fill="black" />
+                <ui:box fill="red" />
+                <ui:box fill="green" />
+                <ui:box fill="green" />
+                <ui:box fill="blue" />
+                <ui:box fill="black" />
+                <ui:box fill="red" />
+                <ui:box fill="red" />
+                <ui:box fill="green" />
+                <ui:box fill="blue" />
+                <ui:box fill="black" />
+            </ui:box>
+        </widget:scrollpane>
+    </ui:box>
+</ibex>
diff --git a/src/org/ibex/test/button.t b/src/org/ibex/test/button.t
new file mode 100644 (file)
index 0000000..0b265f4
--- /dev/null
@@ -0,0 +1,6 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns:theme="org.ibex.theme.win2k">
+    <theme:clickable />
+    <theme:button />
+</ibex>
diff --git a/src/org/ibex/test/check.t b/src/org/ibex/test/check.t
new file mode 100644 (file)
index 0000000..9874bde
--- /dev/null
@@ -0,0 +1,7 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns:lib="xml.lib" xmlns="org.ibex.theme.win2k">
+    <clickable />
+    <focusable />
+    <check />
+</ibex>
diff --git a/src/org/ibex/test/clickable.t b/src/org/ibex/test/clickable.t
new file mode 100644 (file)
index 0000000..0ff7088
--- /dev/null
@@ -0,0 +1,13 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="ibex.theme">
+    <repeatable />
+    <clickable />
+    <ui:box>
+        ibex.log.info("Applying clickable test widget");
+        normal ++= function(v) { fill="white"; }
+        hover ++= function(v) { fill="blue"; }
+        active ++= function(v) { fill="red"; }
+        action ++= function(v) { ibex.log.info("Action fired"); }
+    </ui:box/>
+</ibex>
diff --git a/src/org/ibex/test/flow.t b/src/org/ibex/test/flow.t
new file mode 100644 (file)
index 0000000..c5a62b8
--- /dev/null
@@ -0,0 +1,14 @@
+<ibex xmlns:theme="org.ibex.theme.win2k" xmlns:lib="ibex.lib" xmlns:libtext="ibex.lib.text">
+    <ui:box maxwidth="300" maxheight="300">
+        ibex.ui.frame = thisbox;
+
+        <libtext:flow>
+            <lib:text.block text="Hello " />
+            <lib:text.block text="World," />
+            <lib:text.block text="this is a test " />
+            <lib:text.block text="of the " />
+            <lib:text.block text="Emergency Broadcast "/>
+            <lib:text.block text="System."/>
+        </libtext:flow>
+    </ui:box>
+</ibex>
diff --git a/src/org/ibex/test/label.t b/src/org/ibex/test/label.t
new file mode 100644 (file)
index 0000000..d4293b4
--- /dev/null
@@ -0,0 +1,12 @@
+<ibex xmlns:widget="ibex.widget" xmlns:theme="ibex.theme">
+    <theme:surface />
+    <ui:box cols="1" fill="#d4d0c8" maxwidth="400" maxheight="200">
+        ibex.ui.frame = thisbox;
+
+        <ui:box rows="1">
+            <ui:box />
+            <widget:label fontsize="20" text="Hello World, this is a test." />
+            <ui:box />
+        </ui:box>
+    </ui:box>
+</ibex>
diff --git a/src/org/ibex/test/main.t b/src/org/ibex/test/main.t
new file mode 100644 (file)
index 0000000..7f93937
--- /dev/null
@@ -0,0 +1,21 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns:lib="ibex.lib" xmlns:test="org.ibex.test">
+    <lib:surface />
+    <lib:eventmanager />
+    <lib:focusmanager />
+    <ui:box minwidth="200" minheight="200" cols="3" fill="black">
+        ibex.log.info("Loading widget test");
+        ibex.ui.frame = thisbox;
+
+        <ui:box/>
+        <ui:box/>
+        <ui:box/>
+        <ui:box/>
+        <test:clickable />
+        <ui:box/>
+        <ui:box/>
+        <ui:box/>
+        <ui:box/>
+    </ui:box>
+</ibex>
diff --git a/src/org/ibex/test/radio.t b/src/org/ibex/test/radio.t
new file mode 100644 (file)
index 0000000..061bc13
--- /dev/null
@@ -0,0 +1,7 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns:lib="xml.lib" xmlns="org.ibex.theme.win2k">
+    <clickable />
+    <selectable />
+    <radio />
+</ibex>
diff --git a/src/org/ibex/test/tab.t b/src/org/ibex/test/tab.t
new file mode 100644 (file)
index 0000000..9970d75
--- /dev/null
@@ -0,0 +1,5 @@
+<ibex xmlns="org.ibex.theme.win2k">
+    <clickable />
+    <selectable />
+    <tab />
+</ibex>
diff --git a/src/org/ibex/test/tabtest.t b/src/org/ibex/test/tabtest.t
new file mode 100644 (file)
index 0000000..a0e3630
--- /dev/null
@@ -0,0 +1,27 @@
+<ibex xmlns="org.ibex.theme.win2k" xmlns:theme="ibex.theme">
+    <theme:surface />
+    <ui:box fill="#d4d0c8" maxwidth="200" maxheight="200">
+
+        ibex.ui.frame = thisbox;
+        
+        <tabpane>
+            <ui:box tabtext="testfoo">
+                <ui:box text="left">
+                    <spin value="0" step="1" />
+                </ui:box>
+                <ui:box text="right">
+                    <spin value="0" step="5" />
+                </ui:box>
+            </ui:box>
+            <ui:box tabtext="test1">
+                <ui:box text="test1 content" />
+            </ui:box>
+            <ui:box tabtext="test2">
+                <ui:box text="test2 content" />
+            </ui:box>
+            <ui:box tabtext="test3">
+                <ui:box text="test3 content" />
+            </ui:box>
+        </tabpane>
+    </ui:box>
+</ibex>
diff --git a/src/org/ibex/test/text.t b/src/org/ibex/test/text.t
new file mode 100644 (file)
index 0000000..65f8434
--- /dev/null
@@ -0,0 +1,9 @@
+<ibex xmlns:widget="ibex.widget">
+    <ui:box rows="1" fill="#d4d0c8" minwidth="400" minheight="300">
+        ibex.ui.frame = thisbox;
+
+        <ui:box />
+        <widget:textfield fontsize="20" text="Hello" />
+        <ui:box />
+    </ui:box>
+</ibex>
diff --git a/src/org/ibex/theme/base/bevel.t b/src/org/ibex/theme/base/bevel.t
new file mode 100644 (file)
index 0000000..e25f6fc
--- /dev/null
@@ -0,0 +1,7 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <ui:box>
+        
+    </ui:box>
+</ibex>
diff --git a/src/org/ibex/theme/base/border-img.t b/src/org/ibex/theme/base/border-img.t
new file mode 100644 (file)
index 0000000..0cfe393
--- /dev/null
@@ -0,0 +1,47 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        Author: Charles Goodwin
+
+        TODO:
+            - make border accept values other than resources
+            - border-left/right/top/bottom
+            - take more than one argument to border like CSS
+    </meta:doc>
+
+    <ui:box rows="3" redirect="$content">
+
+        border ++= function(v) {
+            if (typeof(v) == "object") {
+                $nw.fill = v["nw"];
+                $nn.fill = v["nn"];
+                $ne.fill = v["ne"];
+                $ww.fill = v["ww"];
+                $ee.fill = v["ee"];
+                $sw.fill = v["sw"];
+                $ss.fill = v["ss"];
+                $se.fill = v["se"];
+            }
+            // border string
+            else {
+            }
+        }
+
+        // top row
+        <ui:box id="nw" shrink="true" />
+        <ui:box id="ww" hshrink="true" />
+        <ui:box id="sw" shrink="true" />
+
+        // middle row
+        <ui:box id="nn" vshrink="true" />
+        <ui:box id="content" />
+        <ui:box id="ss" vshrink="true" />
+
+        // bottom row
+        <ui:box id="ne" shrink="true" />
+        <ui:box id="ee" hshrink="true" />
+        <ui:box id="se" shrink="true" />
+        
+    </ui:box>
+</ibex>
diff --git a/src/org/ibex/theme/base/clickable.t b/src/org/ibex/theme/base/clickable.t
new file mode 100644 (file)
index 0000000..1485647
--- /dev/null
@@ -0,0 +1,5 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="ibex.lib">
+    <clickable enabled="true" interval="100" repeats="false" />
+</ibex>
diff --git a/src/org/ibex/theme/base/focusable.t b/src/org/ibex/theme/base/focusable.t
new file mode 100644 (file)
index 0000000..a8d263e
--- /dev/null
@@ -0,0 +1,5 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="ibex.lib">
+    <focusable enabled="true" focusable="true" />
+</ibex>
diff --git a/src/org/ibex/theme/base/margin.t b/src/org/ibex/theme/base/margin.t
new file mode 100644 (file)
index 0000000..cc0ee06
--- /dev/null
@@ -0,0 +1,57 @@
+<!-- Copyleft 2004  see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        Author: Charles Goodwin
+
+        TODO:
+            - ? differentiate between pt and px
+            - ? proper child and property redirection
+    </meta:doc>
+
+    <ui:box redirect="$content">
+
+        thisbox.margin = 0;
+        thisbox["margin-top"] = 0;
+        thisbox["margin-right"] = 0;
+        thisbox["margin-bottom"] = 0;
+        thisbox["margin-left"] = 0;
+
+        margin ++= function(v) {
+            var p = v.split(' ');
+
+            if (p.length == 1) {
+                thisbox["margin-top"] = v;
+                thisbox["margin-right"] = v;
+                thisbox["margin-bottom"] = v;
+                thisbox["margin-left"] = v;
+            }
+            else if (p.length == 2) {
+                thisbox["margin-top"] = p[0];
+                thisbox["margin-right"] = p[1];
+                thisbox["margin-bottom"] = p[0];
+                thisbox["margin-left"] = p[1];
+            }
+            else if (p.length == 4) {
+                thisbox["margin-top"] = p[0];
+                thisbox["margin-right"] = p[1];
+                thisbox["margin-bottom"] = p[2];
+                thisbox["margin-left"] = p[3];
+            }
+            else ibex.log.warn("Invalid number of values for margin: " + p.length);
+        }
+
+        thisbox["margin-top"] ++= function(v) { $top.height = v; }
+        thisbox["margin-right"] ++= function(v) { $right.width = v; }
+        thisbox["margin-bottom"] ++= function(v) { $bottom.height = v; }
+        thisbox["margin-left"] ++= function(v) { $left.width = v; }
+
+        <ui:box id="left" width="0" />
+        <ui:box cols="1">
+            <ui:box id="top" height="0" />
+            <ui:box id="content" />
+            <ui:box id="bottom" height="0" />
+        </ui:box>
+        <ui:box id="right" width="0" />
+    </ui:box>
+</ibex>
diff --git a/src/org/ibex/theme/base/pad.t b/src/org/ibex/theme/base/pad.t
new file mode 100644 (file)
index 0000000..8a155eb
--- /dev/null
@@ -0,0 +1,57 @@
+<!-- Copyleft 2004  see COPYING for details [LGPL] -->
+
+<ibex>
+    <meta:doc>
+        Author: Charles Goodwin
+
+        TODO:
+            - ? differentiate between pt and px
+            - ? proper child and property redirection
+    </meta:doc>
+
+    <ui:box redirect="$content">
+
+        thisbox.padding = 0;
+        thisbox["padding-top"] = 0;
+        thisbox["padding-right"] = 0;
+        thisbox["padding-bottom"] = 0;
+        thisbox["padding-left"] = 0;
+
+        padding ++= function(v) {
+            var p = v.split(' ');
+
+            if (p.length == 1) {
+                thisbox["padding-top"] = v;
+                thisbox["padding-right"] = v;
+                thisbox["padding-bottom"] = v;
+                thisbox["padding-left"] = v;
+            }
+            else if (p.length == 2) {
+                thisbox["padding-top"] = p[0];
+                thisbox["padding-right"] = p[1];
+                thisbox["padding-bottom"] = p[0];
+                thisbox["padding-left"] = p[1];
+            }
+            else if (p.length == 4) {
+                thisbox["padding-top"] = p[0];
+                thisbox["padding-right"] = p[1];
+                thisbox["padding-bottom"] = p[2];
+                thisbox["padding-left"] = p[3];
+            }
+            else ibex.log.warn("Invalid number of values for padding: " + p.length);
+        }
+
+        thisbox["padding-top"] ++= function(v) { $top.height = v; }
+        thisbox["padding-right"] ++= function(v) { $right.width = v; }
+        thisbox["padding-bottom"] ++= function(v) { $bottom.height = v; }
+        thisbox["padding-left"] ++= function(v) { $left.width = v; }
+
+        <ui:box id="left" width="0" />
+        <ui:box cols="1">
+            <ui:box id="top" height="0" />
+            <ui:box id="content" />
+            <ui:box id="bottom" height="0" />
+        </ui:box>
+        <ui:box id="right" width="0" />
+    </ui:box>
+</ibex>
diff --git a/src/org/ibex/theme/base/selectable.t b/src/org/ibex/theme/base/selectable.t
new file mode 100644 (file)
index 0000000..a5d0d75
--- /dev/null
@@ -0,0 +1,5 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="ibex.lib">
+    <selectable />
+</ibex>
diff --git a/src/org/ibex/theme/win2k/bevel.t b/src/org/ibex/theme/win2k/bevel.t
new file mode 100644 (file)
index 0000000..6137d2f
--- /dev/null
@@ -0,0 +1,11 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="org.ibex.theme.win2k" xmlns:base="org.ibex.theme.base">
+    <meta:doc>
+        <author>Charles Goodwin</author>
+    </meta:doc>
+
+    <base:border-img>
+        thisbox.form ++= function(v) { if (v != cascade) border = .image["bevel" + v]; }
+    </base:border-img>
+</ibex>
diff --git a/src/org/ibex/theme/win2k/border.t b/src/org/ibex/theme/win2k/border.t
new file mode 100644 (file)
index 0000000..359f52b
--- /dev/null
@@ -0,0 +1,6 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="org.ibex.theme.base">
+    <border-img />
+    <ui:box />
+</ibex>
diff --git a/src/org/ibex/theme/win2k/button.t b/src/org/ibex/theme/win2k/button.t
new file mode 100644 (file)
index 0000000..c6a95b5
--- /dev/null
@@ -0,0 +1,19 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="org.ibex.theme.win2k">
+    <bevel redirect="$content" padding="5 10">
+
+        active ++= function(v) { form = "down"; }
+
+        enabled ++= function(v) { textcolor = v ? "#000000" : "#888888"; }
+
+        focused ++= function(v) { cascade = v; normal = true; }
+
+        var normal_fun = function(v) { form = "up"; }
+
+        hover ++= normal_fun;
+        normal ++= normal_fun;
+
+        <ui:box id="content" />
+    </bevel>
+</ibex>
diff --git a/src/org/ibex/theme/win2k/cardpane.t b/src/org/ibex/theme/win2k/cardpane.t
new file mode 100644 (file)
index 0000000..41c725b
--- /dev/null
@@ -0,0 +1,9 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="ibex.lib">
+    <meta:doc>
+        Author: Charles Goodwin
+    </meta:doc>
+
+    <cardpane />
+</ibex>
diff --git a/src/org/ibex/theme/win2k/check.t b/src/org/ibex/theme/win2k/check.t
new file mode 100644 (file)
index 0000000..76c0daa
--- /dev/null
@@ -0,0 +1,37 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="org.ibex.theme.win2k">
+    <ui:box redirect="$content" align="center" padding="0 5">
+
+        action ++= function(v) { selected = !selected; }
+
+        active ++= function(v) { $bg.fill = "#d4d0c8"; }
+
+        enabled ++= function(v) {
+            $bg.fill = v ? "#ffffff" : "#d4d0c8";
+            textcolor = v ? "#000000" : "#888888";
+        }
+
+        focused ++= function(v) { cascade = v; fill = focused ? "#aaa" : null; }
+
+        var setbg = function(v) { $bg.fill = "#ffffff"; }
+        hover ++= setbg;
+        normal ++= setbg;
+
+        mixed ++= function(v) {
+            if (v) {
+                $check.fill = .image.check_mixed;
+                $check.visible = true;
+            }
+        }
+
+        selected ++= function(v) { cascade = v; $check.visible = selected; }
+
+        <bevel form="down" width="14" height="14">
+            <ui:box id="bg" fill="white">
+                <ui:box id="check" fill=".image.check" shrink="true" visible="false" />
+            </ui:box>
+        </bevel>
+        <ui:box id="content" />
+    </ui:box>
+</ibex>
diff --git a/src/org/ibex/theme/win2k/clickable.t b/src/org/ibex/theme/win2k/clickable.t
new file mode 100644 (file)
index 0000000..1485647
--- /dev/null
@@ -0,0 +1,5 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="ibex.lib">
+    <clickable enabled="true" interval="100" repeats="false" />
+</ibex>
diff --git a/src/org/ibex/theme/win2k/draggable.t b/src/org/ibex/theme/win2k/draggable.t
new file mode 100644 (file)
index 0000000..55dbfb9
--- /dev/null
@@ -0,0 +1,7 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex>
+    <ui:box>
+        ibex..ibex.lib.draggable(thisbox);
+    </ui:box>
+</ibex>
diff --git a/src/org/ibex/theme/win2k/edit.t b/src/org/ibex/theme/win2k/edit.t
new file mode 100644 (file)
index 0000000..affda0f
--- /dev/null
@@ -0,0 +1,23 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns:lib="ibex.lib">
+    <lib:text.edit />
+    <ui:box>
+        // TODO: move these boxes into static so they're shared amongst text
+        //       widgets. as the gains from this are minimal and the static
+        //       selection stuff will require quite a bit of fancy footwork,
+        //       this is put off until Nitrogen core is *at least* as fast as
+        //       Lithium was.
+        <ui:box id="cur" packed="false" width="1" x="0" y="0" pos="0" fill="black" align="topleft" />
+        <ui:box id="sel" packed="false" shrink="true" pos1="0" pos2="0" fill="blue" textcolor="white" align="topleft" />
+
+        thisbox.cur = $cur;
+        thisbox.sel = $sel;
+
+        font ++= function(v) { $sel.font = v; }
+        fontsize ++= function(v) { $sel.fontsize = v; }
+
+        // TODO: move to static (later); see above note
+        ibex.thread = function() {while (true) { if (focused) cur.visible = !cur.visible; ibex.thread.sleep(800); } }
+    </ui:box>
+</ibex>
diff --git a/src/org/ibex/theme/win2k/focusable.t b/src/org/ibex/theme/win2k/focusable.t
new file mode 100644 (file)
index 0000000..5b98d29
--- /dev/null
@@ -0,0 +1,5 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="ibex.lib">
+    <focusable focusable="true" />
+</ibex>
diff --git a/src/org/ibex/theme/win2k/image/arrowdown.png b/src/org/ibex/theme/win2k/image/arrowdown.png
new file mode 100644 (file)
index 0000000..ba348d1
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/arrowdown.png differ
diff --git a/src/org/ibex/theme/win2k/image/arrowleft.png b/src/org/ibex/theme/win2k/image/arrowleft.png
new file mode 100644 (file)
index 0000000..57433c3
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/arrowleft.png differ
diff --git a/src/org/ibex/theme/win2k/image/arrowright.png b/src/org/ibex/theme/win2k/image/arrowright.png
new file mode 100644 (file)
index 0000000..625676e
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/arrowright.png differ
diff --git a/src/org/ibex/theme/win2k/image/arrowup.png b/src/org/ibex/theme/win2k/image/arrowup.png
new file mode 100644 (file)
index 0000000..a86786e
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/arrowup.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevel1down/ee.png b/src/org/ibex/theme/win2k/image/bevel1down/ee.png
new file mode 100644 (file)
index 0000000..76725af
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevel1down/ee.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevel1down/ne.png b/src/org/ibex/theme/win2k/image/bevel1down/ne.png
new file mode 100644 (file)
index 0000000..fb98942
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevel1down/ne.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevel1down/nn.png b/src/org/ibex/theme/win2k/image/bevel1down/nn.png
new file mode 100644 (file)
index 0000000..32dcd05
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevel1down/nn.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevel1down/nw.png b/src/org/ibex/theme/win2k/image/bevel1down/nw.png
new file mode 100644 (file)
index 0000000..b96e751
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevel1down/nw.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevel1down/se.png b/src/org/ibex/theme/win2k/image/bevel1down/se.png
new file mode 100644 (file)
index 0000000..e81a8f2
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevel1down/se.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevel1down/ss.png b/src/org/ibex/theme/win2k/image/bevel1down/ss.png
new file mode 100644 (file)
index 0000000..93205b6
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevel1down/ss.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevel1down/sw.png b/src/org/ibex/theme/win2k/image/bevel1down/sw.png
new file mode 100644 (file)
index 0000000..03cf682
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevel1down/sw.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevel1down/ww.png b/src/org/ibex/theme/win2k/image/bevel1down/ww.png
new file mode 100644 (file)
index 0000000..beedab3
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevel1down/ww.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevel1up/ee.png b/src/org/ibex/theme/win2k/image/bevel1up/ee.png
new file mode 100644 (file)
index 0000000..beedab3
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevel1up/ee.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevel1up/ne.png b/src/org/ibex/theme/win2k/image/bevel1up/ne.png
new file mode 100644 (file)
index 0000000..fb98942
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevel1up/ne.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevel1up/nn.png b/src/org/ibex/theme/win2k/image/bevel1up/nn.png
new file mode 100644 (file)
index 0000000..93205b6
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevel1up/nn.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevel1up/nw.png b/src/org/ibex/theme/win2k/image/bevel1up/nw.png
new file mode 100644 (file)
index 0000000..e81a8f2
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevel1up/nw.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevel1up/se.png b/src/org/ibex/theme/win2k/image/bevel1up/se.png
new file mode 100644 (file)
index 0000000..b96e751
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevel1up/se.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevel1up/ss.png b/src/org/ibex/theme/win2k/image/bevel1up/ss.png
new file mode 100644 (file)
index 0000000..32dcd05
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevel1up/ss.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevel1up/sw.png b/src/org/ibex/theme/win2k/image/bevel1up/sw.png
new file mode 100644 (file)
index 0000000..03cf682
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevel1up/sw.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevel1up/ww.png b/src/org/ibex/theme/win2k/image/bevel1up/ww.png
new file mode 100644 (file)
index 0000000..76725af
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevel1up/ww.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelabove/ee.png b/src/org/ibex/theme/win2k/image/bevelabove/ee.png
new file mode 100644 (file)
index 0000000..eee90f3
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelabove/ee.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelabove/ne.png b/src/org/ibex/theme/win2k/image/bevelabove/ne.png
new file mode 100644 (file)
index 0000000..2a75f48
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelabove/ne.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelabove/nn.png b/src/org/ibex/theme/win2k/image/bevelabove/nn.png
new file mode 100644 (file)
index 0000000..f06f199
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelabove/nn.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelabove/nw.png b/src/org/ibex/theme/win2k/image/bevelabove/nw.png
new file mode 100644 (file)
index 0000000..a2fb68a
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelabove/nw.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelabove/se.png b/src/org/ibex/theme/win2k/image/bevelabove/se.png
new file mode 100644 (file)
index 0000000..acbb6aa
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelabove/se.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelabove/ss.png b/src/org/ibex/theme/win2k/image/bevelabove/ss.png
new file mode 100644 (file)
index 0000000..ce6f18a
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelabove/ss.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelabove/sw.png b/src/org/ibex/theme/win2k/image/bevelabove/sw.png
new file mode 100644 (file)
index 0000000..b628ea3
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelabove/sw.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelabove/ww.png b/src/org/ibex/theme/win2k/image/bevelabove/ww.png
new file mode 100644 (file)
index 0000000..cbd01e6
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelabove/ww.png differ
diff --git a/src/org/ibex/theme/win2k/image/beveldown/ee.png b/src/org/ibex/theme/win2k/image/beveldown/ee.png
new file mode 100644 (file)
index 0000000..3945a2b
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/beveldown/ee.png differ
diff --git a/src/org/ibex/theme/win2k/image/beveldown/ne.png b/src/org/ibex/theme/win2k/image/beveldown/ne.png
new file mode 100644 (file)
index 0000000..33fd079
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/beveldown/ne.png differ
diff --git a/src/org/ibex/theme/win2k/image/beveldown/nn.png b/src/org/ibex/theme/win2k/image/beveldown/nn.png
new file mode 100644 (file)
index 0000000..dfb1306
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/beveldown/nn.png differ
diff --git a/src/org/ibex/theme/win2k/image/beveldown/nw.png b/src/org/ibex/theme/win2k/image/beveldown/nw.png
new file mode 100644 (file)
index 0000000..4a20a0b
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/beveldown/nw.png differ
diff --git a/src/org/ibex/theme/win2k/image/beveldown/se.png b/src/org/ibex/theme/win2k/image/beveldown/se.png
new file mode 100644 (file)
index 0000000..ba15c0b
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/beveldown/se.png differ
diff --git a/src/org/ibex/theme/win2k/image/beveldown/ss.png b/src/org/ibex/theme/win2k/image/beveldown/ss.png
new file mode 100644 (file)
index 0000000..f995cba
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/beveldown/ss.png differ
diff --git a/src/org/ibex/theme/win2k/image/beveldown/sw.png b/src/org/ibex/theme/win2k/image/beveldown/sw.png
new file mode 100644 (file)
index 0000000..b7a5e0d
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/beveldown/sw.png differ
diff --git a/src/org/ibex/theme/win2k/image/beveldown/ww.png b/src/org/ibex/theme/win2k/image/beveldown/ww.png
new file mode 100644 (file)
index 0000000..62f52aa
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/beveldown/ww.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelflat/ee.png b/src/org/ibex/theme/win2k/image/bevelflat/ee.png
new file mode 100644 (file)
index 0000000..89a5aa2
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelflat/ee.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelflat/ne.png b/src/org/ibex/theme/win2k/image/bevelflat/ne.png
new file mode 100644 (file)
index 0000000..9404f10
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelflat/ne.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelflat/nn.png b/src/org/ibex/theme/win2k/image/bevelflat/nn.png
new file mode 100644 (file)
index 0000000..961938c
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelflat/nn.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelflat/nw.png b/src/org/ibex/theme/win2k/image/bevelflat/nw.png
new file mode 100644 (file)
index 0000000..66bf61e
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelflat/nw.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelflat/se.png b/src/org/ibex/theme/win2k/image/bevelflat/se.png
new file mode 100644 (file)
index 0000000..65c7e14
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelflat/se.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelflat/ss.png b/src/org/ibex/theme/win2k/image/bevelflat/ss.png
new file mode 100644 (file)
index 0000000..1429fd2
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelflat/ss.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelflat/sw.png b/src/org/ibex/theme/win2k/image/bevelflat/sw.png
new file mode 100644 (file)
index 0000000..748df80
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelflat/sw.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelflat/ww.png b/src/org/ibex/theme/win2k/image/bevelflat/ww.png
new file mode 100644 (file)
index 0000000..2e55447
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelflat/ww.png differ
diff --git a/src/org/ibex/theme/win2k/image/beveltabtop/ee.png b/src/org/ibex/theme/win2k/image/beveltabtop/ee.png
new file mode 100644 (file)
index 0000000..07bd21f
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/beveltabtop/ee.png differ
diff --git a/src/org/ibex/theme/win2k/image/beveltabtop/ne.png b/src/org/ibex/theme/win2k/image/beveltabtop/ne.png
new file mode 100644 (file)
index 0000000..fbcff37
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/beveltabtop/ne.png differ
diff --git a/src/org/ibex/theme/win2k/image/beveltabtop/nn.png b/src/org/ibex/theme/win2k/image/beveltabtop/nn.png
new file mode 100644 (file)
index 0000000..625b178
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/beveltabtop/nn.png differ
diff --git a/src/org/ibex/theme/win2k/image/beveltabtop/nw.png b/src/org/ibex/theme/win2k/image/beveltabtop/nw.png
new file mode 100644 (file)
index 0000000..510abc5
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/beveltabtop/nw.png differ
diff --git a/src/org/ibex/theme/win2k/image/beveltabtop/se.png b/src/org/ibex/theme/win2k/image/beveltabtop/se.png
new file mode 100644 (file)
index 0000000..18be705
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/beveltabtop/se.png differ
diff --git a/src/org/ibex/theme/win2k/image/beveltabtop/ss.png b/src/org/ibex/theme/win2k/image/beveltabtop/ss.png
new file mode 100644 (file)
index 0000000..7937435
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/beveltabtop/ss.png differ
diff --git a/src/org/ibex/theme/win2k/image/beveltabtop/sw.png b/src/org/ibex/theme/win2k/image/beveltabtop/sw.png
new file mode 100644 (file)
index 0000000..b6c41d8
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/beveltabtop/sw.png differ
diff --git a/src/org/ibex/theme/win2k/image/beveltabtop/ww.png b/src/org/ibex/theme/win2k/image/beveltabtop/ww.png
new file mode 100644 (file)
index 0000000..325a35e
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/beveltabtop/ww.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelup/ee.png b/src/org/ibex/theme/win2k/image/bevelup/ee.png
new file mode 100644 (file)
index 0000000..2d6c155
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelup/ee.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelup/ne.png b/src/org/ibex/theme/win2k/image/bevelup/ne.png
new file mode 100644 (file)
index 0000000..c1001cb
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelup/ne.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelup/nn.png b/src/org/ibex/theme/win2k/image/bevelup/nn.png
new file mode 100644 (file)
index 0000000..13f8d5a
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelup/nn.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelup/nw.png b/src/org/ibex/theme/win2k/image/bevelup/nw.png
new file mode 100644 (file)
index 0000000..34bb015
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelup/nw.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelup/se.png b/src/org/ibex/theme/win2k/image/bevelup/se.png
new file mode 100644 (file)
index 0000000..580bfec
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelup/se.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelup/ss.png b/src/org/ibex/theme/win2k/image/bevelup/ss.png
new file mode 100644 (file)
index 0000000..d59e19f
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelup/ss.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelup/sw.png b/src/org/ibex/theme/win2k/image/bevelup/sw.png
new file mode 100644 (file)
index 0000000..72bd27f
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelup/sw.png differ
diff --git a/src/org/ibex/theme/win2k/image/bevelup/ww.png b/src/org/ibex/theme/win2k/image/bevelup/ww.png
new file mode 100644 (file)
index 0000000..bdaadb2
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/bevelup/ww.png differ
diff --git a/src/org/ibex/theme/win2k/image/check.png b/src/org/ibex/theme/win2k/image/check.png
new file mode 100644 (file)
index 0000000..f176c78
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/check.png differ
diff --git a/src/org/ibex/theme/win2k/image/check_highlighted.png b/src/org/ibex/theme/win2k/image/check_highlighted.png
new file mode 100644 (file)
index 0000000..1a1eadf
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/check_highlighted.png differ
diff --git a/src/org/ibex/theme/win2k/image/check_mixed.png b/src/org/ibex/theme/win2k/image/check_mixed.png
new file mode 100644 (file)
index 0000000..39421a7
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/check_mixed.png differ
diff --git a/src/org/ibex/theme/win2k/image/radio.png b/src/org/ibex/theme/win2k/image/radio.png
new file mode 100644 (file)
index 0000000..f7116b7
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/radio.png differ
diff --git a/src/org/ibex/theme/win2k/image/radio_highlighted.png b/src/org/ibex/theme/win2k/image/radio_highlighted.png
new file mode 100644 (file)
index 0000000..738437d
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/radio_highlighted.png differ
diff --git a/src/org/ibex/theme/win2k/image/radio_mixed.png b/src/org/ibex/theme/win2k/image/radio_mixed.png
new file mode 100644 (file)
index 0000000..5932f96
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/radio_mixed.png differ
diff --git a/src/org/ibex/theme/win2k/image/radiobg.png b/src/org/ibex/theme/win2k/image/radiobg.png
new file mode 100644 (file)
index 0000000..19b0e64
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/radiobg.png differ
diff --git a/src/org/ibex/theme/win2k/image/radiobg_active.png b/src/org/ibex/theme/win2k/image/radiobg_active.png
new file mode 100644 (file)
index 0000000..cf1fca4
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/radiobg_active.png differ
diff --git a/src/org/ibex/theme/win2k/image/scrollbg.png b/src/org/ibex/theme/win2k/image/scrollbg.png
new file mode 100644 (file)
index 0000000..09602e0
Binary files /dev/null and b/src/org/ibex/theme/win2k/image/scrollbg.png differ
diff --git a/src/org/ibex/theme/win2k/margin.t b/src/org/ibex/theme/win2k/margin.t
new file mode 100644 (file)
index 0000000..c4cbd13
--- /dev/null
@@ -0,0 +1,5 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="org.ibex.theme.base">
+    <margin />
+</ibex>
diff --git a/src/org/ibex/theme/win2k/pad.t b/src/org/ibex/theme/win2k/pad.t
new file mode 100644 (file)
index 0000000..4e61a05
--- /dev/null
@@ -0,0 +1,5 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="org.ibex.theme.base">
+    <pad />
+</ibex>
diff --git a/src/org/ibex/theme/win2k/polarizable.t b/src/org/ibex/theme/win2k/polarizable.t
new file mode 100644 (file)
index 0000000..e6330b3
--- /dev/null
@@ -0,0 +1,6 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="ibex.lib">
+    <meta:doc>Author: Charles Goodwin</meta:doc>
+    <polarizable />
+</ibex>
diff --git a/src/org/ibex/theme/win2k/radio.t b/src/org/ibex/theme/win2k/radio.t
new file mode 100644 (file)
index 0000000..f221785
--- /dev/null
@@ -0,0 +1,32 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="org.ibex.theme.win2k">
+    <ui:box redirect="$content" align="center" padding="0 5">
+
+        var fill1 = .image.radiobg;
+        var fill2 = .image.radiobg_active;
+
+        active ++= function(v) { if ($bg.fill != fill2) $bg.fill = fill2; }
+
+        enabled ++= function(v) {
+            $bg.fill = v ? fill1 : fill2;
+            textcolor = v ? "#000000" : "#888888";
+        }
+
+        focused ++= function(v) { cascade = v; fill = focused ? "#aaa" : null; }
+
+        var normal_fun = function(v) { if ($bg.fill != fill1) $bg.fill = fill1; }
+        hover ++= normal_fun;
+        normal ++= normal_fun;
+
+        mixed ++= function(v) { $radio.fill = v ? .image.radio_mixed : .image.radio; }
+
+        selected ++= function(v) { cascade = v; $radio.visible = selected; }
+
+        <ui:box id="bg" shrink="true">
+            <ui:box id="radio" fill=".image.radio" shrink="true" visible="false" />
+        </ui:box>
+        <ui:box id="content" />
+
+    </ui:box>
+</ibex>
diff --git a/src/org/ibex/theme/win2k/redirect.t b/src/org/ibex/theme/win2k/redirect.t
new file mode 100644 (file)
index 0000000..009ae03
--- /dev/null
@@ -0,0 +1,5 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="ibex.lib">
+    <redirect />
+</ibex>
diff --git a/src/org/ibex/theme/win2k/repeatable.t b/src/org/ibex/theme/win2k/repeatable.t
new file mode 100644 (file)
index 0000000..404a359
--- /dev/null
@@ -0,0 +1,5 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="ibex.lib">
+    <repeatable interval="100" />
+</ibex>
diff --git a/src/org/ibex/theme/win2k/scrollbar.t b/src/org/ibex/theme/win2k/scrollbar.t
new file mode 100644 (file)
index 0000000..31073ef
--- /dev/null
@@ -0,0 +1,72 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns:lib="ibex.lib" xmlns="org.ibex.theme.win2k">
+    <meta:doc>
+        Author: Charles Goodwin
+    </meta:doc>
+
+    <lib:scrollbar amount="20">
+
+        var mousepos;
+        var movefunc = function(v) { mousepos = $track.mouse[pos]; }
+
+        th_back = $back;
+        th_next = $next;
+        th_thumb = $thumb;
+        th_track = $track;
+
+        orient ++= function(v) {
+            cascade = v;
+            thisbox[shr] = false;
+            thisbox[flip(shr)] = true;
+
+            if (rows) {
+                $backimg.fill = .image.arrowleft;
+                $nextimg.fill = .image.arrowright;
+            }
+            else {
+                $backimg.fill = .image.arrowup;
+                $nextimg.fill = .image.arrowdown;
+            }
+        }
+
+        page ++= function() {
+            if (slave) return 0.9 * (slave[dim]);
+            else return 0;
+        }
+
+/* FIXME: fix erratic showing of $shadow
+        $track.action ++= function(v) {
+            if ($thumb[pos] > mousepos) {
+                $shadow[dim] = $thumb[pos];
+                $shadow[pos] = 0;
+            }
+            else {
+                $shadow[dim] = $track[dim] - $thumb[dim] - $thumb[pos];
+                $shadow[pos] = $thumb[dim] + $thumb[pos];
+            }
+        }
+
+        $track.repeat ++= function(v) {
+            if (v) Move ++= movefunc;
+            else Move --= movefunc;
+            cascade = v;
+            $shadow.visible = v;
+        }
+*/
+        $track.Press1 ++= function(v) { if ($thumb.mouse.inside) return true; }
+        <button id="back" fill="#d0d4c8" width="16" height="16" repeats="true" shrink="true">
+            .clickable(thisbox);
+            <ui:box id="backimg" shrink="true" />
+        </button>
+        <clickable id="track" enabled="true" fill=".image.scrollbg" repeats="true">
+            <ui:box id="shadow" align="topleft" fill="#888888" packed="false" visible="false" />
+            <bevel id="thumb" align="topleft" fill="#d0d4c8" form="up" packed="false" />
+        </clickable>
+        <button id="next" fill="#d0d4c8" width="16" height="16" repeats="true" shrink="true">
+            .clickable(thisbox);
+            <ui:box id="nextimg" shrink="true" />
+        </button>
+    </lib:scrollbar>
+</ibex>
diff --git a/src/org/ibex/theme/win2k/scrollpane.t b/src/org/ibex/theme/win2k/scrollpane.t
new file mode 100644 (file)
index 0000000..177b2cd
--- /dev/null
@@ -0,0 +1,33 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns:lib="ibex.lib" xmlns="ibex.widget">
+    <meta:doc>
+        Author: Charles Goodwin
+    </meta:doc>
+
+    <lib:scrollpane redirect="$content">
+
+        th_hscroll = $hscroll;
+        th_vscroll = $vscroll;
+        th_viewport = $view;
+
+        $hscroll.SizeChange ++= function(v) { $inset.height = $hscroll.height; }
+        $vscroll.SizeChange ++= function(v) { $inset.width = $vscroll.width; }
+
+        orient ++= function(v) {
+            if (v == "horizontal") { hshrink = false; vshrink = true; }
+            else if (v == "vertical") { hshrink = true; vshrink = false; }
+        }
+
+        <bevel form="down"> 
+            <ui:box rows="2">
+                <ui:box id="view">
+                    <ui:box id="content" align="topleft" packed="false" shrink="true" />
+                </ui:box>
+                <scrollbar id="hscroll" orient="horizontal" />
+                <scrollbar id="vscroll" orient="vertical" />
+                <ui:box id="inset" />
+            </ui:box>
+        </bevel>
+    </lib:scrollpane>
+</ibex>
diff --git a/src/org/ibex/theme/win2k/selectable.t b/src/org/ibex/theme/win2k/selectable.t
new file mode 100644 (file)
index 0000000..a5d0d75
--- /dev/null
@@ -0,0 +1,5 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="ibex.lib">
+    <selectable />
+</ibex>
diff --git a/src/org/ibex/theme/win2k/slider.t b/src/org/ibex/theme/win2k/slider.t
new file mode 100644 (file)
index 0000000..3f1a284
--- /dev/null
@@ -0,0 +1,18 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="org.ibex.theme.win2k">
+    <meta:doc>
+        Author: Charles Goodwin
+    </meta:doc>
+
+    <ui:box cols="1">
+
+        th_track = $track;
+        th_handle = $handle;
+        th_ruler = $ruler;
+
+        <ui:box id="track" />
+        <ui:box id="handle" />
+        <ui:box id="ruler" />
+    </ui:box>
+</ibex>
diff --git a/src/org/ibex/theme/win2k/spin.t b/src/org/ibex/theme/win2k/spin.t
new file mode 100644 (file)
index 0000000..4f019a5
--- /dev/null
@@ -0,0 +1,27 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="org.ibex.theme.win2k" xmlns:lib="ibex.lib">
+    <meta:doc>
+        Author: Charles Goodwin
+    </meta:doc>
+
+    <lib:spin redirect="$content" padding="3">
+
+        th_more = $more;
+        th_less = $less;
+
+        <bevel form="down">
+            <ui:box id="content" fill="white" />
+            <ui:box cols="1" width="15">
+                <button id="more">
+                    .clickable(thisbox);
+                    <ui:box align="center" fill=".image.arrowup_small" shrink="true" />
+                </button>
+                <button id="less">
+                    .clickable(thisbox);
+                    <ui:box align="center" fill=".image.arrowdown_small" shrink="true" />
+                </button>
+            </ui:box>
+        </bevel>
+    </lib:spin>
+</ibex>
diff --git a/src/org/ibex/theme/win2k/surface.t b/src/org/ibex/theme/win2k/surface.t
new file mode 100644 (file)
index 0000000..90c2890
--- /dev/null
@@ -0,0 +1,18 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="ibex.lib">
+    <surface />
+    <eventmanager />
+    <focusmanager />
+    <ui:box>
+
+        _KeyPressed += function(v) {
+            if (v == "tab") {
+                surface.nextFocus();
+            } else if (v == "TAB") {
+                surface.prevFocus();
+            }
+        }
+
+    </ui:box>
+</ibex>
diff --git a/src/org/ibex/theme/win2k/tab.t b/src/org/ibex/theme/win2k/tab.t
new file mode 100644 (file)
index 0000000..aa3a36b
--- /dev/null
@@ -0,0 +1,22 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="org.ibex.theme.win2k">
+    <meta:doc>
+        Author: Charles Goodwin
+    </meta:doc>
+
+    <ui:box redirect="$content" cols="1" padding="4 10">
+
+        selected ++= function(v) {
+            cascade = v;
+            $content.fill = selected ? "#d4d0c8" : "#c4c0b8";
+            $gap.height = selected ? 0 : 2;
+        }
+        <ui:box id="gap" vshrink="true" />
+        <bevel form="tabtop">
+            <ui:box id="content" />
+        </bevel>
+
+    </ui:box>
+</ibex>
diff --git a/src/org/ibex/theme/win2k/tabpane.t b/src/org/ibex/theme/win2k/tabpane.t
new file mode 100644 (file)
index 0000000..01a2732
--- /dev/null
@@ -0,0 +1,39 @@
+<!-- Copyleft 2004 - see COPYING for details [LGPL] -->
+
+<ibex xmlns="org.ibex.theme.win2k" xmlns:lib="ibex.lib">
+    <meta:doc>
+        Author: Charles Goodwin
+    </meta:doc>
+
+    <lib:tabpane />
+    <ui:box redirect="$content" margin="10" padding="10">
+
+        th_head = $header;
+
+        var syncshadow = function(v) {
+                if (typeof(v) != "object" and th_content.show) v = th_content.show.tab;
+                $shadow.width = v.width - 3;
+                $shadow.x = v.x + 1;
+                $shadow.y = $header.height;
+        }
+
+        th_content ++= function(v) {
+            v.show ++= function(c) {
+                if (c and c.tab) {
+                    //if (v.show) v.show.tab.SizeChange --= syncshadow;
+                    if (cascade) cascade.tab.SizeChange --= syncshadow;
+                    c.tab.SizeChange ++= syncshadow;
+                    syncshadow(c.tab);
+                }
+            }
+        }
+
+        <ui:box id="body" cols="1">
+            <ui:box align="topleft" id="header" height="27" shrink="true" />
+            <bevel form="up" thickness="2">
+                <ui:box id="content" />
+            </bevel>
+            <ui:box id="shadow" align="topleft" height="2" packed="false" fill="#d4d0c8" />
+        </ui:box>
+    </ui:box>
+</ibex>
diff --git a/src/sampler.t b/src/sampler.t
new file mode 100644 (file)
index 0000000..ec137dc
--- /dev/null
@@ -0,0 +1,19 @@
+<ibex  xmlns:theme="ibex.theme"  xmlns="org.ibex.theme.win2k" xmlns:sampler="org.ibex.sampler">
+  <theme:surface />
+  <ui:box fill="#d4d0c8" maxwidth="600" maxheight="200" cols="1">
+    
+    ibex.ui.frame = thisbox;
+
+    <ui:box text="menus aren't implemented" height="20" align="left"/>
+    <tabpane>
+      <sampler:dialog tabtext="Widgets"/>      
+      <sampler:window_manager_interaction tabtext="Windowing"/>
+      <sampler:clipboard tabtext="Clipboard"/>      
+      <sampler:color_picker tabtext="Color Picker"/>      
+      <sampler:transparency tabtext="Transparency"/> 
+      <sampler:fonts tabtext="Fonts"/>      
+      <sampler:html tabtext="HTML"/>      
+      <sampler:spreadsheet tabtext="Spreadsheet"/>           
+    </tabpane> 
+  </ui:box>
+</ibex>