Initial version
authorguillaum1 <guillaum1@users.evolvis.org>
Thu, 4 Sep 2008 12:54:07 +0000 (12:54 +0000)
committerguillaum1 <guillaum1@users.evolvis.org>
Thu, 4 Sep 2008 12:54:07 +0000 (12:54 +0000)
100 files changed:
.classpath [new file with mode: 0644]
.project [new file with mode: 0644]
CHANGES [new file with mode: 0644]
COPYING [new file with mode: 0644]
LICENSE [new file with mode: 0644]
README [new file with mode: 0644]
configuration/org/thenesis/lwuit/configuration/configuration.cfg [new file with mode: 0644]
core/java/com/sun/lwuit/Button.java [new file with mode: 0644]
core/java/com/sun/lwuit/ButtonGroup.java [new file with mode: 0644]
core/java/com/sun/lwuit/Calendar.java [new file with mode: 0644]
core/java/com/sun/lwuit/CheckBox.java [new file with mode: 0644]
core/java/com/sun/lwuit/ComboBox.java [new file with mode: 0644]
core/java/com/sun/lwuit/Command.java [new file with mode: 0644]
core/java/com/sun/lwuit/Component.java [new file with mode: 0644]
core/java/com/sun/lwuit/Container.java [new file with mode: 0644]
core/java/com/sun/lwuit/CustomFont.java [new file with mode: 0644]
core/java/com/sun/lwuit/Dialog.java [new file with mode: 0644]
core/java/com/sun/lwuit/Display.java [new file with mode: 0644]
core/java/com/sun/lwuit/EditForm.java [new file with mode: 0644]
core/java/com/sun/lwuit/EventDispatcher.java [new file with mode: 0644]
core/java/com/sun/lwuit/EventMapper.java [new file with mode: 0644]
core/java/com/sun/lwuit/Font.java [new file with mode: 0644]
core/java/com/sun/lwuit/Form.java [new file with mode: 0644]
core/java/com/sun/lwuit/GenericEventMapper.java [new file with mode: 0644]
core/java/com/sun/lwuit/Graphics.java [new file with mode: 0644]
core/java/com/sun/lwuit/Image.java [new file with mode: 0644]
core/java/com/sun/lwuit/IndexedImage.java [new file with mode: 0644]
core/java/com/sun/lwuit/Label.java [new file with mode: 0644]
core/java/com/sun/lwuit/List.java [new file with mode: 0644]
core/java/com/sun/lwuit/M3G.java [new file with mode: 0644]
core/java/com/sun/lwuit/MediaComponent.java [new file with mode: 0644]
core/java/com/sun/lwuit/MonthView.java [new file with mode: 0644]
core/java/com/sun/lwuit/Painter.java [new file with mode: 0644]
core/java/com/sun/lwuit/Popup.java [new file with mode: 0644]
core/java/com/sun/lwuit/RGBImage.java [new file with mode: 0644]
core/java/com/sun/lwuit/RadioButton.java [new file with mode: 0644]
core/java/com/sun/lwuit/RunnableWrapper.java [new file with mode: 0644]
core/java/com/sun/lwuit/StaticAnimation.java [new file with mode: 0644]
core/java/com/sun/lwuit/SystemFont.java [new file with mode: 0644]
core/java/com/sun/lwuit/TabbedPane.java [new file with mode: 0644]
core/java/com/sun/lwuit/TextArea.java [new file with mode: 0644]
core/java/com/sun/lwuit/TextField.java [new file with mode: 0644]
core/java/com/sun/lwuit/VirtualImplementation.java [new file with mode: 0644]
core/java/com/sun/lwuit/animations/Animation.java [new file with mode: 0644]
core/java/com/sun/lwuit/animations/CommonTransitions.java [new file with mode: 0644]
core/java/com/sun/lwuit/animations/Motion.java [new file with mode: 0644]
core/java/com/sun/lwuit/animations/Transition.java [new file with mode: 0644]
core/java/com/sun/lwuit/animations/Transition3D.java [new file with mode: 0644]
core/java/com/sun/lwuit/animations/package.html [new file with mode: 0644]
core/java/com/sun/lwuit/events/ActionEvent.java [new file with mode: 0644]
core/java/com/sun/lwuit/events/ActionListener.java [new file with mode: 0644]
core/java/com/sun/lwuit/events/DataChangedListener.java [new file with mode: 0644]
core/java/com/sun/lwuit/events/FocusListener.java [new file with mode: 0644]
core/java/com/sun/lwuit/events/SelectionListener.java [new file with mode: 0644]
core/java/com/sun/lwuit/events/StyleListener.java [new file with mode: 0644]
core/java/com/sun/lwuit/events/package.html [new file with mode: 0644]
core/java/com/sun/lwuit/geom/Dimension.java [new file with mode: 0644]
core/java/com/sun/lwuit/geom/Rectangle.java [new file with mode: 0644]
core/java/com/sun/lwuit/geom/package.html [new file with mode: 0644]
core/java/com/sun/lwuit/layouts/BorderLayout.java [new file with mode: 0644]
core/java/com/sun/lwuit/layouts/BoxLayout.java [new file with mode: 0644]
core/java/com/sun/lwuit/layouts/CoordinateLayout.java [new file with mode: 0644]
core/java/com/sun/lwuit/layouts/FlowLayout.java [new file with mode: 0644]
core/java/com/sun/lwuit/layouts/GridLayout.java [new file with mode: 0644]
core/java/com/sun/lwuit/layouts/GroupLayout.java [new file with mode: 0644]
core/java/com/sun/lwuit/layouts/Layout.java [new file with mode: 0644]
core/java/com/sun/lwuit/layouts/LayoutStyle.java [new file with mode: 0644]
core/java/com/sun/lwuit/layouts/package.html [new file with mode: 0644]
core/java/com/sun/lwuit/list/DefaultListCellRenderer.java [new file with mode: 0644]
core/java/com/sun/lwuit/list/DefaultListModel.java [new file with mode: 0644]
core/java/com/sun/lwuit/list/ListCellRenderer.java [new file with mode: 0644]
core/java/com/sun/lwuit/list/ListModel.java [new file with mode: 0644]
core/java/com/sun/lwuit/list/package.html [new file with mode: 0644]
core/java/com/sun/lwuit/package.html [new file with mode: 0644]
core/java/com/sun/lwuit/painter/BackgroundPainter.java [new file with mode: 0644]
core/java/com/sun/lwuit/painter/PainterChain.java [new file with mode: 0644]
core/java/com/sun/lwuit/painter/package.html [new file with mode: 0644]
core/java/com/sun/lwuit/plaf/Border.java [new file with mode: 0644]
core/java/com/sun/lwuit/plaf/DefaultLookAndFeel.java [new file with mode: 0644]
core/java/com/sun/lwuit/plaf/LookAndFeel.java [new file with mode: 0644]
core/java/com/sun/lwuit/plaf/Style.java [new file with mode: 0644]
core/java/com/sun/lwuit/plaf/UIManager.java [new file with mode: 0644]
core/java/com/sun/lwuit/plaf/package.html [new file with mode: 0644]
core/java/com/sun/lwuit/util/Effects.java [new file with mode: 0644]
core/java/com/sun/lwuit/util/Log.java [new file with mode: 0644]
core/java/com/sun/lwuit/util/Resources.java [new file with mode: 0644]
core/java/com/sun/lwuit/util/package.html [new file with mode: 0644]
core/java/javax/microedition/m3g/Graphics3D.java [new file with mode: 0644]
core/java/javax/microedition/m3g/Image2D.java [new file with mode: 0644]
core/java/javax/microedition/media/MediaException.java [new file with mode: 0644]
core/java/javax/microedition/media/Player.java [new file with mode: 0644]
core/java/org/thenesis/lwuit/configuration/Configuration.java [new file with mode: 0644]
core/java/org/thenesis/lwuit/configuration/ConfigurationProperties.java [new file with mode: 0644]
core/java/org/thenesis/lwuit/configuration/Properties.java [new file with mode: 0644]
demos/java/org/thenesis/lwuimb/demo/BaseDemo.java [new file with mode: 0644]
demos/java/org/thenesis/lwuimb/demo/ExplicitModeDemo.java [new file with mode: 0644]
demos/resources/res/baldy.png [new file with mode: 0644]
demos/resources/res/bar.png [new file with mode: 0644]
demos/resources/res/cosmic.png [new file with mode: 0644]
demos/resources/res/softbutton.png [new file with mode: 0644]

diff --git a/.classpath b/.classpath
new file mode 100644 (file)
index 0000000..36b6f61
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+       <classpathentry kind="src" path="core/java"/>\r
+       <classpathentry kind="src" path="demos/java"/>\r
+       <classpathentry kind="src" path="demos/resources"/>\r
+       <classpathentry kind="src" path="configuration"/>\r
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>\r
+       <classpathentry kind="output" path="classes"/>\r
+</classpath>\r
diff --git a/.project b/.project
new file mode 100644 (file)
index 0000000..f600121
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+       <name>lwuimb</name>\r
+       <comment></comment>\r
+       <projects>\r
+       </projects>\r
+       <buildSpec>\r
+               <buildCommand>\r
+                       <name>org.eclipse.jdt.core.javabuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+       </buildSpec>\r
+       <natures>\r
+               <nature>org.eclipse.jdt.core.javanature</nature>\r
+       </natures>\r
+</projectDescription>\r
diff --git a/CHANGES b/CHANGES
new file mode 100644 (file)
index 0000000..afed70f
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,8 @@
+0.1-alpha1 (04/09/2008)
+-----------------------
+* Basic features are working
+* Added text edition features
+* Added embedded virtual keyboard
+* Missing: SVG, M3G and Player support
+
+
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..5bb0601
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  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.
+\f
+                   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.)
+\f
+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.
+\f
+  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.
+\f
+  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
+\f
+           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) 19yy  <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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  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) 19yy 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.
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..6e1ec27
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,5 @@
+The software in this package is distributed under the GNU General Public
+License (with a special exception described below).
+
+A copy of GNU General Public License (GPL) is included in this distribution,
+in the file COPYING.
\ No newline at end of file
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..038c322
--- /dev/null
+++ b/README
@@ -0,0 +1,30 @@
+==============
+LWUIMB README
+==============
+
+LWUIMB is a port of LWUIT on top of the MicroBackend library.
+
+It allows LWUIT to work on top of various graphical libraries (SDL, AWT, SWT,
+ X11, GTK, Qt3/Qt4/Qtopia4, Linux framebuffer) and JVMs (CLDC, CDC, J2SE)
+
+The MicroBackend library was created for needs of the MIDPath project.
+
+LWUIMB is released under GPL.
+
+Licensing
+---------
+
+LWUIMB is released under the GPL license.
+See the LICENSE file.
+
+Repository structure:
+-----------------------
+       
+       |-- configuration: configuration files required by the library
+       |-- core/java: sources of the library
+       |-- demos/java: source of the demos
+       |-- demos/java: resources needed by the demos
+       . CHANGES
+       . COPYING
+       . LICENSE
+       . README
diff --git a/configuration/org/thenesis/lwuit/configuration/configuration.cfg b/configuration/org/thenesis/lwuit/configuration/configuration.cfg
new file mode 100644 (file)
index 0000000..e79bf68
--- /dev/null
@@ -0,0 +1,66 @@
+##========================================
+## Graphics parameters
+##========================================
+org.thenesis.lwuit.microbackend.screenWidth:320
+org.thenesis.lwuit.microbackend.screenHeight:240
+
+##======================================
+## Parameters for MicroBackend
+##======================================
+# Possible backend values: NULL, SDL, AWT, AWTGRABBER, SWT, X11, GTK, QT, FB
+org.thenesis.microbackend.ui.backend:AWT
+# SDL backend configuration.
+# Possible bitsPerPixels values: 8, 16, 32
+# Possible video mode values: SW, HW (i.e software, hardware)
+org.thenesis.microbackend.ui.sdl.bitsPerPixel:32
+org.thenesis.microbackend.ui.sdl.videoMode:SW
+# X11 backend configuration.
+# Display value examples: :0.0, 192.168.0.1:1.0
+org.thenesis.microbackend.ui.x11.Display::0.0
+# Linux Framebuffer (FB) backend configuration 
+# (see /proc/bus/input/devices to know which special files are  
+# associated with your mouse or touchscreen)
+org.thenesis.microbackend.ui.fb.framebufferDevice:/dev/fb0
+org.thenesis.microbackend.ui.fb.keyboardDevice:/dev/tty
+org.thenesis.microbackend.ui.fb.mouseDevice:/dev/input/event1
+org.thenesis.microbackend.ui.fb.touchscreenDevice:/dev/input/event2
+
+##======================================
+## Event parameters
+##======================================
+org.thenesis.lwuit.pointerSupported:true
+org.thenesis.lwuit.pointerMotionSupported:true
+
+##======================================
+## Key mapping 
+## (AWT codes are used by convention, 
+## see java.awt.event.KeyEvent javadocs)
+##======================================
+# DOWN key. Default: VK_DOWN (40)
+org.thenesis.lwuit.keys.GAME_DOWN:40
+# FIRE key. Default: VK_ENTER (10)
+org.thenesis.lwuit.keys.GAME_FIRE:10
+# LEFT key. Default: VK_LEFT (37)
+org.thenesis.lwuit.keys.GAME_LEFT:37
+# RIGHT key. Default: VK_RIGHT (39)
+org.thenesis.lwuit.keys.GAME_RIGHT:39
+# UP key. Default: VK_UP (38)
+org.thenesis.lwuit.keys.GAME_UP:38
+# POUND key (#). Default: VK_NUMBER_SIGN (520)
+org.thenesis.lwuit.keys.POUND:520
+# BACK key. Default: VK_F4 (115)
+org.thenesis.lwuit.keys.BACK:115
+# CLEAR key. Default: VK_F5 (116)
+org.thenesis.lwuit.keys.CLEAR:116
+# SOFT_LEFT key. Default: VK_F1 (112)
+org.thenesis.lwuit.keys.SOFT_LEFT:112
+# SOFT_RIGHT key. Default: VK_F2 (113)
+org.thenesis.lwuit.keys.SOFT_RIGHT:113
+# SOFT_RIGHT2 key. Default: VK_F3 (114)
+org.thenesis.lwuit.keys.SOFT_RIGHT2:113
+# DELETE key. Default: VK_DELETE (127)
+org.thenesis.lwuit.keys.DELETE:127
+# BACKSPACE key. Default: VK_BACK_SPACE (8)
+org.thenesis.lwuit.keys.BACKSPACE:8
+
+
diff --git a/core/java/com/sun/lwuit/Button.java b/core/java/com/sun/lwuit/Button.java
new file mode 100644 (file)
index 0000000..f9cc4cb
--- /dev/null
@@ -0,0 +1,323 @@
+/*\r
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.\r
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\r
+ *\r
+ * This code is free software; you can redistribute it and/or modify it\r
+ * under the terms of the GNU General Public License version 2 only, as\r
+ * published by the Free Software Foundation.  Sun designates this\r
+ * particular file as subject to the "Classpath" exception as provided\r
+ * by Sun in the LICENSE file that accompanied this code.\r
+ *\r
+ * This code is distributed in the hope that it will be useful, but WITHOUT\r
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
+ * version 2 for more details (a copy is included in the LICENSE file that\r
+ * accompanied this code).\r
+ *\r
+ * You should have received a copy of the GNU General Public License version\r
+ * 2 along with this work; if not, write to the Free Software Foundation,\r
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,\r
+ * CA 95054 USA or visit www.sun.com if you need additional information or\r
+ * have any questions.\r
+ */\r
+\r
+package com.sun.lwuit;\r
+\r
+import com.sun.lwuit.geom.Dimension;\r
+import com.sun.lwuit.events.ActionEvent;\r
+import com.sun.lwuit.events.ActionListener;\r
+import com.sun.lwuit.plaf.Border;\r
+import com.sun.lwuit.plaf.UIManager;\r
+\r
+\r
+/**\r
+ * Button is the base class for several UI widgets allowing clickability.\r
+ * It has 3 states: rollover, pressed and the default state it \r
+ * can also have ActionListeners that react when the Button is clicked.\r
+ * \r
+ * @author Chen Fishbein\r
+ */\r
+public class Button extends Label {\r
+    /**\r
+     * Indicates the rollover state of a button which is equivalent to focused for\r
+     * most uses\r
+     */\r
+    public static final int STATE_ROLLOVER = 0;\r
+    \r
+    /**\r
+     * Indicates the pressed state of a button \r
+     */\r
+    public static final int STATE_PRESSED = 1;\r
+    \r
+    /**\r
+     * Indicates the default state of a button which is neither pressed nor focused\r
+     */\r
+    public static final int STATE_DEAFULT = 2;\r
+    \r
+    private static String id = "Button";\r
+    \r
+    private EventDispatcher dispatcher = new EventDispatcher();\r
+    \r
+    private int state = STATE_DEAFULT;\r
+    \r
+    private Image pressedIcon;\r
+    \r
+    private Image rolloverIcon;\r
+  \r
+    private Command cmd;\r
+    \r
+    /** \r
+     * Constructs a button with an empty string for its text.\r
+     */\r
+    public Button() {\r
+        this("");\r
+    }\r
+    \r
+    /**\r
+     * Constructs a button with the specified text.\r
+     * \r
+     * @param text label appearing on the button\r
+     */\r
+    public Button(String text) {\r
+        this(text, null);\r
+    }\r
+    \r
+    /**\r
+     * Allows binding a command to a button for ease of use\r
+     * \r
+     * @param cmd command whose text would be used for the button and would recive action events\r
+     * from the button\r
+     */\r
+    public Button(Command cmd) {\r
+        this(cmd.getCommandName(), cmd.getIcon());\r
+        addActionListener(cmd);\r
+        this.cmd = cmd;\r
+    }\r
+    \r
+    /**\r
+     * Constructs a button with the specified image.\r
+     * \r
+     * @param icon appearing on the button\r
+     */\r
+    public Button(Image icon) {\r
+        this("", icon);\r
+    }\r
+    \r
+    /**\r
+     * Constructor a button with text and image\r
+     * \r
+     * @param text label appearing on the button\r
+     * @param icon image appearing on the button\r
+     */\r
+    public Button(String text, Image icon) {\r
+        super(text);\r
+        setFocusable(true);\r
+        setIcon(icon);\r
+        this.pressedIcon = icon;\r
+        this.rolloverIcon = icon;\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    void focusGainedInternal() {\r
+        state = STATE_ROLLOVER;\r
+    }\r
+    \r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    void focusLostInternal() {\r
+        state = STATE_DEAFULT;\r
+    }\r
+    \r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    protected String getUIID() {\r
+        return id;\r
+    }\r
+    \r
+    /**\r
+     * Returns the button state\r
+     * \r
+     * @return One of STATE_ROLLOVER, STATE_DEAFULT, STATE_PRESSED\r
+     */\r
+    public int getState() {\r
+        return state;\r
+    }\r
+    \r
+    /**\r
+     * Indicates the icon that is displayed on the button when the button is in \r
+     * pressed state\r
+     * \r
+     * @return icon used\r
+     * @see #STATE_PRESSED\r
+     */\r
+    public Image getPressedIcon() {\r
+        return pressedIcon;\r
+    }\r
+    \r
+    /**\r
+     * Indicates the icon that is displayed on the button when the button is in \r
+     * rolled over state\r
+     * \r
+     * @return icon used\r
+     * @see #STATE_ROLLOVER\r
+     */\r
+    public Image getRolloverIcon() {\r
+        return rolloverIcon;\r
+    }\r
+    \r
+    /**\r
+     * Indicates the icon that is displayed on the button when the button is in \r
+     * rolled over state\r
+     * \r
+     * @param rolloverIcon icon to use\r
+     * @see #STATE_ROLLOVER\r
+     */\r
+    public void setRolloverIcon(Image rolloverIcon) {\r
+        this.rolloverIcon = rolloverIcon;\r
+        setShouldCalcPreferredSize(true);\r
+        repaint();\r
+        \r
+    }\r
+    \r
+    /**\r
+     * Indicates the icon that is displayed on the button when the button is in \r
+     * pressed state\r
+     * \r
+     * @param pressedIcon icon used\r
+     * @see #STATE_PRESSED\r
+     */\r
+    public void setPressedIcon(Image pressedIcon) {\r
+        this.pressedIcon = pressedIcon;\r
+        setShouldCalcPreferredSize(true);\r
+        repaint();\r
+    }\r
+    \r
+    /**\r
+     * Adds a listener to the button which will cause an event to dispatch on click\r
+     * \r
+     * @param l implementation of the action listener interface\r
+     */\r
+    public void addActionListener(ActionListener l){\r
+        dispatcher.addListener(l);\r
+    }\r
+    \r
+    /**\r
+     * Removes the given action listener from the button\r
+     * \r
+     * @param l implementation of the action listener interface\r
+     */\r
+    public void removeActionListener(ActionListener l){\r
+        dispatcher.removeListener(l);\r
+    }\r
+    \r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    void fireActionEvent(){\r
+        super.fireActionEvent();\r
+        if(cmd != null) {\r
+            dispatcher.fireActionEvent(new ActionEvent(cmd));\r
+        } else {\r
+            dispatcher.fireActionEvent(new ActionEvent(this));\r
+        }\r
+    }\r
+    \r
+    /**\r
+     * Invoked to change the state of the button to the pressed state\r
+     */\r
+    void pressed(){\r
+        if(isEnabled()) {\r
+            state=STATE_PRESSED;\r
+            repaint();\r
+        }\r
+    }\r
+    \r
+    /**\r
+     * Invoked to change the state of the button to the released state\r
+     */\r
+    void released(){\r
+        if(isEnabled()) {\r
+            state=STATE_ROLLOVER;\r
+            repaint();\r
+            fireActionEvent();\r
+        }\r
+    }\r
+    \r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void keyPressed(int keyCode) {\r
+        if (Display.getInstance().getGameAction(keyCode) == Display.GAME_FIRE){\r
+            pressed();\r
+        }\r
+    }\r
+    \r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void keyReleased(int keyCode) {\r
+        if (Display.getInstance().getGameAction(keyCode) == Display.GAME_FIRE){\r
+            released();\r
+        }\r
+    }\r
+    \r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    protected void fireClicked() {\r
+        pressed();\r
+        released();\r
+    }\r
+    \r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    protected boolean isSelectableInteraction() {\r
+        return true;\r
+    }\r
+    \r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void pointerPressed(int x, int y) {\r
+        pressed();\r
+    }\r
+    \r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void pointerReleased(int x, int y) {\r
+        released();\r
+    }\r
+    \r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void paint(Graphics g) {\r
+        UIManager.getInstance().getLookAndFeel().drawButton(g, this);\r
+    }\r
+    \r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    protected Dimension calcPreferredSize(){\r
+        return UIManager.getInstance().getLookAndFeel().getButtonPreferredSize(this);\r
+    }\r
+    \r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    protected Border getBorder() {\r
+        if(getState() != STATE_PRESSED){\r
+            return super.getBorder();\r
+        } else {\r
+            return getStyle().getBorder().createPressedVersion();\r
+        }\r
+    }\r
+}\r
diff --git a/core/java/com/sun/lwuit/ButtonGroup.java b/core/java/com/sun/lwuit/ButtonGroup.java
new file mode 100644 (file)
index 0000000..153f704
--- /dev/null
@@ -0,0 +1,160 @@
+/*\r
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.\r
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\r
+ *\r
+ * This code is free software; you can redistribute it and/or modify it\r
+ * under the terms of the GNU General Public License version 2 only, as\r
+ * published by the Free Software Foundation.  Sun designates this\r
+ * particular file as subject to the "Classpath" exception as provided\r
+ * by Sun in the LICENSE file that accompanied this code.\r
+ *\r
+ * This code is distributed in the hope that it will be useful, but WITHOUT\r
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
+ * version 2 for more details (a copy is included in the LICENSE file that\r
+ * accompanied this code).\r
+ *\r
+ * You should have received a copy of the GNU General Public License version\r
+ * 2 along with this work; if not, write to the Free Software Foundation,\r
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,\r
+ * CA 95054 USA or visit www.sun.com if you need additional information or\r
+ * have any questions.\r
+ */\r
+\r
+package com.sun.lwuit;\r
+\r
+/**\r
+ * This class is used to create a multiple-exclusion scope for a set of \r
+ * RadioButtons. Creating a set of RadioButtons with the same ButtonGroup object\r
+ * means that only one RadioButton can be selected amoung the ButtonGroup.\r
+ * Initialy all RadioButtons are unselected.\r
+ * \r
+ * @author Nir Shabi\r
+ */\r
+public class ButtonGroup {\r
+    \r
+    \r
+    private java.util.Vector buttons = new java.util.Vector();\r
+    private int selectedIndex=-1;\r
+    \r
+    /** \r
+     * Creates a new instance of ButtonsGroup \r
+     */\r
+    public ButtonGroup() {\r
+    }\r
+    \r
+    /**\r
+     * Adds a RadioButton to the group\r
+     * \r
+     * @param rb a RadioButton to add\r
+     */\r
+    public void add(RadioButton rb){\r
+        if(rb==null)\r
+            return;\r
+        buttons.addElement(rb);\r
+        if(rb.isSelected())\r
+            setSelected(selectedIndex);\r
+        rb.setGroup(this);\r
+        \r
+    }\r
+\r
+    /**\r
+     * removes a RadioButton from the group\r
+     * \r
+     * @param rb a RadioButton to remove\r
+     */\r
+    public void remove(RadioButton rb){\r
+        if(rb==null)\r
+            return;\r
+        buttons.removeElement(rb);\r
+        if(rb.isSelected())\r
+            clearSelection();\r
+        rb.setGroup(null);\r
+    }\r
+    \r
+    /**\r
+     * Clears the selection such that none of the buttons in the ButtonGroup are selected.\r
+     */\r
+    public void clearSelection() {\r
+        if(selectedIndex!=-1) {\r
+            ((RadioButton)buttons.elementAt(selectedIndex)).setSelected(false);\r
+            selectedIndex=-1;\r
+        }\r
+        \r
+    }\r
+    \r
+    /**\r
+     * Returns the number of buttons in the group.\r
+     * \r
+     * @return number of radio buttons in the group\r
+     */\r
+    public int getButtonCount() {\r
+        return buttons.size();\r
+    }\r
+    \r
+    /**\r
+     * Returns whether a radio button in the group is selected.\r
+     * \r
+     * @return true if a selection was made in the radio button group\r
+     */\r
+    public boolean isSelected() {\r
+        if(selectedIndex!= -1)\r
+            return true;\r
+        return false;\r
+    }\r
+    \r
+    /**\r
+     * Return the index of the selected button within the group\r
+     * \r
+     * @return the index of the selected button within the group\r
+     */\r
+    public int getSelectedIndex() {\r
+        return selectedIndex;\r
+    }\r
+    \r
+    /**\r
+     * Returns the radio button at the given group index\r
+     * \r
+     * @param index offset within the group starting with 0 and no larger than getButtonCount()\r
+     * @return the radio button instance\r
+     */\r
+    public RadioButton getRadioButton(int index) {\r
+        if(index >=0 && index < getButtonCount())\r
+            return ((RadioButton)buttons.elementAt(index));\r
+        return null;\r
+    }\r
+\r
+    /**\r
+     * Selects the given radio button\r
+     * \r
+     * @param rb the radio button to set as selected\r
+     */\r
+    public void setSelected(RadioButton rb) {\r
+        if (rb != null) {\r
+            int index = buttons.indexOf(rb);\r
+            setSelected(index);\r
+        } else {\r
+            clearSelection();\r
+        }\r
+    }\r
+    \r
+    /**\r
+     * Sets the selected Radion button by index\r
+     * \r
+     * @param index the index of the radio button to mark as selected\r
+     */\r
+    public void setSelected(int index) {\r
+        if(index < 0  ||  index >= getButtonCount() )\r
+            throw new IllegalArgumentException("Inedx out of bounds");\r
+        \r
+        if(selectedIndex!=-1) {\r
+            //unselect last selected Radio button\r
+            ((RadioButton)buttons.elementAt(selectedIndex)).setSelected(false);\r
+            ((RadioButton)buttons.elementAt(selectedIndex)).repaint();\r
+        }\r
+        ((RadioButton)buttons.elementAt(index)).setSelected(true);\r
+        selectedIndex=index;\r
+    }\r
+}\r
diff --git a/core/java/com/sun/lwuit/Calendar.java b/core/java/com/sun/lwuit/Calendar.java
new file mode 100644 (file)
index 0000000..eb3bb7d
--- /dev/null
@@ -0,0 +1,181 @@
+/*\r
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.\r
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\r
+ *\r
+ * This code is free software; you can redistribute it and/or modify it\r
+ * under the terms of the GNU General Public License version 2 only, as\r
+ * published by the Free Software Foundation.  Sun designates this\r
+ * particular file as subject to the "Classpath" exception as provided\r
+ * by Sun in the LICENSE file that accompanied this code.\r
+ *\r
+ * This code is distributed in the hope that it will be useful, but WITHOUT\r
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
+ * version 2 for more details (a copy is included in the LICENSE file that\r
+ * accompanied this code).\r
+ *\r
+ * You should have received a copy of the GNU General Public License version\r
+ * 2 along with this work; if not, write to the Free Software Foundation,\r
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,\r
+ * CA 95054 USA or visit www.sun.com if you need additional information or\r
+ * have any questions.\r
+ */\r
+\r
+package com.sun.lwuit;\r
+\r
+import com.sun.lwuit.events.ActionListener;\r
+import com.sun.lwuit.plaf.Style;\r
+import com.sun.lwuit.layouts.BorderLayout;\r
+import com.sun.lwuit.layouts.BoxLayout;\r
+import com.sun.lwuit.layouts.FlowLayout;\r
+import com.sun.lwuit.plaf.UIManager;\r
+import java.util.Date;\r
+import java.util.Hashtable;\r
+\r
+/**\r
+ * Date widget for selecting a date/time value. \r
+ * <p>To localize strings for month names\r
+ * use the values "Calendar.Month" in the resource localization e.g. "Calendar.Jan", "Calendar.Feb" etc...\r
+ *\r
+ * @author Iddo Ari\r
+ */\r
+public class Calendar extends Container {\r
+    protected Label month;\r
+    protected Label year;\r
+    private MonthView mv;\r
+    private static String[] MONTHS = new String[]{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};\r
+\r
+    /**\r
+     * Creates a new instance of Calendar set to the given date based on time\r
+     * since epoch (the java.util.Date convention)\r
+     * \r
+     * @param time time since epoch\r
+     */\r
+    public Calendar(long time) {\r
+        super(new BorderLayout());\r
+        Container upper = new Container(new FlowLayout(Component.CENTER));\r
+        mv = new MonthView(time, this);\r
+        \r
+        month = new Label(MONTHS[mv.getMonth()]);\r
+        java.util.Calendar cal = java.util.Calendar.getInstance();\r
+        cal.setTime(new java.util.Date(time));\r
+        month.getStyle().setBgTransparency(0);\r
+        int y = cal.get(java.util.Calendar.YEAR);\r
+        year = new Label("" + y);\r
+        year.getStyle().setBgTransparency(0);\r
+        \r
+        Container cnt = new Container(new BoxLayout(BoxLayout.X_AXIS));\r
+        cnt.addComponent(month);\r
+        cnt.addComponent(year);\r
+        upper.addComponent(cnt);\r
+        \r
+        addComponent(BorderLayout.NORTH, upper);\r
+        addComponent(BorderLayout.CENTER, mv);\r
+    }\r
+    \r
+    /**\r
+     * Constructs a calendar with the current date and time\r
+     */\r
+    public Calendar() {\r
+        this(System.currentTimeMillis());\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    protected String getUIID() {\r
+        return "Calendar";\r
+    }\r
+\r
+    /**\r
+     * Returns the time for the current calendar.\r
+     * \r
+     * @return the time for the current calendar.\r
+     */\r
+    public long getSelectedDay() {\r
+        return mv.getSelectedDay();\r
+    }\r
+\r
+    void componentChanged() {\r
+        java.util.Calendar cal = java.util.Calendar.getInstance();\r
+\r
+        cal.set(java.util.Calendar.YEAR, mv.getYear());\r
+        cal.set(java.util.Calendar.MONTH, mv.getMonth());\r
+        cal.set(java.util.Calendar.DAY_OF_MONTH, mv.getDayOfMonth());\r
+        Hashtable t =  UIManager.getInstance().getResourceBundle();\r
+        String text = MONTHS[mv.getMonth()];\r
+        if(t != null) {\r
+            Object o = t.get("Calendar." + text);\r
+            if(o != null) {\r
+                text = (String)o;\r
+            }\r
+        } \r
+        month.setText(text);\r
+        year.setText("" + mv.getYear());\r
+        month.getParent().revalidate();\r
+    }\r
+\r
+    /**\r
+     * Return the date object matching the current selection\r
+     * \r
+     * @return the date object matching the current selection\r
+     */\r
+    public Date getDate() {\r
+        return new Date(mv.getSelectedDay());\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void paint(Graphics g) {\r
+        super.paint(g);\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void refreshTheme() {\r
+        mv.refreshTheme();\r
+    }\r
+    \r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void setStyle(Style s) {\r
+        // make sure the labels have the style of the calendar and not the style of a label\r
+        super.setStyle(s);\r
+        month.setStyle(s);\r
+        year.setStyle(s);\r
+    }\r
+\r
+    /**\r
+     * Sets the style of the month view component within the calendar\r
+     */\r
+    public void setMonthViewStyle(Style s) {\r
+        mv.setStyle(s);\r
+    }\r
+\r
+    /**\r
+     * Sets the style of the month view component within the calendar\r
+     */\r
+    public Style getMonthViewStyle() {\r
+        return mv.getStyle();\r
+    }\r
+\r
+    \r
+    /**\r
+     * Fires when a change is made to the month view of this component\r
+     */\r
+    public void addActionListener(ActionListener l){\r
+        mv.addActionListener(l);\r
+    }\r
+    \r
+    /**\r
+     * Fires when a change is made to the month view of this component\r
+     */\r
+    public void removeActionListener(ActionListener l){\r
+        mv.removeActionListener(l);\r
+    }\r
+}\r
diff --git a/core/java/com/sun/lwuit/CheckBox.java b/core/java/com/sun/lwuit/CheckBox.java
new file mode 100644 (file)
index 0000000..950822e
--- /dev/null
@@ -0,0 +1,132 @@
+/*\r
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.\r
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\r
+ *\r
+ * This code is free software; you can redistribute it and/or modify it\r
+ * under the terms of the GNU General Public License version 2 only, as\r
+ * published by the Free Software Foundation.  Sun designates this\r
+ * particular file as subject to the "Classpath" exception as provided\r
+ * by Sun in the LICENSE file that accompanied this code.\r
+ *\r
+ * This code is distributed in the hope that it will be useful, but WITHOUT\r
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
+ * version 2 for more details (a copy is included in the LICENSE file that\r
+ * accompanied this code).\r
+ *\r
+ * You should have received a copy of the GNU General Public License version\r
+ * 2 along with this work; if not, write to the Free Software Foundation,\r
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,\r
+ * CA 95054 USA or visit www.sun.com if you need additional information or\r
+ * have any questions.\r
+ */\r
+\r
+package com.sun.lwuit;\r
+\r
+import com.sun.lwuit.plaf.UIManager;\r
+import com.sun.lwuit.geom.*;\r
+\r
+/**\r
+ * Checkbox is a button that can be selected or deselected, and which displays\r
+ * its state to the user.\r
+ * \r
+ * @author Chen Fishbein\r
+ */\r
+public class CheckBox extends Button {\r
+    \r
+    private static final String id = "CheckBox";\r
+    \r
+    private boolean selected= false;\r
+    \r
+    /**\r
+     * Constructs a checkbox with the given text\r
+     * \r
+     * @param text to display next to the checkbox\r
+     */\r
+    public CheckBox(String text) {\r
+        this(text, null);\r
+    }\r
+\r
+    /**\r
+     * Constructs a checkbox with no text\r
+     */\r
+    public CheckBox() {\r
+        this("");\r
+    }\r
+    \r
+    /**\r
+     * Constructs a checkbox with the given icon\r
+     * \r
+     * @param icon icon to display next to the checkbox\r
+     */\r
+    public CheckBox(Image icon) {\r
+        this("", icon);\r
+    }\r
+\r
+    /**\r
+     * Constructs a checkbox with the given text and icon\r
+     * \r
+     * @param text to display next to the checkbox\r
+     * @param icon icon to display next to the text\r
+     */\r
+    public CheckBox(String text,Image icon) {\r
+        super(text,icon);\r
+    }\r
+    \r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    protected String getUIID() {\r
+        return id;\r
+    }\r
+    \r
+    /**\r
+     * Return true if the checkbox is selected\r
+     * \r
+     * @return true if the checkbox is selected\r
+     */\r
+    public boolean isSelected() {\r
+        return selected;\r
+    }\r
+    \r
+    /**\r
+     * Selects the current checkbox\r
+     * \r
+     * @param selected value for selection\r
+     */\r
+    public void setSelected(boolean selected) {\r
+        this.selected = selected;\r
+        repaint();\r
+    }\r
+    \r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void released() {\r
+        selected = !isSelected();\r
+        super.released();\r
+    }\r
+    \r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void paint(Graphics g) {\r
+        UIManager.getInstance().getLookAndFeel().drawCheckBox(g, this);\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    protected Dimension calcPreferredSize(){\r
+        return UIManager.getInstance().getLookAndFeel().getCheckBoxPreferredSize(this);\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    protected String paramString() {\r
+        return super.paramString() + ", selected = " +selected;\r
+    }\r
+}\r
diff --git a/core/java/com/sun/lwuit/ComboBox.java b/core/java/com/sun/lwuit/ComboBox.java
new file mode 100644 (file)
index 0000000..b661557
--- /dev/null
@@ -0,0 +1,218 @@
+/*\r
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.\r
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\r
+ *\r
+ * This code is free software; you can redistribute it and/or modify it\r
+ * under the terms of the GNU General Public License version 2 only, as\r
+ * published by the Free Software Foundation.  Sun designates this\r
+ * particular file as subject to the "Classpath" exception as provided\r
+ * by Sun in the LICENSE file that accompanied this code.\r
+ *\r
+ * This code is distributed in the hope that it will be useful, but WITHOUT\r
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
+ * version 2 for more details (a copy is included in the LICENSE file that\r
+ * accompanied this code).\r
+ *\r
+ * You should have received a copy of the GNU General Public License version\r
+ * 2 along with this work; if not, write to the Free Software Foundation,\r
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,\r
+ * CA 95054 USA or visit www.sun.com if you need additional information or\r
+ * have any questions.\r
+ */\r
+package com.sun.lwuit;\r
+\r
+import com.sun.lwuit.geom.Dimension;\r
+import com.sun.lwuit.plaf.Style;\r
+import com.sun.lwuit.events.ActionEvent;\r
+import com.sun.lwuit.events.ActionListener;\r
+import com.sun.lwuit.layouts.BorderLayout;\r
+import com.sun.lwuit.list.DefaultListCellRenderer;\r
+import com.sun.lwuit.list.DefaultListModel;\r
+import com.sun.lwuit.list.ListCellRenderer;\r
+import com.sun.lwuit.list.ListModel;\r
+import com.sun.lwuit.plaf.UIManager;\r
+import java.util.Vector;\r
+\r
+/**\r
+ * A combo box is a list that allows only one selection at a time, when a user clicks\r
+ * the combo box a popup button with the full list of elements allows the selection of\r
+ * a single element. The combo box is driven by the list model and allows all the renderer\r
+ * features of the List as well. \r
+ * \r
+ * @see List\r
+ * @author Chen Fishbein\r
+ */\r
+public class ComboBox extends List {\r
+\r
+    private static String id = "ComboBox";\r
+    private Component popupContent;\r
+    private List contained;\r
+    private Popup popup;\r
+\r
+    /** \r
+     * Creates a new instance of ComboBox \r
+     * \r
+     * @param items set of items placed into the combo box model\r
+     */\r
+    public ComboBox(Vector items) {\r
+        this(new DefaultListModel(items));\r
+    }\r
+\r
+    /** \r
+     * Creates a new instance of ComboBox \r
+     * \r
+     * @param items set of items placed into the combo box model\r
+     */\r
+    public ComboBox(Object[] items) {\r
+        this(new DefaultListModel(items));\r
+    }\r
+\r
+    /** \r
+     * Constructs an empty combo box\r
+     */\r
+    public ComboBox() {\r
+        this(new DefaultListModel());\r
+    }\r
+\r
+    /**\r
+     * Creates a new instance of ComboBox \r
+     * \r
+     * @param model the model for the combo box elements and selection\r
+     */\r
+    public ComboBox(ListModel model) {\r
+        super(model);\r
+        ((DefaultListCellRenderer)super.getRenderer()).setShowNumbers(false);\r
+        setInputOnFocus(false);\r
+        setIsScrollVisible(false);\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    protected String getUIID() {\r
+        return id;\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void setSelectedIndex(int selection) {\r
+        super.setSelectedIndex(selection, false);\r
+    }\r
+    \r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void setSelectedIndex(int selection, boolean scroll) {\r
+        super.setSelectedIndex(selection, false);\r
+    }\r
+    \r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void setModel(ListModel m) {\r
+        super.setModel(m);\r
+        if (contained != null) {\r
+            contained.setModel(m);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void setHandlesInput(boolean handlesInput) {\r
+        super.setHandlesInput(handlesInput);\r
+        getPopup().setVisible(handlesInput);\r
+        if (isSmoothScrolling()) {\r
+            if (handlesInput) {\r
+                getComponentForm().registerAnimated(((Container) popupContent).getComponentAt(0));\r
+            } else {\r
+                getComponentForm().deregisterAnimated(((Container) popupContent).getComponentAt(0));\r
+            }\r
+        }\r
+    }\r
+\r
+    private Component getPopupContent() {\r
+\r
+        contained = new List(getModel());\r
+        contained.setFixedSelection(FIXED_NONE_CYCLIC);\r
+        contained.setListCellRenderer(getRenderer());\r
+        contained.addActionListener(new ActionListener() {\r
+\r
+            public void actionPerformed(ActionEvent evt) {\r
+                setHandlesInput(!handlesInput());\r
+                fireActionEvent();\r
+            }\r
+        });\r
+        Container cnt = new Container(new BorderLayout());\r
+        cnt.addComponent(BorderLayout.CENTER, contained);\r
+        contained.setStyle(UIManager.getInstance().getComponentStyle("ComboBoxPopup"));\r
+\r
+        popupContent = cnt;\r
+        return popupContent;\r
+    }\r
+\r
+    private Popup getPopup() {\r
+        if (popup == null) {\r
+            popup = new Popup(getComponentForm(), getPopupContent());\r
+        } else {\r
+            contained.setListCellRenderer(getRenderer());\r
+            contained.setModel(getModel());\r
+        }\r
+        int y = getAbsoluteY() + getHeight();\r
+        int height = Math.min(getComponentForm().getHeight() - y, popupContent.getPreferredSize().getHeight());\r
+        \r
+        // if there is not enough room to popup, open the popup upwards.\r
+        if(getComponentForm().getHeight() - y < contained.getElementSize(true).getHeight() * 3) {\r
+            height = contained.getElementSize(true).getHeight() * 3;\r
+            y = getAbsoluteY() - height;\r
+        }\r
+        popupContent.setHeight(height);\r
+        popupContent.setX(getAbsoluteX());\r
+        popupContent.setY(y);\r
+        popupContent.setWidth(getWidth());\r
+        popupContent.setFixedPosition(true);\r
+        Style s = popupContent.getStyle();\r
+        s.merge(getStyle());\r
+        s.setBgTransparency(0xFF);\r
+        s.setBorder(null);\r
+        s.setMargin(0, 0, 0, 0);\r
+        s.setPadding(0, 0, 0, 0);\r
+        return popup;\r
+    }\r
+\r
+    /**\r
+     * Reset popup data on model change to allow the popup to refresh with the \r
+     * right details\r
+     * \r
+     * @param status the model status\r
+     */\r
+    protected void modelChanged(int status) {\r
+        popup = null;\r
+        popupContent = null;\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void pointerReleased(int x, int y) {\r
+        setHandlesInput(true);\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void paint(Graphics g) {\r
+        UIManager.getInstance().getLookAndFeel().drawComboBox(g, this);\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    protected Dimension calcPreferredSize() {\r
+        return UIManager.getInstance().getLookAndFeel().getComboBoxPreferredSize(this);\r
+    }\r
+}\r
diff --git a/core/java/com/sun/lwuit/Command.java b/core/java/com/sun/lwuit/Command.java
new file mode 100644 (file)
index 0000000..6caf66f
--- /dev/null
@@ -0,0 +1,213 @@
+/*\r
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.\r
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\r
+ *\r
+ * This code is free software; you can redistribute it and/or modify it\r
+ * under the terms of the GNU General Public License version 2 only, as\r
+ * published by the Free Software Foundation.  Sun designates this\r
+ * particular file as subject to the "Classpath" exception as provided\r
+ * by Sun in the LICENSE file that accompanied this code.\r
+ *\r
+ * This code is distributed in the hope that it will be useful, but WITHOUT\r
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
+ * version 2 for more details (a copy is included in the LICENSE file that\r
+ * accompanied this code).\r
+ *\r
+ * You should have received a copy of the GNU General Public License version\r
+ * 2 along with this work; if not, write to the Free Software Foundation,\r
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,\r
+ * CA 95054 USA or visit www.sun.com if you need additional information or\r
+ * have any questions.\r
+ */\r
+\r
+package com.sun.lwuit;\r
+\r
+import com.sun.lwuit.events.ActionEvent;\r
+import com.sun.lwuit.events.ActionListener;\r
+\r
+/**\r
+ * The action placed on the soft buttons and in the Menu on devices, similar to the\r
+ * MIDP command abstraction and Swing's Actions. Unlike the MIDP abstraction this class \r
+ * can be derived to implement the right behavior\r
+ * \r
+ * @author Nir Shabi\r
+ */\r
+public class Command implements ActionListener{\r
+    private boolean disposesDialog = true;\r
+    private Image icon;\r
+    private String command;\r
+    \r
+    /**\r
+     * Simplifies code dealing with commands allowing them to be used in switch statements\r
+     * more easily\r
+     */\r
+    private int commandId;\r
+    \r
+    /**\r
+     * Creates a new instance of Command\r
+     * \r
+     * @param command the string that will be placed on the Soft buttons\Menu\r
+     */\r
+    public Command(String command) {\r
+        this.command = command;\r
+    }\r
+\r
+    /**\r
+     * Creates a new instance of Command\r
+     * \r
+     * @param command the string that will be placed on the Soft buttons\Menu\r
+     * @param icon the icon representing the command\r
+     */\r
+    public Command(String command, Image icon) {\r
+        this.command = command;\r
+        this.icon = icon;\r
+    }\r
+\r
+\r
+    /**\r
+     * Creates a new instance of Command\r
+     * \r
+     * @param command the string that will be placed on the Soft buttons\Menu\r
+     * @param id user defined ID for a command simplifying switch statement code\r
+     * working with a command\r
+     */\r
+    public Command(String command, int id) {\r
+        this.command = command;\r
+        this.commandId = id;\r
+    }\r
+    \r
+    /**\r
+     * Creates a new instance of Command\r
+     * \r
+     * @param command the string that will be placed on the Soft buttons\Menu\r
+     * @param icon the icon representing the command\r
+     * @param id user defined ID for a command simplifying switch statement code\r
+     * working with a command\r
+     */\r
+    public Command(String command, Image icon, int id) {\r
+        this.command = command;\r
+        this.commandId = id;\r
+        this.icon = icon;\r
+    }\r
+    \r
+    /**\r
+     * Creates a new instance of Command\r
+     * \r
+     * @param command the string that will be placed on the Soft buttons\Menu\r
+     * @param id user defined ID for a command simplifying switch statement code\r
+     * working with a command\r
+     * @param defaultAction Indicates that this action should occur by default \r
+     * on fire action event\r
+     * @deprecated this funcitionality is no longer supported use Form.setDefaultCommand() instead\r
+     */\r
+    public Command(String command, int id, boolean defaultAction) {\r
+        this.command = command;\r
+        this.commandId = id;\r
+    }\r
+\r
+    /**\r
+     * Creates a new instance of Command\r
+     * \r
+     * @param command the string that will be placed on the Soft buttons\Menu\r
+     * @param defaultAction Indicates that this action should occur by default \r
+     * on fire action event\r
+     * @deprecated this funcitionality is no longer supported use Form.setDefaultCommand() instead\r
+     */\r
+    public Command(String command, boolean defaultAction) {\r
+        this.command = command;\r
+    }\r
+\r
+    /**\r
+     * Return the command ID\r
+     * \r
+     * @return the command ID\r
+     */\r
+    public int getId() {\r
+        return commandId;\r
+    }\r
+    \r
+    /**\r
+     * gets the Command Name\r
+     * \r
+     * @return the Command name\r
+     */\r
+    public String getCommandName() {\r
+        return command;\r
+    }\r
+    \r
+    /**\r
+     * Returns the icon representing the command\r
+     * \r
+     * @return an icon representing the command\r
+     */\r
+    public Image getIcon() {\r
+        return icon;\r
+    }\r
+    \r
+    /**\r
+     * Returns a string representation of the object\r
+     * \r
+     * @return Returns a string representation of the object\r
+     */\r
+    public String toString() {\r
+        return command;\r
+    }\r
+    \r
+    /**\r
+     * compare two commands\r
+     * \r
+     * @param obj a Command Object to compare\r
+     * @return true if the obj has the same command name\r
+     */\r
+    public boolean equals(Object obj) {\r
+        return (obj != null) && obj.getClass() == getClass() && ((Command)obj).command == command && ((Command)obj).commandId == commandId;\r
+    }\r
+\r
+    public int hashCode() {\r
+        return getClass().hashCode() + commandId;\r
+    }\r
+    \r
+    /**\r
+     * This method is called when the soft button/Menu item is clicked\r
+     * \r
+     * @param evt the Event Object\r
+     */\r
+    public void actionPerformed(ActionEvent evt) {\r
+    }\r
+\r
+    /**\r
+     * Indicates that this action should occur by default on fire action event\r
+     * \r
+     * @return true if it is the default action event\r
+     * @deprecated this funcitionality is no longer supported use Form.setDefaultCommand() instead\r
+     */\r
+    public boolean isDefaultAction() {\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Setting the default action event\r
+     * \r
+     * @param defaultAction the default action event\r
+     * @deprecated this funcitionality is no longer supported use Form.setDefaultCommand() instead\r
+     */\r
+    public void setDefaultAction(boolean defaultAction) {\r
+    }\r
+    \r
+    /**\r
+     * Indicates whether this command causes the dialog to dispose implicitly\r
+     */\r
+    void setDisposesDialog(boolean disposesDialog) {\r
+        this.disposesDialog = disposesDialog;\r
+    }\r
+    \r
+    /**\r
+     * Indicates whether this command causes the dialog to dispose implicitly\r
+     */\r
+    boolean isDisposesDialog() {\r
+        return disposesDialog;\r
+    }\r
+}\r
diff --git a/core/java/com/sun/lwuit/Component.java b/core/java/com/sun/lwuit/Component.java
new file mode 100644 (file)
index 0000000..22448ee
--- /dev/null
@@ -0,0 +1,2044 @@
+/*\r
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.\r
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\r
+ *\r
+ * This code is free software; you can redistribute it and/or modify it\r
+ * under the terms of the GNU General Public License version 2 only, as\r
+ * published by the Free Software Foundation.  Sun designates this\r
+ * particular file as subject to the "Classpath" exception as provided\r
+ * by Sun in the LICENSE file that accompanied this code.\r
+ *\r
+ * This code is distributed in the hope that it will be useful, but WITHOUT\r
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
+ * version 2 for more details (a copy is included in the LICENSE file that\r
+ * accompanied this code).\r
+ *\r
+ * You should have received a copy of the GNU General Public License version\r
+ * 2 along with this work; if not, write to the Free Software Foundation,\r
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,\r
+ * CA 95054 USA or visit www.sun.com if you need additional information or\r
+ * have any questions.\r
+ */\r
+package com.sun.lwuit;\r
+\r
+import com.sun.lwuit.geom.Rectangle;\r
+import com.sun.lwuit.geom.Dimension;\r
+import com.sun.lwuit.plaf.Style;\r
+import com.sun.lwuit.animations.Animation;\r
+import com.sun.lwuit.animations.Motion;\r
+import com.sun.lwuit.events.FocusListener;\r
+import com.sun.lwuit.events.StyleListener;\r
+import com.sun.lwuit.plaf.Border;\r
+import com.sun.lwuit.plaf.LookAndFeel;\r
+import com.sun.lwuit.plaf.UIManager;\r
+import java.util.Hashtable;\r
+import java.util.Vector;\r
+\r
+/**\r
+ * Base class for all the widgets in the toolkit using the composite pattern in \r
+ * a similar way to the AWT Container/Component relationship. All components are\r
+ * potentially animated (need to be registered in {@link Display}). \r
+ * \r
+ * @author Chen Fishbein\r
+ */\r
+public class Component implements Animation, StyleListener {\r
+\r
+    /**\r
+     * Allows us to determine which component will receive focus next when travering \r
+     * with the down key\r
+     */\r
+    private Component nextFocusDown;\r
+    private Component nextFocusUp;\r
+    /**\r
+     * Indicates whether component is enabled or disabled\r
+     */\r
+    private boolean enabled = true;\r
+    /**\r
+     * Allows us to determine which component will receive focus next when travering \r
+     * with the right key\r
+     */\r
+    private Component nextFocusRight;\r
+    private Component nextFocusLeft;\r
+    /**\r
+     * Baseline resize behavior constant used to properly align components. \r
+     * Indicates as the size of the component\r
+     * changes the baseline remains a fixed distance from the top of the\r
+     * component.\r
+     * @see #getBaselineResizeBehavior\r
+     */\r
+    public static final int BRB_CONSTANT_ASCENT = 1;\r
+    /**\r
+     * Baseline resize behavior constant used to properly align components. Indicates as the size of the component\r
+     * changes the baseline remains a fixed distance from the bottom of the \r
+     * component.\r
+     * @see #getBaselineResizeBehavior\r
+     */\r
+    public static final int BRB_CONSTANT_DESCENT = 2;\r
+    /**\r
+     * Baseline resize behavior constant used to properly align components. Indicates as the size of the component\r
+     * changes the baseline remains a fixed distance from the center of the\r
+     * component.\r
+     * @see #getBaselineResizeBehavior\r
+     */\r
+    public static final int BRB_CENTER_OFFSET = 3;\r
+    /**\r
+     * Baseline resize behavior constant used to properly align components. Indicates as the size of the component\r
+     * changes the baseline can not be determined using one of the other\r
+     * constants.\r
+     * @see #getBaselineResizeBehavior\r
+     */\r
+    public static final int BRB_OTHER = 4;\r
+    private boolean visible = true;\r
+    /**\r
+     * Used as an optimization to mark that this component is currently being\r
+     * used as a cell renderer\r
+     */\r
+    private boolean cellRenderer;\r
+    /**\r
+     * Indicates that this component is fixed into place and not affected by\r
+     * scrolling of the parent container. This is applicable for components such as\r
+     * menus etc...\r
+     */\r
+    private boolean fixedPosition;\r
+    private Rectangle bounds = new Rectangle(0, 0, new Dimension(0, 0));\r
+    private int scrollX;\r
+    private int scrollY;\r
+    private Dimension preferredSize;\r
+    private Style style;\r
+    private Container parent;\r
+    private boolean focused = false;\r
+    private boolean focusPainted = true;\r
+    private EventDispatcher focusListeners = new EventDispatcher();\r
+    private boolean handlesInput = false;\r
+    private boolean shouldCalcPreferredSize = true;\r
+    private boolean focusable = true;\r
+    private boolean isScrollVisible = true;\r
+    /**\r
+     * Indicates that moving through the component should work as an animation\r
+     */\r
+    private boolean smoothScrolling;\r
+    /**\r
+     * Animation speed in milliseconds allowing a developer to slow down or accelerate\r
+     * the smooth animation mode\r
+     */\r
+    private int animationSpeed;\r
+    private Motion animationMotion;\r
+    private Motion draggedMotion;\r
+    /**\r
+     * Allows us to flag a drag operation in action thus preventing the mouse pointer\r
+     * release event from occuring.\r
+     */\r
+    private boolean dragActivated;\r
+    private int initialScrollY = -1;\r
+    private int destScrollY = -1;\r
+    private int lastScrollY;\r
+    private int beforeLastScrollY;\r
+    private long[] lastTime = new long[2];\r
+    private int[] lastDragged = new int[2];\r
+    private int pLastDragged = 0;\r
+    /**\r
+     * Indicates if the component is in the initalized state, a component is initialized\r
+     * when its initComponent() method was invoked. The initMethod is invoked before showing the\r
+     * component to the user.\r
+     */\r
+    private boolean initialized;\r
+    /**\r
+     * Indicates a Component center alignment\r
+     */\r
+    public static final int CENTER = 4;\r
+    /** \r
+     * Box-orientation constant used to specify the top of a box.\r
+     */\r
+    public static final int TOP = 0;\r
+    /** \r
+     * Box-orientation constant used to specify the left side of a box.\r
+     */\r
+    public static final int LEFT = 1;\r
+    /** \r
+     * Box-orientation constant used to specify the bottom of a box.\r
+     */\r
+    public static final int BOTTOM = 2;\r
+    /** \r
+     * Box-orientation constant used to specify the right side of a box.\r
+     */\r
+    public static final int RIGHT = 3;\r
+    private Hashtable clientProperties;\r
+    private Rectangle dirtyRegion = null;\r
+\r
+    /** \r
+     * Creates a new instance of Component \r
+     */\r
+    protected Component() {\r
+        style = UIManager.getInstance().getComponentStyle(getUIID());\r
+        if (style != null) {\r
+            style.addStyleListener(this);\r
+            style.setBgPainter(new BGPainter());\r
+        }\r
+        LookAndFeel laf = UIManager.getInstance().getLookAndFeel();\r
+        animationSpeed = laf.getDefaultSmoothScrollingSpeed();\r
+        setSmoothScrolling(laf.isDefaultSmoothScrolling());\r
+    }\r
+\r
+    /**\r
+     * Returns the current component x location relatively to its parent container\r
+     * \r
+     * @return the current x coordinate of the components origin\r
+     */\r
+    public int getX() {\r
+        return bounds.getX();\r
+    }\r
+\r
+    /**\r
+     * Returns the component y location relatively to its parent container\r
+     * \r
+     * @return the current y coordinate of the components origin\r
+     */\r
+    public int getY() {\r
+        return bounds.getY();\r
+    }\r
+\r
+    /**\r
+     * Returns whether the component is visible or not\r
+     * \r
+     * @return true if component is visible; otherwise false \r
+     */\r
+    public boolean isVisible() {\r
+        return visible;\r
+    }\r
+\r
+    /**\r
+     * Client properties allow the association of meta-data with a component, this\r
+     * is useful for some applications that construct GUI's on the fly and need\r
+     * to track the connection between the UI and the data. \r
+     * \r
+     * @param key the key used for putClientProperty\r
+     * @return the value set to putClientProperty or null if no value is set to the property\r
+     */\r
+    public Object getClientProperty(String key) {\r
+        if (clientProperties == null) {\r
+            return null;\r
+        }\r
+        return clientProperties.get(key);\r
+    }\r
+\r
+    /**\r
+     * Client properties allow the association of meta-data with a component, this\r
+     * is useful for some applications that construct GUI's on the fly and need\r
+     * to track the connection between the UI and the data. Setting the value to\r
+     * null will remove the client property from the component.\r
+     * \r
+     * @param key arbitrary key for the property\r
+     * @param value the value assigned to the given client property\r
+     */\r
+    public void putClientProperty(String key, Object value) {\r
+        if (clientProperties == null) {\r
+            if (value == null) {\r
+                return;\r
+            }\r
+            clientProperties = new Hashtable();\r
+        }\r
+        if (value == null) {\r
+            clientProperties.remove(key);\r
+            if (clientProperties.size() == 0) {\r
+                clientProperties = null;\r
+            }\r
+        } else {\r
+            clientProperties.put(key, value);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * gets the Component dirty region\r
+     * \r
+     * @return\r
+     */\r
+    Rectangle getDirtyRegion() {\r
+        return dirtyRegion;\r
+    }\r
+\r
+    /**\r
+     * sets the Component dirty region\r
+     * \r
+     * @param dirty\r
+     */\r
+    void setDirtyRegion(Rectangle dirty) {\r
+        this.dirtyRegion = dirty;\r
+    }\r
+\r
+    /**\r
+     * Toggles visibility of the component\r
+     * \r
+     * @param visible true if component is visible; otherwise false \r
+     */\r
+    public void setVisible(boolean visible) {\r
+        this.visible = visible;\r
+    }\r
+\r
+    /**\r
+     * Returns the component width\r
+     * \r
+     * @return the component width\r
+     */\r
+    public int getWidth() {\r
+        return bounds.getSize().getWidth();\r
+    }\r
+\r
+    /**\r
+     * Returns the component height\r
+     * \r
+     * @return the component height\r
+     */\r
+    public int getHeight() {\r
+        return bounds.getSize().getHeight();\r
+    }\r
+\r
+    /**\r
+     * Sets the Component x location relative to the parent container, this method\r
+     * is exposed for the purpose of external layout managers and should not be invoked\r
+     * directly.\r
+     * \r
+     * @param x the current x coordinate of the components origin\r
+     */\r
+    public void setX(int x) {\r
+        bounds.setX(x);\r
+    }\r
+\r
+    /**\r
+     * Sets the Component y location relative to the parent container, this method\r
+     * is exposed for the purpose of external layout managers and should not be invoked\r
+     * directly.\r
+     * \r
+     * @param y the current y coordinate of the components origin\r
+     */\r
+    public void setY(int y) {\r
+        bounds.setY(y);\r
+    }\r
+\r
+    /**\r
+     * The baseline for the component text according to which it should be aligned\r
+     * with other components for best visual look.\r
+     * \r
+     * \r
+     * @param width the component width\r
+     * @param height the component height\r
+     * @return baseline value from the top of the component\r
+     */\r
+    public int getBaseline(int width, int height) {\r
+        return getHeight() - getStyle().getPadding(BOTTOM);\r
+    }\r
+\r
+    /**\r
+     * Returns a constant indicating how the baseline varies with the size\r
+     * of the component.\r
+     *\r
+     * @return one of BRB_CONSTANT_ASCENT, BRB_CONSTANT_DESCENT,\r
+     *         BRB_CENTER_OFFSET or BRB_OTHER\r
+     */\r
+    public int getBaselineResizeBehavior() {\r
+        return BRB_OTHER;\r
+    }\r
+\r
+    /**\r
+     * Sets the Component Preferred Size, there is no garuntee the Component will \r
+     * be sized at its Preferred Size. The final size of the component may be\r
+     * smaller than its preferred size or even larger than the size.<br>\r
+     * The Layout manager can take this value into consideration, but there is\r
+     * no guarantee or requirement.\r
+     * \r
+     * @param d the component dimension\r
+     */\r
+    public void setPreferredSize(Dimension d) {\r
+        preferredSize().setWidth(d.getWidth());\r
+        preferredSize().setHeight(d.getHeight());\r
+        sizeRequestedByUser = true;\r
+    }\r
+\r
+    /**\r
+     * Returns the Component Preferred Size, there is no garuntee the Component will \r
+     * be sized at its Preferred Size. The final size of the component may be\r
+     * smaller than its preferred size or even larger than the size.<br>\r
+     * The Layout manager can take this value into consideration, but there is\r
+     * no guarantee or requirement.\r
+     * \r
+     * @return the component preferred size\r
+     */\r
+    public Dimension getPreferredSize() {\r
+        return preferredSize();\r
+    }\r
+\r
+    /**\r
+     * Helper method to set the preferred width of the component.\r
+     * \r
+     * @param preferredW the preferred width of the component\r
+     * @see #setPreferredSize\r
+     * @deprecated see setPreferredSize this method won't behave as you expect!\r
+     */\r
+    public void setPreferredW(int preferredW) {\r
+        setPreferredSize(new Dimension(preferredW, getPreferredH()));\r
+    }\r
+\r
+    /**\r
+     * Helper method to set the preferred height of the component.\r
+     * \r
+     * @param preferredH the preferred height of the component\r
+     * @see #setPreferredSize\r
+     * @deprecated see setPreferredSize this method won't behave as you expect!\r
+     */\r
+    public void setPreferredH(int preferredH) {\r
+        setPreferredSize(new Dimension(getPreferredW(), preferredH));\r
+    }\r
+\r
+    /**\r
+     * Helper method to retrieve the preferred width of the component.\r
+     * \r
+     * @return preferred width of the component\r
+     * @see #getPreferredSize\r
+     */\r
+    public int getPreferredW() {\r
+        return getPreferredSize().getWidth();\r
+    }\r
+\r
+    /**\r
+     * Helper method to retrieve the preferred height of the component.\r
+     * \r
+     * @return preferred height of the component\r
+     * @see #getPreferredSize\r
+     */\r
+    public int getPreferredH() {\r
+        return getPreferredSize().getHeight();\r
+    }\r
+\r
+    /**\r
+     * Sets the Component width, this method is exposed for the purpose of \r
+     * external layout managers and should not be invoked directly.<br>\r
+     * If a user wishes to effect the component size setPreferredSize should\r
+     * be used.\r
+     * \r
+     * @param width the width of the component\r
+     * @see #setPreferredSize\r
+     */\r
+    public void setWidth(int width) {\r
+        bounds.getSize().setWidth(width);\r
+    }\r
+\r
+    /**\r
+     * Sets the Component height, this method is exposed for the purpose of \r
+     * external layout managers and should not be invoked directly.<br>\r
+     * If a user wishes to effect the component size setPreferredSize should\r
+     * be used.\r
+     * \r
+     * @param height the height of the component\r
+     * @see #setPreferredSize\r
+     */\r
+    public void setHeight(int height) {\r
+        bounds.getSize().setHeight(height);\r
+    }\r
+\r
+    /**\r
+     * Sets the Component size, this method is exposed for the purpose of \r
+     * external layout managers and should not be invoked directly.<br>\r
+     * If a user wishes to effect the component size setPreferredSize should\r
+     * be used.\r
+     * \r
+     * @param d the component dimension\r
+     * @see #setPreferredSize\r
+     */\r
+    public void setSize(Dimension d) {\r
+        Dimension d2 = bounds.getSize();\r
+        d2.setWidth(d.getWidth());\r
+        d2.setHeight(d.getHeight());\r
+    }\r
+\r
+    /**\r
+     * Unique identifier for a component, must be overriden for a component so\r
+     * a style can be applied to the component\r
+     * \r
+     * @return unique string identifying this component for the style sheet\r
+     */\r
+    protected String getUIID() {\r
+        return null;\r
+    }\r
+\r
+    /**\r
+     * Returns the container in which this component is contained\r
+     * \r
+     * @return the parent container in which this component is contained\r
+     */\r
+    public Container getParent() {\r
+        return parent;\r
+    }\r
+\r
+    /**\r
+     * Sets the Component Parent.\r
+     * This method should not be called by the user.\r
+     * \r
+     * @param parent the parent container\r
+     */\r
+    void setParent(Container parent) {\r
+        this.parent = parent;\r
+    }\r
+\r
+    /**\r
+     * Registers interest in receiving callbacks for focus gained events, a focus event \r
+     * is invoked when the component accepts the focus. A special case exists for the\r
+     * Form which sends a focus even for every selection within the form.\r
+     * \r
+     * @param l listener interface implementing the observable pattern\r
+     */\r
+    public void addFocusListener(FocusListener l) {\r
+        focusListeners.addListener(l);\r
+    }\r
+\r
+    /**\r
+     * Deregisters interest in receiving callbacks for focus gained events\r
+     * \r
+     * @param l listener interface implementing the observable pattern\r
+     */\r
+    public void removeFocusListener(FocusListener l) {\r
+        focusListeners.removeListener(l);\r
+    }\r
+\r
+    /**\r
+     * When working in 3 softbutton mode "fire" key (center softbutton) is sent to this method\r
+     * in order to allow 3 button devices to work properly. When overriding this method\r
+     * you should also override isSelectableInteraction to indicate that a command is placed\r
+     * appropriately on top of the fire key for 3 soft button phones. \r
+     */\r
+    protected void fireClicked() {\r
+    }\r
+\r
+    /**\r
+     * This method allows a component to indicate that it is interested in an "implicit" select\r
+     * command to appear in the "fire" button when 3 softbuttons are defined in a device.\r
+     */\r
+    protected boolean isSelectableInteraction() {\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Fired when component gains focus\r
+     */\r
+    void fireFocusGained() {\r
+        fireFocusGained(this);\r
+    }\r
+\r
+    /**\r
+     * Fired when component lost focus\r
+     */\r
+    void fireFocusLost() {\r
+        fireFocusLost(this);\r
+    }\r
+\r
+    /**\r
+     * Fired when component gains focus\r
+     */\r
+    void fireFocusGained(Component cmp) {\r
+        if (cmp.isCellRenderer()) {\r
+            return;\r
+        }\r
+\r
+        focusListeners.fireFocus(cmp);\r
+        focusGainedInternal();\r
+        if (isSelectableInteraction()) {\r
+            Form f = getComponentForm();\r
+            if (f != null) {\r
+                f.addSelectCommand();\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Fired when component lost focus\r
+     */\r
+    void fireFocusLost(Component cmp) {\r
+        if (cmp.isCellRenderer()) {\r
+            return;\r
+        }\r
+        if (isSelectableInteraction()) {\r
+            Form f = getComponentForm();\r
+            if (f != null) {\r
+                f.removeSelectCommand();\r
+            }\r
+        }\r
+\r
+        focusListeners.fireFocus(cmp);\r
+        focusLostInternal();\r
+    }\r
+\r
+    /**\r
+     * This method allows us to detect an action event internally without \r
+     * implementing the action listener interface.\r
+     */\r
+    void fireActionEvent() {\r
+    }\r
+\r
+    /**\r
+     * This method is useful since it is not a part of the public API yet\r
+     * allows a component within this package to observe focus events\r
+     * without implementing a public interface or creating a new class\r
+     */\r
+    void focusGainedInternal() {\r
+    }\r
+\r
+    /**\r
+     * This method is useful since it is not a part of the public API yet\r
+     * allows a component within this package to observe focus events\r
+     * without implementing a public interface or creating a new class\r
+     */\r
+    void focusLostInternal() {\r
+    }\r
+\r
+    /**\r
+     * This method paints all the parents Components Background.\r
+     * \r
+     * @param g the graphics object\r
+     */\r
+    public void paintBackgrounds(Graphics g) {\r
+        Rectangle bounds = new Rectangle(getAbsoluteX(), getAbsoluteY(),\r
+                getWidth(), getHeight());\r
+        drawPainters(g, this.getParent(), this, bounds);\r
+    }\r
+\r
+    /**\r
+     * Returns the absolute X location based on the component hierarchy, this method\r
+     * calculates a location on the screen for the component rather than a relative\r
+     * location as returned by getX()\r
+     * \r
+     * @return the absolute x location of the component\r
+     * @see #getX\r
+     */\r
+    public int getAbsoluteX() {\r
+        int x = getX() - getScrollX();\r
+        Container parent = getParent();\r
+        if (parent != null) {\r
+            x += parent.getAbsoluteX();\r
+        }\r
+        return x;\r
+    }\r
+\r
+    /**\r
+     * Returns the absolute Y location based on the component hierarchy, this method\r
+     * calculates a location on the screen for the component rather than a relative\r
+     * location as returned by getX()\r
+     * \r
+     * @return the absolute y location of the component\r
+     * @see #getY\r
+     */\r
+    public int getAbsoluteY() {\r
+        int y = getY() - getScrollY();\r
+        Container parent = getParent();\r
+        if (parent != null) {\r
+            y += parent.getAbsoluteY();\r
+        }\r
+        return y;\r
+    }\r
+\r
+    /**\r
+     * This method performs the paint of the component internally including drawing\r
+     * the scrollbars and scrolling the component. This functionality is hidden\r
+     * from developers to prevent errors\r
+     * \r
+     * @param g the component graphics\r
+     */\r
+    final void paintInternal(Graphics g) {\r
+        paintInternal(g, true);\r
+    }\r
+\r
+    final void paintInternal(Graphics g, boolean paintIntersects) {\r
+        if (!isVisible()) {\r
+            return;\r
+        }\r
+        int oX = g.getClipX();\r
+        int oY = g.getClipY();\r
+        int oWidth = g.getClipWidth();\r
+        int oHeight = g.getClipHeight();\r
+        if (bounds.intersects(oX, oY, oWidth, oHeight)) {\r
+            g.clipRect(getX(), getY(), getWidth(), getHeight());\r
+            paintBackground(g);\r
+\r
+            if (isScrollable()) {\r
+                int scrollX = getScrollX();\r
+                int scrollY = getScrollY();\r
+                g.translate(-scrollX, -scrollY);\r
+                paint(g);\r
+                g.translate(scrollX, scrollY);\r
+                if (isScrollVisible) {\r
+                    paintScrollbars(g);\r
+                }\r
+            } else {\r
+                paint(g);\r
+            }\r
+            if (isBorderPainted()) {\r
+                paintBorder(g);\r
+            }\r
+\r
+            //paint all the intersecting Components above the Component\r
+            if (paintIntersects && parent != null) {\r
+                paintIntersectingComponentsAbove(g);\r
+            }\r
+\r
+            g.setClip(oX, oY, oWidth, oHeight);\r
+        }\r
+    }\r
+\r
+    private void paintIntersectingComponentsAbove(Graphics g) {\r
+        Container parent = getParent();\r
+        Component component = this;\r
+        Rectangle bounds = new Rectangle(getAbsoluteX(), getAbsoluteY(),\r
+                getWidth(), getHeight());\r
+        int tx = g.getTranslateX();\r
+        int ty = g.getTranslateY();\r
+\r
+        g.translate(-tx, -ty);\r
+        while (parent != null) {\r
+            g.translate(parent.getAbsoluteX() + parent.getScrollX(), \r
+                    parent.getAbsoluteY() + parent.getScrollY());\r
+            parent.paintIntersecting(g, component, bounds, true);\r
+            g.translate(-parent.getAbsoluteX() - parent.getScrollX(), \r
+                    -parent.getAbsoluteY() - parent.getScrollY());\r
+            component = parent;\r
+            parent = parent.getParent();\r
+        }\r
+        g.translate(tx, ty);\r
+\r
+    }\r
+\r
+    /**\r
+     * Paints the UI for the scrollbars on the component, this will be invoked only\r
+     * for scrollable components. This method invokes the appropriate X/Y versions\r
+     * to do all the work.\r
+     * \r
+     * @param g the component graphics\r
+     */\r
+    protected void paintScrollbars(Graphics g) {\r
+        if (isScrollableX()) {\r
+            paintScrollbarX(g);\r
+        }\r
+        if (isScrollableY()) {\r
+            paintScrollbarY(g);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Paints the UI for the scrollbar on the X axis, this method allows component\r
+     * subclasses to customize the look of a scrollbar\r
+     * \r
+     * @param g the component graphics\r
+     */\r
+    protected void paintScrollbarX(Graphics g) {\r
+        float offset = ((float) getScrollX()) / ((float) getPreferredW());\r
+        float block = ((float) getWidth()) / ((float) getPreferredW());\r
+        UIManager.getInstance().getLookAndFeel().drawHorizontalScroll(g, this, offset, block);\r
+    }\r
+\r
+    /**\r
+     * Paints the UI for the scrollbar on the Y axis, this method allows component\r
+     * subclasses to customize the look of a scrollbar\r
+     * \r
+     * @param g the component graphics\r
+     */\r
+    protected void paintScrollbarY(Graphics g) {\r
+        float offset = ((float) getScrollY()) / ((float) getPreferredH());\r
+        float block = ((float) getHeight()) / ((float) getPreferredH());\r
+        UIManager.getInstance().getLookAndFeel().drawVerticalScroll(g, this, offset, block);\r
+    }\r
+\r
+    /**\r
+     * Paints this component as a root by going to all the parent components and\r
+     * setting the absolute translation based on coordinates and scroll status.\r
+     * Restores translation when the painting is finished.\r
+     * \r
+     * @param g the graphics to paint this Component on\r
+     */\r
+    final public void paintComponent(Graphics g) {\r
+        paintComponent(g, true);\r
+    }\r
+\r
+    /**\r
+     * Paints this component as a root by going to all the parent components and\r
+     * setting the absolute translation based on coordinates and scroll status.\r
+     * Restores translation when the painting is finished.\r
+     * \r
+     * @param g the graphics to paint this Component on\r
+     * @param background if true paints all parents background\r
+     */\r
+    final public void paintComponent(Graphics g, boolean background) {\r
+        int clipX = g.getClipX();\r
+        int clipY = g.getClipX();\r
+        int clipW = g.getClipWidth();\r
+        int clipH = g.getClipHeight();\r
+        Container parent = getParent();\r
+        int translateX = 0;\r
+        int translateY = 0;\r
+        if (!isFixedPosition()) {\r
+            while (parent != null) {\r
+                translateX += parent.getX();\r
+                translateY += parent.getY();\r
+                //if (parent.isScrollable()) {\r
+                if (parent.isScrollableX()) {\r
+                    translateX -= parent.getScrollX();\r
+                }\r
+                if (parent.isScrollableY()) {\r
+                    translateY -= parent.getScrollY();\r
+                }\r
+                // since scrollability can translate everything... we should clip based on the\r
+                // current scroll\r
+                g.clipRect(parent.getAbsoluteX() + parent.getScrollX(), parent.getAbsoluteY() + parent.getScrollY(), parent.getWidth(), parent.getHeight());\r
+                //}\r
+                // restore the position for fixed components\r
+                if (parent.isFixedPosition()) {\r
+                    translateX = parent.getX();\r
+                    translateY = parent.getY();\r
+                    g.clipRect(parent.getX(), parent.getY(), parent.getWidth(), parent.getHeight());\r
+                    break;\r
+                }\r
+                parent = parent.getParent();\r
+            }\r
+        }\r
+        g.clipRect(translateX + getX(), translateY + getY(), getWidth(), getHeight());\r
+        if (background) {\r
+            paintBackgrounds(g);\r
+        }\r
+\r
+        g.translate(translateX, translateY);\r
+        paintInternal(g);\r
+        g.translate(-translateX, -translateY);\r
+\r
+        Form parentForm = getComponentForm();\r
+        if (parentForm != null) {\r
+            Painter glass = parentForm.getGlassPane();\r
+            if (glass != null) {\r
+                glass.paint(g, parentForm.getBounds());\r
+            }\r
+        }\r
+\r
+        g.setClip(clipX, clipY, clipW, clipH);\r
+    }\r
+\r
+    private void drawPainters(com.sun.lwuit.Graphics g, Component par, Component c,\r
+            Rectangle bounds) {\r
+        if (par == null) {\r
+            return;\r
+        } else {\r
+            if (par.getStyle().getBgTransparency() != ((byte) 0xFF)) {\r
+                drawPainters(g, par.getParent(), par, bounds);\r
+            }\r
+        }\r
+\r
+        int transX = par.getAbsoluteX() + par.getScrollX();\r
+        int transY = par.getAbsoluteY() + par.getScrollY();\r
+\r
+        g.translate(transX, transY);\r
+\r
+        ((Container) par).paintIntersecting(g, c, bounds, false);\r
+\r
+        if (par.isBorderPainted()) {\r
+            Border b = par.getBorder();\r
+            if (b != null && b.isBackgroundPainter()) {\r
+                g.translate(-par.getX(), -par.getY());\r
+                b.paintBorderBackground(g, par);\r
+                b.paint(g, par);\r
+                g.translate(par.getX() - transX, par.getY() - transY);\r
+            }\r
+        } else {\r
+            Painter p = par.getStyle().getBgPainter();\r
+            if (p != null) {\r
+                p.paint(g, new Rectangle(0, 0, par.getWidth(), par.getHeight()));\r
+            }\r
+            g.translate(-transX, -transY);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Normally returns getStyle().getBorder() but some subclasses might use this \r
+     * to programmatically replace the border in runtime e.g. for a pressed border effect\r
+     * \r
+     * @return the borde that is drawn according to the current component state\r
+     */\r
+    protected Border getBorder() {\r
+        Border b = getStyle().getBorder();\r
+        if (hasFocus()) {\r
+            if (b != null) {\r
+                return b.getFocusedInstance();\r
+            }\r
+            return b;\r
+        } else {\r
+            return b;\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Paints the background of the component, invoked with the clipping region\r
+     * and appropriate scroll translation.\r
+     * \r
+     * @param g the component graphics\r
+     */\r
+    protected void paintBackground(Graphics g) {\r
+        if (isBorderPainted()) {\r
+            Border b = getBorder();\r
+            if (b != null && b.isBackgroundPainter()) {\r
+                b.paintBorderBackground(g, this);\r
+                return;\r
+            }\r
+        }\r
+        if (getStyle().getBgPainter() != null) {\r
+            getStyle().getBgPainter().paint(g, new Rectangle(getX(), getY(), getWidth(), getHeight()));\r
+        }\r
+    }\r
+\r
+    /**\r
+     * This method paints the Component on the screen, it should be overriden\r
+     * by subclasses to perform custom drawing or invoke the UI API's to let\r
+     * the PLAF perform the rendering.\r
+     * \r
+     * @param g the component graphics\r
+     */\r
+    public void paint(Graphics g) {\r
+    }\r
+\r
+    /**\r
+     * Indicates whether the component should/could scroll by default a component\r
+     * is not scrollable.\r
+     * \r
+     * @return whether the component is scrollable\r
+     */\r
+    protected boolean isScrollable() {\r
+        return isScrollableX() || isScrollableY();\r
+    }\r
+\r
+    /**\r
+     * Indicates whether the component should/could scroll on the X axis\r
+     * \r
+     * @return whether the component is scrollable on the X axis\r
+     */\r
+    public boolean isScrollableX() {\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Indicates whether the component should/could scroll on the Y axis\r
+     * \r
+     * @return whether the component is scrollable on the X axis\r
+     */\r
+    public boolean isScrollableY() {\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Indicates the X position of the scrolling, this number is relative to the\r
+     * component position and so a position of 0 would indicate the x position\r
+     * of the component.\r
+     * \r
+     * @return the X position of the scrolling\r
+     */\r
+    public int getScrollX() {\r
+        return scrollX;\r
+    }\r
+\r
+    /**\r
+     * Indicates the Y position of the scrolling, this number is relative to the\r
+     * component position and so a position of 0 would indicate the x position\r
+     * of the component.\r
+     * \r
+     * @return the Y position of the scrolling\r
+     */\r
+    public int getScrollY() {\r
+        return scrollY;\r
+    }\r
+\r
+    /**\r
+     * Indicates the X position of the scrolling, this number is relative to the\r
+     * component position and so a position of 0 would indicate the x position\r
+     * of the component.\r
+     * \r
+     * @param scrollX the X position of the scrolling\r
+     */\r
+    protected void setScrollX(int scrollX) {\r
+        if (isScrollableX()) {\r
+            this.scrollX = scrollX;\r
+            repaint();\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Indicates the X position of the scrolling, this number is relative to the\r
+     * component position and so a position of 0 would indicate the x position\r
+     * of the component.\r
+     * \r
+     * @param scrollY the Y position of the scrolling\r
+     */\r
+    protected void setScrollY(int scrollY) {\r
+        if (isScrollableY()) {\r
+            this.scrollY = scrollY;\r
+            repaint();\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Returns the gap to be left for the bottom scrollbar on the X axis. This\r
+     * method is used by layout managers to determine the room they should\r
+     * leave for the scrollbar\r
+     * \r
+     * @return the gap to be left for the bottom scrollbar on the X axis\r
+     */\r
+    public int getBottomGap() {\r
+        if (isScrollableX()) {\r
+            return UIManager.getInstance().getLookAndFeel().getHorizontalScrollHeight();\r
+        }\r
+        return 0;\r
+    }\r
+\r
+    /**\r
+     * Returns the gap to be left for the side scrollbar on the Y axis. This\r
+     * method is used by layout managers to determine the room they should\r
+     * leave for the scrollbar. (note: side scrollbar rather than left scrollbar\r
+     * is used for a future version that would support bidi).\r
+     * \r
+     * @return the gap to be left for the side scrollbar on the Y axis\r
+     */\r
+    public int getSideGap() {\r
+        if (isScrollableY()) {\r
+            return UIManager.getInstance().getLookAndFeel().getVerticalScrollWidth();\r
+        }\r
+        return 0;\r
+    }\r
+\r
+    /**\r
+     * Retuns true if the given absolute cordinate is contained in the Component\r
+     * \r
+     * @param x the given absolute x cordinate\r
+     * @param y the given absolute y cordinate\r
+     * @return true if the given absolute cordinate is contained in the \r
+     * Component; otherwise false\r
+     */\r
+    public boolean contains(int x, int y) {\r
+        int absX = getAbsoluteX() + getScrollX();\r
+        int absY = getAbsoluteY() + getScrollY();\r
+        return (x >= absX && x < absX + getWidth() && y >= absY && y < absY + getHeight());\r
+    }\r
+\r
+    /**\r
+     * Calculates the preferred size based on component content. This method is\r
+     * invoked lazily by getPreferred size.\r
+     * \r
+     * @return the calculated preferred size based on component content\r
+     */\r
+    protected Dimension calcPreferredSize() {\r
+        Dimension d = new Dimension(0, 0);\r
+        return d;\r
+    }\r
+    private boolean sizeRequestedByUser = false;\r
+\r
+    private Dimension preferredSize() {\r
+\r
+        if (!sizeRequestedByUser && (shouldCalcPreferredSize || preferredSize == null)) {\r
+            shouldCalcPreferredSize = false;\r
+            preferredSize = calcPreferredSize();\r
+        }\r
+        return preferredSize;\r
+\r
+    }\r
+\r
+    /**\r
+     * Returns the component bounds which is sometimes more convenient than invoking\r
+     * getX/Y/Width/Height. Bounds are relative to parent container.<br>\r
+     * Changing values within the bounds can lead to unpredicted behavior.\r
+     * \r
+     * @see #getX\r
+     * @see #getY\r
+     * @return the component bounds\r
+     */\r
+    protected Rectangle getBounds() {\r
+        return bounds;\r
+    }\r
+\r
+    /**\r
+     * Returns true if this component can receive focus and is enabled\r
+     * \r
+     * @return true if this component can receive focus; otherwise false\r
+     */\r
+    public boolean isFocusable() {\r
+        return focusable && enabled && isVisible();\r
+    }\r
+\r
+    /**\r
+     * A simple setter to determine if this Component can get focused\r
+     * \r
+     * @param focusable indicate whether this component can get focused\r
+     */\r
+    public void setFocusable(boolean focusable) {\r
+        this.focusable = focusable;\r
+        Form p = getComponentForm();\r
+        if (p != null) {\r
+            p.clearFocusVectors();\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Indicates the values within the component have changed and preferred \r
+     * size should be recalculated\r
+     * \r
+     * @param shouldCalcPreferredSize indicate whether this component need to \r
+     * recalculate his preferred size\r
+     */\r
+    protected void setShouldCalcPreferredSize(boolean shouldCalcPreferredSize) {\r
+        if (shouldCalcPreferredSize != this.shouldCalcPreferredSize) {\r
+            this.shouldCalcPreferredSize = shouldCalcPreferredSize;\r
+            if (shouldCalcPreferredSize && getParent() != null) {\r
+                this.shouldCalcPreferredSize = shouldCalcPreferredSize;\r
+                getParent().setShouldCalcPreferredSize(shouldCalcPreferredSize);\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Indicates whether focus should be drawn around the component or whether \r
+     * it will handle its own focus painting\r
+     * \r
+     * @return true if focus should be drawn around the component\r
+     * ; otherwise false\r
+     */\r
+    public boolean isFocusPainted() {\r
+        return focusPainted;\r
+    }\r
+\r
+    /**\r
+     * Indicates whether focus should be drawn around the component or whether \r
+     * it will handle its own focus painting\r
+     * \r
+     * @param focusPainted indicates whether focus should be drawn around the \r
+     * component\r
+     */\r
+    public void setFocusPainted(boolean focusPainted) {\r
+        this.focusPainted = focusPainted;\r
+    }\r
+\r
+    /**\r
+     * Prevents key events from being grabbed for focus traversal. E.g. a list component\r
+     * might use the arrow keys for internal navigation so it will switch this flag to\r
+     * true in order to prevent the focus manager from moving to the next component.\r
+     * \r
+     * @return true if key events are being used for focus traversal\r
+     * ; otherwise false\r
+     */\r
+    public boolean handlesInput() {\r
+        return handlesInput;\r
+    }\r
+\r
+    /**\r
+     * Prevents key events from being grabbed for focus traversal. E.g. a list component\r
+     * might use the arrow keys for internal navigation so it will switch this flag to\r
+     * true in order to prevent the focus manager from moving to the next component.\r
+     * \r
+     * @param handlesInput indicates whether key events can be grabbed for \r
+     * focus traversal\r
+     */\r
+    public void setHandlesInput(boolean handlesInput) {\r
+        this.handlesInput = handlesInput;\r
+    }\r
+\r
+    /**\r
+     * Returns true if the componet has focus\r
+     * \r
+     * @return true if the componet has focus; otherwise false\r
+     * @see #setFocus\r
+     */\r
+    public boolean hasFocus() {\r
+        return focused;\r
+    }\r
+\r
+    /**\r
+     * This flag doesn't really give focus, its a state that determines\r
+     * what colors from the Style should be used when painting the component.\r
+     * Actual focus is determined by the parent form\r
+     * \r
+     * @param focused sets the state that determines what colors from the \r
+     * Style should be used when painting a focused component\r
+     * \r
+     * @see #requestFocus\r
+     */\r
+    public void setFocus(boolean focused) {\r
+        this.focused = focused;\r
+    }\r
+\r
+    /**\r
+     * Returns the Component Form or null if this Component\r
+     * is not added yet to a form\r
+     * \r
+     * @return the Component Form\r
+     */\r
+    public Form getComponentForm() {\r
+        Form retVal = null;\r
+        Component parent = getParent();\r
+        if (parent != null) {\r
+            retVal = parent.getComponentForm();\r
+        }\r
+        return retVal;\r
+    }\r
+\r
+    /**\r
+     * Repaint the given component to the screen\r
+     * \r
+     * @param cmp the given component on the screen\r
+     */\r
+    void repaint(Component cmp) {\r
+        if (isCellRenderer() || cmp.getWidth() <= 0 || cmp.getHeight() <= 0) {\r
+            return;\r
+        }\r
+        // null parent repaint can happen when a component is removed and modified which\r
+        // is common ofr a popup\r
+        Component parent = getParent();\r
+        if (parent != null) {\r
+            parent.repaint(cmp);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Repaint this Component, the repaint call causes a callback of the paint\r
+     * method on the event dispatch thread.\r
+     * \r
+     * @see Display\r
+     */\r
+    public void repaint() {\r
+        dirtyRegion = null;\r
+        repaint(this);\r
+    }\r
+\r
+    public void repaint(int x, int y, int w, int h) {\r
+        if (dirtyRegion == null) {\r
+            dirtyRegion = new Rectangle(x, y, w, h);\r
+        } else {\r
+            Dimension size = dirtyRegion.getSize();\r
+\r
+            int x1 = Math.min(dirtyRegion.getX(), x);\r
+            int y1 = Math.min(dirtyRegion.getY(), y);\r
+\r
+            int x2 = Math.max(x + w, dirtyRegion.getX() + size.getWidth());\r
+            int y2 = Math.max(y + h, dirtyRegion.getY() + size.getHeight());\r
+\r
+            dirtyRegion.setX(x1);\r
+            dirtyRegion.setY(y1);\r
+            size.setWidth(x2 - x1);\r
+            size.setHeight(y2 - y1);\r
+\r
+        }\r
+        repaint(this);\r
+    }\r
+\r
+    /**\r
+     * If this Component is focused, the key pressed event\r
+     * will call this method\r
+     * \r
+     * @param keyCode the key code value to indicate a physical key.\r
+     */\r
+    public void keyPressed(int keyCode) {\r
+    }\r
+\r
+    /**\r
+     * If this Component is focused, the key released event\r
+     * will call this method\r
+     * \r
+     * @param keyCode the key code value to indicate a physical key.\r
+     */\r
+    public void keyReleased(int keyCode) {\r
+    }\r
+\r
+    /**\r
+     * If this Component is focused, the key repeat event\r
+     * will call this method. Calls key pressed/released by default\r
+     * \r
+     * @param keyCode the key code value to indicate a physical key.\r
+     */\r
+    public void keyRepeated(int keyCode) {\r
+        int game = Display.getInstance().getGameAction(keyCode);\r
+        if (game == Display.GAME_DOWN || game == Display.GAME_UP || game == Display.GAME_LEFT || game == Display.GAME_RIGHT) {\r
+            keyPressed(keyCode);\r
+            keyReleased(keyCode);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Allows defining the physics for the animation motion behavior directly \r
+     * by plugging in an alternative motion object\r
+     * \r
+     * @param motion new motion object\r
+     */\r
+    private void setAnimationMotion(Motion motion) {\r
+        animationMotion = motion;\r
+    }\r
+\r
+    /**\r
+     * Allows defining the physics for the animation motion behavior directly \r
+     * by plugging in an alternative motion object\r
+     * \r
+     * @return the component motion object\r
+     */\r
+    private Motion getAnimationMotion() {\r
+        return animationMotion;\r
+    }\r
+\r
+    /**\r
+     * Scroll animation speed in milliseconds allowing a developer to slow down or accelerate\r
+     * the smooth animation mode\r
+     * \r
+     * @return scroll animation speed in milliseconds\r
+     */\r
+    public int getScrollAnimationSpeed() {\r
+        return animationSpeed;\r
+    }\r
+\r
+    /**\r
+     * Scroll animation speed in milliseconds allowing a developer to slow down or accelerate\r
+     * the smooth animation mode\r
+     * \r
+     * @param animationSpeed scroll animation speed in milliseconds\r
+     */\r
+    public void setScrollAnimationSpeed(int animationSpeed) {\r
+        this.animationSpeed = animationSpeed;\r
+    }\r
+\r
+    /**\r
+     * Indicates that scrolling through the component should work as an animation\r
+     * \r
+     * @return whether this component use smooth scrolling\r
+     */\r
+    public boolean isSmoothScrolling() {\r
+        return smoothScrolling;\r
+    }\r
+\r
+    /**\r
+     * Indicates that scrolling through the component should work as an animation\r
+     * \r
+     * @param smoothScrolling indicates if a component uses smooth scrolling\r
+     */\r
+    public void setSmoothScrolling(boolean smoothScrolling) {\r
+        this.smoothScrolling = smoothScrolling;\r
+        Form f = getComponentForm();\r
+        if (f != null) {\r
+            if (smoothScrolling) {\r
+                f.registerAnimated(this);\r
+            } else {\r
+                f.deregisterAnimated(this);\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * If this Component is focused, the pointer dragged event\r
+     * will call this method\r
+     * \r
+     * @param x the pointer x coordinate\r
+     * @param y the pointer y coordinate\r
+     */\r
+    public void pointerDragged(int x, int y) {\r
+        if (isScrollable() && isSmoothScrolling()) {\r
+            int axisValue;\r
+            if (isScrollableY()) {\r
+                axisValue = y;\r
+            } else {\r
+                axisValue = x;\r
+            }\r
+\r
+            if (!dragActivated) {\r
+                dragActivated = true;\r
+                beforeLastScrollY = axisValue;\r
+                lastScrollY = axisValue;\r
+            }\r
+            //save time and locations to create velocity when the \r
+            //pointer is released\r
+            long currentTime = System.currentTimeMillis();\r
+            if (currentTime != lastTime[(pLastDragged + lastTime.length + 1) % lastTime.length]) {\r
+                lastTime[pLastDragged] = System.currentTimeMillis();\r
+                lastDragged[pLastDragged] = axisValue;\r
+                pLastDragged = (++pLastDragged) % lastTime.length;\r
+            }\r
+\r
+            beforeLastScrollY = lastScrollY;\r
+            lastScrollY = axisValue;\r
+\r
+            // we drag inversly to get a feel of grabbing a physical screen\r
+            // and pulling it in the reverse direction of the drag\r
+            if (isScrollableY()) {\r
+                int scroll = getScrollY() + (beforeLastScrollY - axisValue);\r
+                if (scroll >= 0 && scroll < getPreferredH() - getHeight()) {\r
+                    setScrollY(scroll);\r
+                }\r
+            } else {\r
+                int scroll = getScrollX() + (beforeLastScrollY - axisValue);\r
+                if (scroll >= 0 && scroll < getPreferredW() - getWidth()) {\r
+                    setScrollX(scroll);\r
+                }\r
+            }\r
+        } else {\r
+            //try to find a scrollable element until you reach the Form\r
+            Component parent = getParent();\r
+            if (!(parent instanceof Form)) {\r
+                parent.pointerDragged(x, y);\r
+            }\r
+        }\r
+    }\r
+\r
+    private void initScrollMotion() {\r
+        Motion m = Motion.createLinearMotion(initialScrollY, destScrollY, getScrollAnimationSpeed());\r
+        setAnimationMotion(m);\r
+        m.start();\r
+    }\r
+\r
+    /**\r
+     * If this Component is focused, the pointer pressed event\r
+     * will call this method\r
+     * \r
+     * @param x the pointer x coordinate\r
+     * @param y the pointer y coordinate\r
+     */\r
+    public void pointerPressed(int x, int y) {\r
+//        if(draggedMotion != null){\r
+        draggedMotion = null;\r
+//        }\r
+    }\r
+\r
+    /**\r
+     * If this Component is focused, the pointer released event\r
+     * will call this method\r
+     * \r
+     * @param x the pointer x coordinate\r
+     * @param y the pointer y coordinate\r
+     */\r
+    public void pointerReleased(int x, int y) {\r
+        if (dragActivated) {\r
+            long currentTime = System.currentTimeMillis();\r
+\r
+            // replace x and y if this is an x scrolling container\r
+            if (!isScrollableY()) {\r
+                y = x;\r
+            }\r
+\r
+            if (currentTime != lastTime[(pLastDragged + lastTime.length + 1) % lastTime.length]) {\r
+                lastTime[pLastDragged] = System.currentTimeMillis();\r
+                lastDragged[pLastDragged] = y;\r
+                pLastDragged = (++pLastDragged) % lastTime.length;\r
+            }\r
+            float velocity = (float) (lastDragged[pLastDragged] - lastDragged[(pLastDragged + lastDragged.length + 1) % lastDragged.length]) / (lastTime[pLastDragged] - lastTime[(pLastDragged + lastTime.length + 1) % lastTime.length]);\r
+            velocity = velocity * -1;\r
+\r
+            if (isScrollableY()) {\r
+                draggedMotion = Motion.createFrictionMotion(scrollY, velocity, 0.0004f);\r
+            } else {\r
+                draggedMotion = Motion.createFrictionMotion(scrollX, velocity, 0.0004f);\r
+            }\r
+            draggedMotion.start();\r
+            dragActivated = false;\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Returns the Component Style allowing us to manipulate the look of the \r
+     * component\r
+     * \r
+     * @return the component Style object\r
+     */\r
+    public Style getStyle() {\r
+        return style;\r
+    }\r
+\r
+    /**\r
+     * Changes the Component Style by replacing the Component Style with the given Style\r
+     * \r
+     * @param style the component Style object\r
+     */\r
+    public void setStyle(Style style) {\r
+        if (this.style != null) {\r
+            this.style.removeStyleListener(this);\r
+        }\r
+        this.style = style;\r
+        this.style.addStyleListener(this);\r
+        if (this.style.getBgPainter() == null) {\r
+            this.style.setBgPainter(new BGPainter());\r
+        }\r
+        setShouldCalcPreferredSize(true);\r
+        checkAnimation();\r
+    }\r
+\r
+    /**\r
+     * Changes the current component to the focused component, will work only\r
+     * for a component that belongs to a parent form.\r
+     */\r
+    public void requestFocus() {\r
+        Form rootForm = getComponentForm();\r
+        if (rootForm != null) {\r
+            rootForm.requestFocus(this);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Overriden to return a useful value for debugging purposes\r
+     * \r
+     * @return a string representation of this component\r
+     */\r
+    public String toString() {\r
+        String className = getClass().getName();\r
+        className = className.substring(className.lastIndexOf('.') + 1);\r
+        return className + "[" + paramString() + "]";\r
+    }\r
+\r
+    /**\r
+     * Returns a string representing the state of this component. This \r
+     * method is intended to be used only for debugging purposes, and the \r
+     * content and format of the returned string may vary between \r
+     * implementations. The returned string may be empty but may not be \r
+     * <code>null</code>.\r
+     * \r
+     * @return  a string representation of this component's state\r
+     */\r
+    protected String paramString() {\r
+        return "x=" + getX() + " y=" + getY() + " width=" + getWidth() + " height=" + getHeight();\r
+    }\r
+\r
+    /**\r
+     * Makes sure the component is up to date with the current style object\r
+     */\r
+    public void refreshTheme() {\r
+        refreshTheme(getUIID());\r
+    }\r
+\r
+    /**\r
+     * Makes sure the component is up to date with the given UIID\r
+     * \r
+     * @param id The Style Id to update the Component with\r
+     */\r
+    protected void refreshTheme(String id) {\r
+        if (style.isModified()) {\r
+            style.merge(UIManager.getInstance().getComponentStyle(id));\r
+        } else {\r
+            setStyle(UIManager.getInstance().getComponentStyle(id));\r
+        }\r
+        checkAnimation();\r
+        UIManager.getInstance().getLookAndFeel().bind(this);\r
+    }\r
+\r
+    /**\r
+     * Internal method indicating whether we are in the middle of a drag\r
+     * \r
+     * @return true if we are in the middle of a drag; otherwise false\r
+     */\r
+    boolean isDragActivated() {\r
+        return dragActivated;\r
+    }\r
+\r
+    void checkAnimation() {\r
+        Image bgImage = getStyle().getBgImage();\r
+        if (bgImage != null && bgImage.isAnimation()) {\r
+            Form parent = getComponentForm();\r
+\r
+            if (parent != null) {\r
+                parent.registerAnimated(this);\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public boolean animate() {\r
+        Image bgImage = getStyle().getBgImage();\r
+        boolean animateBackground = bgImage != null && bgImage.isAnimation() && ((Animation) bgImage).animate();\r
+        Motion m = getAnimationMotion();\r
+        //preform regular scrolling\r
+        if (m != null && destScrollY != -1 && destScrollY != getScrollY()) {\r
+            // change the variable directly for efficiency both in removing redundant\r
+            // repaints and scroll checks\r
+            scrollY = m.getValue();\r
+\r
+            if (destScrollY == scrollY) {\r
+                destScrollY = -1;\r
+            }\r
+            return true;\r
+        }\r
+\r
+        //preform the dragging motion if exists\r
+        if (draggedMotion != null && !draggedMotion.isFinished()) {\r
+            // change the variable directly for efficiency both in removing redundant\r
+            // repaints and scroll checks\r
+            int dragVal = draggedMotion.getValue();\r
+            if (isScrollableY()) {\r
+                if (dragVal >= 0 && dragVal <= (getPreferredH() - getHeight())) {\r
+                    scrollY = dragVal;\r
+                    return true;\r
+                }\r
+            } else {\r
+                if (dragVal >= 0 && dragVal <= (getPreferredW() - getWidth())) {\r
+                    scrollX = dragVal;\r
+                    return true;\r
+                }\r
+            }\r
+        }\r
+        if (animateBackground && bgImage instanceof StaticAnimation) {\r
+            Rectangle dirty = ((StaticAnimation) bgImage).getDirtyRegion();\r
+            if (dirty != null) {\r
+                dirty.setX(getAbsoluteX());\r
+                dirty.setY(getAbsoluteY() + dirty.getY());\r
+            }\r
+            setDirtyRegion(dirty);\r
+        }\r
+        return animateBackground;\r
+    }\r
+\r
+    /**\r
+     * Indicates that this component is fixed into place and not affected by\r
+     * scrolling of the parent container. This is applicable for components such as\r
+     * menus etc...\r
+     * \r
+     * @return true is this component is fixed into place and not affected by\r
+     * scrolling of the parent container; othewise false\r
+     */\r
+    boolean isFixedPosition() {\r
+        return fixedPosition;\r
+    }\r
+\r
+    /**\r
+     * Indicates that this component is fixed into place and not affected by\r
+     * scrolling of the parent container. This is applicable for components such as\r
+     * menus etc...\r
+     * \r
+     * @param fixedPosition whether this component is fixed into place and not \r
+     * affected by scrolling of the parent container\r
+     */\r
+    void setFixedPosition(boolean fixedPosition) {\r
+        this.fixedPosition = fixedPosition;\r
+    }\r
+\r
+    /**\r
+     * Makes sure the component is visible in the scroll if this container \r
+     * is scrollable\r
+     * \r
+     * @param rect the rectangle that need to be visible\r
+     * @param coordinateSpace the component according to whose coordinates \r
+     * rect is defined. Rect's x/y are relative to that component \r
+     * (they are not absolute).\r
+     */\r
+    protected void scrollRectToVisible(Rectangle rect, Component coordinateSpace) {\r
+        if (isScrollable()) {\r
+\r
+            int scrollPosition = getScrollY();\r
+            int w = getWidth() - getStyle().getPadding(LEFT) - getStyle().getPadding(RIGHT);\r
+            int h = getHeight() - getStyle().getPadding(TOP) - getStyle().getPadding(BOTTOM);\r
+\r
+            Rectangle view = new Rectangle(getScrollX(), getScrollY(), w, h);\r
+\r
+            int relativeX = rect.getX();\r
+            int relativeY = rect.getY();\r
+\r
+            // component needs to be in absolute coordinates...\r
+            Container parent = null;\r
+            if (coordinateSpace != null) {\r
+                parent = coordinateSpace.getParent();\r
+            }\r
+            if (parent == this) {\r
+                if (view.contains(rect)) {\r
+                    return;\r
+                }\r
+            } else {\r
+                while (parent != this) {\r
+                    // mostly a special case for list\r
+                    if (parent == null) {\r
+                        relativeX = rect.getX();\r
+                        relativeY = rect.getY();\r
+                        break;\r
+                    }\r
+                    relativeX += parent.getX();\r
+                    relativeY += parent.getY();\r
+                    parent = parent.getParent();\r
+                }\r
+                if (view.contains(relativeX, relativeY, rect.getSize().getWidth(), rect.getSize().getHeight())) {\r
+                    return;\r
+                }\r
+            }\r
+            if (getScrollX() > relativeX) {\r
+                setScrollX(relativeX);\r
+            }\r
+            if (getScrollY() > relativeY) {\r
+                scrollPosition = relativeY;\r
+            }\r
+            int rightX = relativeX + rect.getSize().getWidth();\r
+            int bottomY = relativeY + rect.getSize().getHeight();\r
+            if (getScrollX() + w < rightX) {\r
+                setScrollX(getScrollX() + (rightX - (getScrollX() + w)));\r
+            } else {\r
+                if (getScrollX() > relativeX) {\r
+                    setScrollX(relativeX);\r
+                }\r
+            }\r
+            if (getScrollY() + h < bottomY) {\r
+                scrollPosition = getScrollY() + (bottomY - (getScrollY() + h));\r
+            } else {\r
+                if (getScrollY() > relativeY) {\r
+                    scrollPosition = relativeY;\r
+                }\r
+            }\r
+            if (isSmoothScrolling()) {\r
+                initialScrollY = getScrollY();\r
+                destScrollY = scrollPosition;\r
+                initScrollMotion();\r
+            } else {\r
+                setScrollY(scrollPosition);\r
+            }\r
+            repaint();\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Indicates whether a border should be painted\r
+     * \r
+     * @param b true would cause the paintBorder method to be invoked false\r
+     * allows us to hide the border of the component without deriving the class\r
+     * @deprecated use getStyle().setBorder() to null to disable borders or install\r
+     * a different border\r
+     */\r
+    public void setBorderPainted(boolean b) {\r
+        if (!b) {\r
+            getStyle().setBorder(null);\r
+        } else {\r
+            getStyle().setBorder(Border.getDefaultBorder());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Indicates whether a border should be painted\r
+     *\r
+     * @return if the border will be painted\r
+     * @deprecated use getStyle().getBorder() != null \r
+     */\r
+    public boolean isBorderPainted() {\r
+        return getStyle().getBorder() != null;\r
+    }\r
+\r
+    /**\r
+     * Draws the component border if such a border exists. The border unlike the content\r
+     * of the component will not be affected by scrolling for a scrollable component.\r
+     * \r
+     * @param g graphics context on which the border is painted\r
+     */\r
+    protected void paintBorder(Graphics g) {\r
+        Border b = getBorder();\r
+        if (b != null) {\r
+            if (isFocusPainted() && hasFocus()) {\r
+                g.setColor(getStyle().getFgSelectionColor());\r
+            } else {\r
+                g.setColor(getStyle().getFgColor());\r
+            }\r
+            b.paint(g, this);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Used as an optimization to mark that this component is currently being\r
+     * used as a cell renderer\r
+     * \r
+     * @param cellRenderer indicate whether this component is currently being\r
+     * used as a cell renderer\r
+     */\r
+    public void setCellRenderer(boolean cellRenderer) {\r
+        this.cellRenderer = cellRenderer;\r
+    }\r
+\r
+    /**\r
+     * Used as an optimization to mark that this component is currently being\r
+     * used as a cell renderer\r
+     * \r
+     * @return rtue is this component is currently being used as a cell renderer\r
+     */\r
+    boolean isCellRenderer() {\r
+        return cellRenderer;\r
+    }\r
+\r
+    /**\r
+     * Indicate whether this component scroll is visible\r
+     * \r
+     * @return true is this component scroll is visible; otherwise false\r
+     */\r
+    public boolean isScrollVisible() {\r
+        return isScrollVisible;\r
+    }\r
+\r
+    /**\r
+     * Set whether this component scroll is visible\r
+     * \r
+     * @param isScrollVisible Indicate whether this component scroll is visible\r
+     */\r
+    public void setIsScrollVisible(boolean isScrollVisible) {\r
+        this.isScrollVisible = isScrollVisible;\r
+    }\r
+\r
+    /**\r
+     * Invoked internally to initialize and bind the component\r
+     */\r
+    void initComponentImpl() {\r
+        if (!initialized) {\r
+            initialized = true;\r
+            UIManager.getInstance().getLookAndFeel().bind(this);\r
+            checkAnimation();\r
+            initComponent();\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Cleansup the initialization flags in the hierachy, notice that paint calls might\r
+     * still occur after deinitilization mostly to perform transitions etc.\r
+     * <p>However interactivity, animation and event tracking code can and probably\r
+     * should be removed by this method.\r
+     */\r
+    void deinitializeImpl() {\r
+        if (isInitialized()) {\r
+            Form f = getComponentForm();\r
+            if (f != null) {\r
+                f.deregisterAnimated(this);\r
+            }\r
+            setInitialized(false);\r
+            setDirtyRegion(null);\r
+            deinitialize();\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Invoked to indicate that the component initialization is being reversed\r
+     * since the component was detached from the container hierarchy. This allows\r
+     * the component to deregister animators and cleanup after itself. This\r
+     * method is the opposite of the initComponent() method.\r
+     */\r
+    protected void deinitialize() {\r
+    }\r
+\r
+    /**\r
+     * Allows subclasses to bind functionality that relies on fully initialized and\r
+     * "ready for action" component state\r
+     */\r
+    protected void initComponent() {\r
+    }\r
+\r
+    /**\r
+     * Indicates if the component is in the initalized state, a component is initialized\r
+     * when its initComponent() method was invoked. The initMethod is invoked before showing the\r
+     * component to the user.\r
+     * \r
+     * @return true if the component is in the initalized state\r
+     */\r
+    protected boolean isInitialized() {\r
+        return initialized;\r
+    }\r
+\r
+    /**\r
+     * Indicates if the component is in the initalized state, a component is initialized\r
+     * when its initComponent() method was invoked. The initMethod is invoked before showing the\r
+     * component to the user.\r
+     * \r
+     * @param initialized Indicates if the component is in the initalized state\r
+     */\r
+    protected void setInitialized(boolean initialized) {\r
+        this.initialized = initialized;\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void styleChanged(String propertyName, Style source) {\r
+        //changing the Font, Padding, Margin may casue the size of the Component to Change\r
+        //therefore we turn on the shouldCalcPreferredSize flag\r
+        if (!shouldCalcPreferredSize &&\r
+                propertyName.equals(Style.FONT) ||\r
+                propertyName.equals(Style.MARGIN) ||\r
+                propertyName.equals(Style.PADDING)) {\r
+            setShouldCalcPreferredSize(true);\r
+            Container parent = getParent();\r
+            if (parent != null) {\r
+                parent.revalidate();\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Allows us to determine which component will receive focus next when travering \r
+     * with the down key\r
+     */\r
+    public Component getNextFocusDown() {\r
+        return nextFocusDown;\r
+    }\r
+\r
+    /**\r
+     * Allows us to determine which component will receive focus next when travering \r
+     * with the down key\r
+     */\r
+    public void setNextFocusDown(Component nextFocusDown) {\r
+        this.nextFocusDown = nextFocusDown;\r
+    }\r
+\r
+    /**\r
+     * Allows us to determine which component will receive focus next when travering \r
+     * with the up key. \r
+     */\r
+    public Component getNextFocusUp() {\r
+        return nextFocusUp;\r
+    }\r
+\r
+    /**\r
+     * Allows us to determine which component will receive focus next when travering \r
+     * with the up key, this method doesn't affect the generl focus beavior.\r
+     */\r
+    public void setNextFocusUp(Component nextFocusUp) {\r
+        this.nextFocusUp = nextFocusUp;\r
+    }\r
+\r
+    /**\r
+     * Allows us to determine which component will receive focus next when travering \r
+     * with the left key. \r
+     */\r
+    public Component getNextFocusLeft() {\r
+        return nextFocusLeft;\r
+    }\r
+\r
+    /**\r
+     * Allows us to determine which component will receive focus next when travering \r
+     * with the left key, this method doesn't affect the generl focus beavior.\r
+     */\r
+    public void setNextFocusLeft(Component nextFocusLeft) {\r
+        this.nextFocusLeft = nextFocusLeft;\r
+    }\r
+\r
+    /**\r
+     * Allows us to determine which component will receive focus next when travering \r
+     * with the right key\r
+     */\r
+    public Component getNextFocusRight() {\r
+        return nextFocusRight;\r
+    }\r
+\r
+    /**\r
+     * Allows us to determine which component will receive focus next when travering \r
+     * with the right key\r
+     */\r
+    public void setNextFocusRight(Component nextFocusRight) {\r
+        this.nextFocusRight = nextFocusRight;\r
+    }\r
+\r
+    /**\r
+     * Indicates whether component is enabled or disabled thus allowing us to prevent\r
+     * a component from receiving input events and indicate so visually\r
+     */\r
+    public boolean isEnabled() {\r
+        return enabled;\r
+    }\r
+\r
+    /**\r
+     * Used to reduce coupling between the TextArea component and display/implementation\r
+     * classes thus reduce the size of the hello world MIDlet\r
+     * \r
+     * @param text text after editing is completed\r
+     */\r
+    void onEditComplete(String text) {\r
+    }\r
+\r
+    /**\r
+     * Indicates whether component is enabled or disabled thus allowing us to prevent\r
+     * a component from receiving input events and indicate so visually\r
+     */\r
+    public void setEnabled(boolean enabled) {\r
+        this.enabled = enabled;\r
+        Form f = getComponentForm();\r
+        if (f != null) {\r
+            f.clearFocusVectors();\r
+            repaint();\r
+        }\r
+    }\r
+\r
+    class BGPainter implements Painter {\r
+\r
+        private Form parent;\r
+        private Form previousTint;\r
+        private boolean ignorCoordinates;\r
+        private Painter painter;\r
+\r
+        public BGPainter() {\r
+        }\r
+\r
+        public BGPainter(Form parent, Painter p) {\r
+            this.painter = p;\r
+            this.parent = parent;\r
+        }\r
+\r
+        public void setIgnorCoordinates(boolean ignorCoordinates) {\r
+            this.ignorCoordinates = ignorCoordinates;\r
+        }\r
+\r
+        public void setPreviousForm(Form previous) {\r
+            previousTint = previous;\r
+        }\r
+\r
+        public void paint(Graphics g, Rectangle rect) {\r
+            if (painter != null) {\r
+                if (previousTint != null) {\r
+                    previousTint.paint(g);\r
+                }\r
+                Dimension d = rect.getSize();\r
+                int width = d.getWidth();\r
+                int height = d.getHeight();\r
+                int x = rect.getX();\r
+                int y = rect.getY();\r
+\r
+                if (ignorCoordinates) {\r
+                    // this is a special case for dialogs since they are "pushed" to\r
+                    // a position in the screen and can't draw behind their title\r
+                    // we need to still "pretend" that they own the screen... \r
+                    x = 0;\r
+                    y = 0;\r
+                    width = parent.getWidth();\r
+                    height = parent.getHeight();\r
+                    int transY = g.getTranslateY();\r
+                    g.translate(0, -transY);\r
+\r
+                    painter.paint(g, new Rectangle(x, y, width, height));\r
+                    g.translate(0, transY);\r
+                } else {\r
+                    painter.paint(g, new Rectangle(x, y, width, height));\r
+                }\r
+            } else {\r
+                Style s = getStyle();\r
+                int x = rect.getX();\r
+                int y = rect.getY();\r
+                int width = rect.getSize().getWidth();\r
+                int height = rect.getSize().getHeight();\r
+                if (width <= 0 || height <= 0) {\r
+                    return;\r
+                }\r
+                Image bgImage = s.getBgImage();\r
+                if (bgImage == null) {\r
+                    if (hasFocus() && isFocusPainted()) {\r
+                        g.setColor(s.getBgSelectionColor());\r
+                        g.fillRect(x, y, width, height, s.getBgTransparency());\r
+                    } else {\r
+                        g.setColor(s.getBgColor());\r
+                        g.fillRect(x, y, width, height, s.getBgTransparency());\r
+                    }\r
+                } else {\r
+                    if (getStyle().isScaleImage()) {\r
+                        if (bgImage.getWidth() != width || bgImage.getHeight() != height) {\r
+                            bgImage = bgImage.scaled(width, height);\r
+                            s.setBgImage(bgImage, true);\r
+                        }\r
+                    } else {\r
+                        int iW = bgImage.getWidth();\r
+                        int iH = bgImage.getHeight();\r
+                        for (int xPos = 0; xPos < width; xPos += iW) {\r
+                            for (int yPos = 0; yPos < height; yPos += iH) {\r
+                                g.drawImage(s.getBgImage(), x + xPos, y + yPos);\r
+                            }\r
+                        }\r
+                        return;\r
+                    }\r
+                    g.drawImage(s.getBgImage(), x, y);\r
+                }\r
+            }\r
+        }\r
+    }\r
+}\r
diff --git a/core/java/com/sun/lwuit/Container.java b/core/java/com/sun/lwuit/Container.java
new file mode 100644 (file)
index 0000000..1e5039c
--- /dev/null
@@ -0,0 +1,758 @@
+/*\r
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.\r
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\r
+ *\r
+ * This code is free software; you can redistribute it and/or modify it\r
+ * under the terms of the GNU General Public License version 2 only, as\r
+ * published by the Free Software Foundation.  Sun designates this\r
+ * particular file as subject to the "Classpath" exception as provided\r
+ * by Sun in the LICENSE file that accompanied this code.\r
+ *\r
+ * This code is distributed in the hope that it will be useful, but WITHOUT\r
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
+ * version 2 for more details (a copy is included in the LICENSE file that\r
+ * accompanied this code).\r
+ *\r
+ * You should have received a copy of the GNU General Public License version\r
+ * 2 along with this work; if not, write to the Free Software Foundation,\r
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,\r
+ * CA 95054 USA or visit www.sun.com if you need additional information or\r
+ * have any questions.\r
+ */\r
+package com.sun.lwuit;\r
+\r
+import com.sun.lwuit.animations.Animation;\r
+import com.sun.lwuit.animations.Transition;\r
+import com.sun.lwuit.layouts.BorderLayout;\r
+import com.sun.lwuit.layouts.FlowLayout;\r
+import com.sun.lwuit.layouts.Layout;\r
+import com.sun.lwuit.plaf.UIManager;\r
+import java.util.Enumeration;\r
+import com.sun.lwuit.geom.Dimension;\r
+import com.sun.lwuit.geom.Rectangle;\r
+import java.util.Vector;\r
+\r
+/**\r
+ * A composite pattern with {@link Component}, allows nesting and arranging multiple\r
+ * components using a pluggable layout manager architecture. Containers can be nested\r
+ * one within the other to form elaborate UI's.\r
+ *\r
+ * @see com.sun.lwuit.layouts\r
+ * @see Component\r
+ * @author Chen Fishbein\r
+ */\r
+public class Container extends Component {\r
+\r
+    private Layout layout;\r
+    private java.util.Vector components = new java.util.Vector();\r
+    private boolean shouldLayout = true;\r
+    private boolean scrollableX;\r
+    private boolean scrollableY;\r
+\r
+    /**\r
+     * Constructs a new Container with a new layout manager.\r
+     * \r
+     * @param layout the specified layout manager\r
+     */\r
+    public Container(Layout layout) {\r
+        super();\r
+        this.layout = layout;\r
+        setFocusable(false);\r
+    }\r
+\r
+    /** \r
+     * Constructs a new Container, with a {@link FlowLayout}. \r
+     */\r
+    public Container() {\r
+        this(new FlowLayout());\r
+    }\r
+\r
+    /**\r
+     * Returns the layout manager responsible for arranging this container\r
+     * \r
+     * @return the container layout manager\r
+     */\r
+    public Layout getLayout() {\r
+        return layout;\r
+    }\r
+\r
+    /**\r
+     * Sets the layout manager responsible for arranging this container\r
+     * \r
+     * @param layout the specified layout manager\r
+     */\r
+    public void setLayout(Layout layout) {\r
+        this.layout = layout;\r
+    }\r
+\r
+    /**\r
+     * Same as setShouldCalcPreferredSize(true) but made accessible for \r
+     * layout managers\r
+     */\r
+    public void invalidate() {\r
+        setShouldCalcPreferredSize(true);\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    protected void setShouldCalcPreferredSize(boolean shouldCalcPreferredSize) {\r
+        super.setShouldCalcPreferredSize(shouldCalcPreferredSize);\r
+        shouldLayout = shouldCalcPreferredSize;\r
+        Enumeration enums = components.elements();\r
+        if (shouldLayout) {\r
+            while (enums.hasMoreElements()) {\r
+                Component cmp = (Component) enums.nextElement();\r
+                if (cmp instanceof Container) {\r
+                    ((Container) cmp).setShouldCalcPreferredSize(shouldCalcPreferredSize);\r
+                }\r
+            }\r
+        }\r
+        Form f = getComponentForm();\r
+        if (f != null) {\r
+            f.clearFocusVectors();\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Returns the width for layout manager purposes, this takes scrolling\r
+     * into consideration unlike the getWidth method.\r
+     * \r
+     * @return the layout width\r
+     */\r
+    public int getLayoutWidth() {\r
+        if (isScrollableX()) {\r
+            int scrollH = UIManager.getInstance().getLookAndFeel().getHorizontalScrollHeight();\r
+            return Math.max(getWidth() + scrollH, getPreferredW() + scrollH);\r
+        } else {\r
+            Container parent = getScrollableParent();\r
+            if (parent != null && parent.isScrollableX()) {\r
+                return Math.max(getWidth(), getPreferredW());\r
+            }\r
+            int width = getWidth();\r
+            if (width <= 0) {\r
+                return getPreferredW();\r
+            }\r
+            return width;\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Returns the height for layout manager purposes, this takes scrolling\r
+     * into consideration unlike the getWidth method.\r
+     * \r
+     * @return the layout height\r
+     */\r
+    public int getLayoutHeight() {\r
+        if (isScrollableY()) {\r
+            int scrollW = UIManager.getInstance().getLookAndFeel().getVerticalScrollWidth();\r
+            return Math.max(getHeight() + scrollW, getPreferredH() + scrollW);\r
+        } else {\r
+            Container parent = getScrollableParent();\r
+            if (parent != null && parent.isScrollableY()) {\r
+                return Math.max(getHeight(), getPreferredH());\r
+            }\r
+            int height = getHeight();\r
+            if (height <= 1) {\r
+                return getPreferredH();\r
+            }\r
+            return height;\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Returns a parent container that is scrollable or null if no parent is \r
+     * scrollable.\r
+     * \r
+     * @return a parent container that is scrollable or null if no parent is \r
+     * scrollable.\r
+     */\r
+    private Container getScrollableParent() {\r
+        Container parent = getParent();\r
+        while (parent != null) {\r
+            if (parent.isScrollable()) {\r
+                return parent;\r
+            }\r
+            parent = parent.getParent();\r
+        }\r
+        return null;\r
+    }\r
+\r
+    /**\r
+     * Adds a Component to the Container\r
+     * \r
+     * @param cmp the component to be added\r
+     */\r
+    public void addComponent(Component cmp) {\r
+        // helper check for a common mistake...\r
+        if (layout instanceof BorderLayout) {\r
+            throw new IllegalArgumentException("Cannot add component to BorderLayout Container without constraint parameter");\r
+        }\r
+\r
+        insertComponentAt(components.size(), cmp);\r
+    }\r
+\r
+    /**\r
+     * Adds a Component to the Container\r
+     * \r
+     * @param constraints this method is useful when the Layout requires a constraint\r
+     * such as the BorderLayout.\r
+     * In this case you need to specify an additional data when you add a Component,\r
+     * such as "CENTER", "NORTH"...\r
+     *\r
+     * @param cmp component to add\r
+     */\r
+    public void addComponent(Object constraints, Component cmp) {\r
+        layout.addLayoutComponent(constraints, cmp, this);\r
+        insertComponentAt(components.size(), cmp);\r
+    }\r
+\r
+    private void insertComponentAt(int index, Component cmp) {\r
+        if (cmp.getParent() != null) {\r
+            throw new IllegalArgumentException("Component is already contained in Container: " + cmp.getParent());\r
+        }\r
+        if (cmp instanceof Form) {\r
+            throw new IllegalArgumentException("A form cannot be added to a container");\r
+        }\r
+        cmp.setParent(this);\r
+        components.insertElementAt(cmp, index);\r
+        setShouldCalcPreferredSize(true);\r
+        if (isInitialized()) {\r
+            cmp.initComponentImpl();\r
+        }\r
+        Form f = getComponentForm();\r
+        if (f != null) {\r
+            f.clearFocusVectors();\r
+        }\r
+    //repaint();\r
+    }\r
+\r
+    /**\r
+     * This method adds the Component at a specific index location in the Conatiner\r
+     * Components array.\r
+     * \r
+     * @param index location to insert the Component\r
+     * @param cmp the Component to add\r
+     * @throws ArrayIndexOutOfBoundsException if index is out of bounds\r
+     * @throws IllegalArgumentException if Component is already contained or\r
+     * the cmp is a Form Component\r
+     */\r
+    public void addComponent(int index, Component cmp) {\r
+        insertComponentAt(index, cmp);\r
+    }\r
+\r
+    /**\r
+     * This method replaces the current Component with the next Component.\r
+     * Current Component must be contained in this Container.\r
+     * This method return immediately.\r
+     * \r
+     * @param current a Component to remove from the Container\r
+     * @param next a Component that replaces the current Component\r
+     * @param t a Transition between the add and removal of the Components\r
+     *  a Transition can be null\r
+     */\r
+    public void replace(final Component current, final Component next, final Transition t) {\r
+        if (!contains(current)) {\r
+            throw new IllegalArgumentException("Component " + current + " is not contained in this Container");\r
+        }\r
+        if (t == null) {\r
+            replace(current, next);\r
+            return;\r
+        }\r
+\r
+        next.setX(current.getX());\r
+        next.setY(current.getY());\r
+        next.setWidth(current.getWidth());\r
+        next.setHeight(current.getHeight());\r
+        next.setParent(this);\r
+        if (next instanceof Container) {\r
+            ((Container) next).layoutContainer();\r
+        }\r
+\r
+        Animation anim = new Anim(this, current, next, t);\r
+\r
+        // block events as long as the transition is animating\r
+        Display.getInstance().blockEvents(true);\r
+\r
+        // register the transition animation\r
+        getComponentForm().registerAnimated(anim);\r
+    }\r
+\r
+    void replace(final Component current, final Component next) {\r
+        int index = components.indexOf(current);\r
+        boolean currentFocused = false;\r
+        if (current.getComponentForm() != null && current.getComponentForm().getFocused() == current) {\r
+            currentFocused = true;\r
+        }\r
+        if (layout instanceof BorderLayout) {\r
+            Object constraint = layout.getComponentConstraint(current);\r
+            removeComponent(current);\r
+            layout.addLayoutComponent(constraint, next, Container.this);\r
+        } else {\r
+            removeComponent(current);\r
+        }\r
+        next.setParent(null);\r
+        if (index < 0) {\r
+            index = 0;\r
+        }\r
+        insertComponentAt(index, next);\r
+        if (currentFocused && next.isFocusable()) {\r
+            next.requestFocus();\r
+        }\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    void initComponentImpl() {\r
+        if (!isInitialized()) {\r
+            if (isSmoothScrolling()) {\r
+                getComponentForm().registerAnimated(this);\r
+            }\r
+            super.initComponentImpl();\r
+        }\r
+        Enumeration e = components.elements();\r
+        while (e.hasMoreElements()) {\r
+            ((Component) e.nextElement()).initComponentImpl();\r
+        }\r
+    }\r
+\r
+    /**\r
+     * removes a Component from the Container\r
+     * \r
+     * @param cmp the removed component\r
+     */\r
+    public void removeComponent(Component cmp) {\r
+        Form parentForm = cmp.getComponentForm();\r
+        layout.removeLayoutComponent(cmp);\r
+        cmp.deinitializeImpl();\r
+        components.removeElement(cmp);\r
+        cmp.setParent(null);\r
+        cmp.setShouldCalcPreferredSize(true);\r
+        if (parentForm != null) {\r
+            if (parentForm.getFocused() == cmp || cmp instanceof Container && ((Container) cmp).contains(parentForm.getFocused())) {\r
+                parentForm.setFocused(null);\r
+            }\r
+            parentForm.clearFocusVectors();\r
+            if (cmp.isSmoothScrolling()) {\r
+                parentForm.deregisterAnimated(cmp);\r
+            }\r
+        }\r
+        setShouldCalcPreferredSize(true);\r
+    }\r
+\r
+    /**\r
+     * Cleansup the initialization flags in the hierachy\r
+     */\r
+    void deinitializeImpl() {\r
+        super.deinitializeImpl();\r
+        int size = components.size();\r
+        for (int iter = 0; iter < size; iter++) {\r
+            ((Component) components.elementAt(iter)).deinitializeImpl();\r
+        }\r
+    }\r
+\r
+    /**\r
+     * remove all Components from container\r
+     */\r
+    public void removeAll() {\r
+        Form parentForm = getComponentForm();\r
+        if (parentForm != null) {\r
+            Component focus = parentForm.getFocused();\r
+            if (focus != null && contains(focus)) {\r
+                parentForm.setFocused(null);\r
+            }\r
+        }\r
+        Object[] arr = new Object[components.size()];\r
+        components.copyInto(arr);\r
+\r
+        for (int i = 0; i < arr.length; i++) {\r
+            removeComponent((Component) arr[i]);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Re-layout the container, this is useful when we modify the container hierarchy and\r
+     * need to redo the layout\r
+     */\r
+    public void revalidate() {\r
+        setShouldCalcPreferredSize(true);\r
+        Form root = getComponentForm();\r
+        if (root != null) {\r
+            root.layoutContainer();\r
+            root.repaint();\r
+        } else {\r
+            layoutContainer();\r
+            repaint();\r
+        }\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void paint(Graphics g) {\r
+        layoutContainer();\r
+        g.translate(getX(), getY());\r
+        Enumeration enums = components.elements();\r
+        while (enums.hasMoreElements()) {\r
+            Component cmp = (Component) enums.nextElement();\r
+            cmp.paintInternal(g);\r
+        }\r
+\r
+        g.translate(-getX(), -getY());\r
+    }\r
+\r
+    void paintIntersecting(Graphics g, Component cmp, Rectangle bounds, boolean above) {\r
+        \r
+        if (layout.isOverlapSupported() && components.contains(cmp)) {\r
+            int indexOfComponent = components.indexOf(cmp);\r
+            int startIndex;\r
+            int endIndex;\r
+            if (above) {\r
+                startIndex = indexOfComponent + 1;\r
+                endIndex = components.size();\r
+            } else {\r
+                startIndex = 0;\r
+                endIndex = indexOfComponent;\r
+            }\r
+\r
+            for (int i = startIndex; i < endIndex; i++) {\r
+                Component cmp2 = (Component) components.elementAt(i);\r
+                Rectangle rect = new Rectangle(cmp2.getBounds());\r
+                rect.setX(cmp2.getAbsoluteX());\r
+                rect.setY(cmp2.getAbsoluteY());\r
+\r
+                if (rect.intersects(bounds)) {\r
+                    cmp2.paintInternal(g, false);\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Performs the layout of the container if a layout is necessary\r
+     */\r
+    public void layoutContainer() {\r
+        //will compute the container + components and will layout the components.\r
+        if (shouldLayout) {\r
+            shouldLayout = false;\r
+            doLayout();\r
+        }\r
+\r
+    }\r
+\r
+    /**\r
+     * Lays out the container\r
+     */\r
+    void doLayout() {\r
+        layout.layoutContainer(this);\r
+        int count = getComponentCount();\r
+        for (int i = 0; i <\r
+                count; i++) {\r
+            Component c = getComponentAt(i);\r
+            if (c instanceof Container) {\r
+                ((Container) c).doLayout();\r
+            }\r
+\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Returns the number of components\r
+     * \r
+     * @return the Component count\r
+     */\r
+    public int getComponentCount() {\r
+        return components.size();\r
+    }\r
+\r
+    /**\r
+     * Returns the Component at a given index\r
+     * \r
+     * @param index of the Component you wish to get\r
+     * @return a Component\r
+     * @throws ArrayIndexOutOfBoundsException if an invalid index was given.\r
+     */\r
+    public Component getComponentAt(\r
+            int index) {\r
+        return (Component) components.elementAt(index);\r
+    }\r
+\r
+    /**\r
+     * Returns the Component index in the Container\r
+     * \r
+     * @param cmp the component to search for\r
+     * @return the Component index in the Container or -1 if not found\r
+     */\r
+    public int getComponentIndex(Component cmp) {\r
+        int count = getComponentCount();\r
+        for (int i = 0; i <\r
+                count; i++) {\r
+            Component c = getComponentAt(i);\r
+            if (c.equals(cmp)) {\r
+                return i;\r
+            }\r
+        }\r
+        return -1;\r
+    }\r
+\r
+    /**\r
+     * Returns true if the given component is within the hierarchy of this container\r
+     *\r
+     * @param cmp a Component to check\r
+     * @return true if this Component contains in this Container\r
+     */\r
+    public boolean contains(Component cmp) {\r
+        boolean found = false;\r
+        int count = getComponentCount();\r
+        for (int i = 0; i < count; i++) {\r
+            Component c = getComponentAt(i);\r
+            if (c.equals(cmp)) {\r
+                return true;\r
+            }\r
+\r
+            if (c instanceof Container) {\r
+                found = ((Container) c).contains(cmp);\r
+                if (found) {\r
+                    return true;\r
+                }\r
+\r
+            }\r
+        }\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Makes sure the component is visible in the scroll if this container is \r
+     * scrollable\r
+     * \r
+     * @param c the component that will be scrolling for visibility\r
+     */\r
+    protected void scrollComponentToVisible(Component c) {\r
+        if (isScrollable()) {\r
+            if (c != null) {\r
+                if (c.getParent() != null) {\r
+                    // special case for the first component to allow the user to scroll all the \r
+                    // way to the top\r
+                    Form f = getComponentForm();\r
+                    if (f != null && f.getFocusPosition(c) == 0) {\r
+                        scrollRectToVisible(new Rectangle(0, 0, c.getX() + c.getWidth(), c.getY() + c.getHeight()), c);\r
+                        return;\r
+                    }\r
+                }\r
+                scrollRectToVisible(c.getBounds(), c);\r
+            }\r
+        }\r
+\r
+    }\r
+\r
+    /**\r
+     * Returns a Component that exists in the given x, y coordinates by traversing\r
+     * component objects and invoking contains\r
+     * \r
+     * @param x absolute screen location\r
+     * @param y absolute screen location\r
+     * @return a Component if found, null otherwise\r
+     * @see Component#contains\r
+     */\r
+    public Component getComponentAt(int x, int y) {\r
+        int count = getComponentCount();\r
+        for (int i = count - 1; i >= 0; i--) {\r
+            Component cmp = getComponentAt(i);\r
+            if (cmp.contains(x, y)) {\r
+                if (cmp instanceof Container) {\r
+                    return ((Container) cmp).getComponentAt(x, y);\r
+                }\r
+                return cmp;\r
+            }\r
+\r
+        }\r
+        return null;\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void pointerPressed(int x, int y) {\r
+        if (!isDragActivated()) {\r
+            Component cmp = getComponentAt(x, y);\r
+            if (cmp != null) {\r
+                cmp.pointerPressed(x, y);\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void pointerReleased(int x, int y) {\r
+        if (isDragActivated()) {\r
+            super.pointerReleased(x, y);\r
+            return;\r
+        }\r
+        Component cmp = getComponentAt(x, y);\r
+        if (cmp != null) {\r
+            cmp.pointerReleased(x, y);\r
+        }\r
+\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    protected Dimension calcPreferredSize() {\r
+        Dimension d = layout.getPreferredSize(this);\r
+        return d;\r
+    }\r
+\r
+//    /**\r
+//     * @inheritDoc\r
+//     */\r
+//    public boolean isFocusable() {\r
+//        return false;\r
+//    }\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    protected String paramString() {\r
+        String className = layout.getClass().getName();\r
+        String layoutStr = className.substring(className.lastIndexOf('.') + 1);\r
+        return super.paramString() + ", layout = " + layoutStr +\r
+                ", scrollableX = " + scrollableX +\r
+                ", scrollableY = " + scrollableY +\r
+                ", components = " + getComponentsNames();\r
+    }\r
+\r
+    /**\r
+     * Return the conatainer components objects as list of Strings\r
+     * @return the conatainer components objects as list of Strings\r
+     */\r
+    private String getComponentsNames() {\r
+        String ret = "[";\r
+        Enumeration enums = components.elements();\r
+        while (enums.hasMoreElements()) {\r
+            String className = enums.nextElement().getClass().getName();\r
+            ret += className.substring(className.lastIndexOf('.') + 1) + ", ";\r
+        }\r
+\r
+        return ret.substring(0, ret.length() - 2) + "]";\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void refreshTheme() {\r
+        super.refreshTheme();\r
+        Enumeration enums = components.elements();\r
+        while (enums.hasMoreElements()) {\r
+            Component cmp = (Component) enums.nextElement();\r
+            cmp.refreshTheme();\r
+        }\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public boolean isScrollableX() {\r
+        return scrollableX && getPreferredW() > getWidth();\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public boolean isScrollableY() {\r
+        return scrollableY && getPreferredH() > getHeight();\r
+    }\r
+\r
+    /**\r
+     * Sets whether the component should/could scroll on the X axis\r
+     * \r
+     * @param scrollableX whether the component should/could scroll on the X axis\r
+     */\r
+    public void setScrollableX(boolean scrollableX) {\r
+        this.scrollableX = scrollableX;\r
+    }\r
+\r
+    /**\r
+     * Sets whether the component should/could scroll on the Y axis\r
+     * \r
+     * @param scrollableY whether the component should/could scroll on the Y axis\r
+     */\r
+    public void setScrollableY(boolean scrollableY) {\r
+        this.scrollableY = scrollableY;\r
+    }\r
+\r
+    /**\r
+     * The equivalent of calling both setScrollableY and setScrollableX\r
+     * \r
+     * @param scrollable whether the component should/could scroll on the \r
+     * X and Y axis\r
+     */\r
+    public void setScrollable(boolean scrollable) {\r
+        setScrollableX(scrollable);\r
+        setScrollableY(scrollable);\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void setCellRenderer(boolean cellRenderer) {\r
+        if (isCellRenderer() != cellRenderer) {\r
+            super.setCellRenderer(cellRenderer);\r
+            int size = getComponentCount();\r
+            for (int iter = 0; iter <\r
+                    size; iter++) {\r
+                getComponentAt(iter).setCellRenderer(cellRenderer);\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    protected String getUIID() {\r
+        return "Container";\r
+    }\r
+}\r
+\r
+class Anim implements Animation {\r
+\r
+    private Transition t;\r
+    private Component current;\r
+    private Component next;\r
+    private boolean started = false;\r
+    private Container thisContainer;\r
+\r
+    public Anim(Container thisContainer, Component current, Component next, Transition t) {\r
+        this.t = t;\r
+        this.next = next;\r
+        this.current = current;\r
+        this.thisContainer = thisContainer;\r
+    }\r
+\r
+    public boolean animate() {\r
+        if (!started) {\r
+            t.init(current, next);\r
+            t.initTransition();\r
+            started = true;\r
+        }\r
+        boolean notFinished = t.animate();\r
+        if (!notFinished) {\r
+            next.setParent(null);\r
+            thisContainer.replace(current, next);\r
+            //release the events blocking\r
+            Display.getInstance().blockEvents(false);\r
+            t.cleanup();\r
+            thisContainer.getComponentForm().deregisterAnimated(this);\r
+        }\r
+        return notFinished;\r
+    }\r
+\r
+    public void paint(Graphics g) {\r
+        t.paint(g);\r
+    }\r
+}\r
+\r
diff --git a/core/java/com/sun/lwuit/CustomFont.java b/core/java/com/sun/lwuit/CustomFont.java
new file mode 100644 (file)
index 0000000..3954ae7
--- /dev/null
@@ -0,0 +1,260 @@
+/*\r
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.\r
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\r
+ *\r
+ * This code is free software; you can redistribute it and/or modify it\r
+ * under the terms of the GNU General Public License version 2 only, as\r
+ * published by the Free Software Foundation.  Sun designates this\r
+ * particular file as subject to the "Classpath" exception as provided\r
+ * by Sun in the LICENSE file that accompanied this code.\r
+ *\r
+ * This code is distributed in the hope that it will be useful, but WITHOUT\r
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
+ * version 2 for more details (a copy is included in the LICENSE file that\r
+ * accompanied this code).\r
+ *\r
+ * You should have received a copy of the GNU General Public License version\r
+ * 2 along with this work; if not, write to the Free Software Foundation,\r
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,\r
+ * CA 95054 USA or visit www.sun.com if you need additional information or\r
+ * have any questions.\r
+ */\r
+package com.sun.lwuit;\r
+\r
+\r
+\r
+/**\r
+ * Implements a bitmap font that uses an image and sets of offsets to draw a font\r
+ * with a given character set.\r
+ *\r
+ * @author Shai Almog\r
+ */\r
+class CustomFont extends Font {\r
+    /**\r
+     * Keep two colors in cache by default to allow faster selection colors\r
+     */\r
+    private static final int COLOR_CACHE_SIZE = 2;\r
+    \r
+    /**\r
+     * The selected color values\r
+     */\r
+    private int[] selectedColors;\r
+    \r
+    /**\r
+     * The selected color values\r
+     */\r
+    private Image[] cachedImages;\r
+\r
+    private String charsets;\r
+    private int color;\r
+    \r
+    // package protected for the resource editor\r
+    Image cache;\r
+    \r
+    /**\r
+     * The offset in which to cut the character from the bitmap\r
+     */\r
+    int[] cutOffsets;\r
+\r
+    /**\r
+     * The width of the character when drawing... this should not be confused with\r
+     * the number of cutOffset[o + 1] - cutOffset[o]. They are completely different\r
+     * since a character can be "wider" and "seep" into the next region. This is\r
+     * especially true with italic characters all of which "lean" outside of their \r
+     * bounds.\r
+     */\r
+    int[] charWidth;\r
+\r
+    private int imageWidth;\r
+    private int imageHeight;\r
+    private int[] imageArray;\r
+    \r
+    \r
+    /**\r
+     * Creates a bitmap font with the given arguments\r
+     * \r
+     * @param bitmap a transparency map in red and black that indicates the characters\r
+     * @param cutOffsets character offsets matching the bitmap pixels and characters in the font \r
+     * @param charWidth The width of the character when drawing... this should not be confused with\r
+     *      the number of cutOffset[o + 1] - cutOffset[o]. They are completely different\r
+     *      since a character can be "wider" and "seep" into the next region. This is\r
+     *      especially true with italic characters all of which "lean" outside of their \r
+     *      bounds.\r
+     * @param charsets the set of characters in the font\r
+     * @return a font object to draw bitmap fonts\r
+     */\r
+    public CustomFont(Image bitmap, int[] cutOffsets, int[] charWidth, String charsets) {\r
+        this.cutOffsets = cutOffsets;\r
+        this.charWidth = charWidth;\r
+        this.charsets = charsets;\r
+        imageWidth = bitmap.getWidth();\r
+        imageHeight = bitmap.getHeight();\r
+        imageArray = new int[imageWidth * imageHeight];\r
+        \r
+        // default to black colored font\r
+        bitmap.getRGB(imageArray, 0, imageWidth, 0, 0, imageWidth, imageHeight);\r
+        for(int iter = 0 ; iter < imageArray.length ; iter++) {\r
+            // extract the red component from the font image\r
+            // shift the alpha 8 bits to the left\r
+            // apply the alpha to the image\r
+            imageArray[iter] = ((imageArray[iter] & 0xff0000) << 8);\r
+        }\r
+        cache = Image.createImage(imageArray, imageWidth, imageHeight);\r
+        if(!Display.getInstance().isLightMode()) {\r
+            selectedColors = new int[COLOR_CACHE_SIZE];\r
+            cachedImages = new Image[COLOR_CACHE_SIZE];\r
+            for(int iter = 0 ; iter < selectedColors.length ; iter++) {\r
+                selectedColors[iter] = color;\r
+                cachedImages[iter] = cache;\r
+            }\r
+        } else {\r
+            imageArray = null;\r
+        }\r
+    }\r
+    \r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public int charWidth(char ch) {\r
+        int i = charsets.indexOf(ch);\r
+        if(i < 0) {\r
+            return 0;\r
+        }\r
+        return charWidth[i];\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public int getHeight() {\r
+        return imageHeight;\r
+    }\r
+\r
+    private boolean checkCacheCurrentColor(int newColor) {\r
+        if(Display.getInstance().isLightMode()) {\r
+            return false;\r
+        }\r
+        for(int iter = 0 ; iter < selectedColors.length ; iter++) {\r
+            if(selectedColors[iter] == newColor) {\r
+                selectedColors[iter] = color;\r
+                Image newCache = cachedImages[iter];\r
+                color = newColor;\r
+                cachedImages[iter] = cache;\r
+                cache = newCache;\r
+                return true;\r
+            }\r
+        }\r
+        \r
+        // shift the cache and stick the current value at 0\r
+        for(int iter = selectedColors.length - 1; iter > 0; iter--) {\r
+            selectedColors[iter] = selectedColors[iter - 1];\r
+            cachedImages[iter] = cachedImages[iter - 1];\r
+        }\r
+        selectedColors[0] = color;\r
+        cachedImages[0] = cache;\r
+        \r
+        return false;\r
+    }\r
+    \r
+    private void initColor(Graphics g) {\r
+        int newColor = g.getColor();\r
+        if(newColor != color && !checkCacheCurrentColor(newColor)) {\r
+            color = newColor & 0xffffff;\r
+            if(imageArray == null) {\r
+                imageArray = cache.getRGB();\r
+            }\r
+            for(int iter = 0 ; iter < imageArray.length ; iter++) {\r
+                // extract the red component from the font image\r
+                // shift the alpha 8 bits to the left\r
+                // apply the alpha to the image\r
+                imageArray[iter] = color | (imageArray[iter] & 0xff000000);\r
+            }\r
+            cache = Image.createImage(imageArray, imageWidth, imageHeight);\r
+            if(Display.getInstance().isLightMode()) {\r
+                imageArray = null;\r
+            }\r
+        }\r
+    }\r
+    \r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    void drawChar(Graphics g, char character, int x, int y) {\r
+        int clipX = g.getClipX();\r
+        int clipY = g.getClipY();\r
+        int clipWidth = g.getClipWidth();\r
+        int clipHeight = g.getClipHeight();\r
+\r
+        int i = charsets.indexOf(character);\r
+        if(i > -1) {\r
+            initColor(g);\r
+            \r
+            // draw region is flaky on some devices, use setClip instead\r
+            g.clipRect(x, y, charWidth[i], imageHeight);\r
+            g.drawImage(cache, x - cutOffsets[i], y);\r
+            //g.drawRegion(cache, cutOffsets[i], 0, charWidth[i], imageHeight, x, y);\r
+        }\r
+\r
+        // restore the clip\r
+        g.setClip(clipX, clipY, clipWidth, clipHeight);\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void addContrast(byte value) {\r
+        for(int iter = 0 ; iter < imageArray.length ; iter++) {\r
+            int alpha = (imageArray[iter] >> 24) & 0xff;\r
+            if(alpha != 0) {\r
+                alpha = Math.min(alpha + value, 255);\r
+                imageArray[iter] = ((alpha << 24) & 0xff000000) | color;\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Override this frequently used method for a slight performance boost...\r
+     * \r
+     * @param g the component graphics\r
+     * @param data the chars to draw\r
+     * @param offset the offset to draw the chars \r
+     * @param length the length of chars \r
+     * @param x the x coordinate to draw the chars\r
+     * @param y the y coordinate to draw the chars\r
+     */\r
+    void drawChars(Graphics g, char[] data, int offset, int length, int x, int y) {\r
+        initColor(g);\r
+        int clipX = g.getClipX();\r
+        int clipY = g.getClipY();\r
+        int clipWidth = g.getClipWidth();\r
+        int clipHeight = g.getClipHeight();\r
+\r
+        if(clipY <= y + getHeight() && clipY + clipHeight >= y) {\r
+            char c;\r
+            for ( int i = 0; i < length; i++ ) {\r
+                c = data[offset+i];\r
+                int position = charsets.indexOf(c);\r
+                if(position < 0) {\r
+                    continue;\r
+                }\r
+                // draw region is flaky on some devices, use setClip instead\r
+                g.clipRect(x, y, charWidth[position], imageHeight);\r
+                if(g.getClipWidth() > 0 && g.getClipHeight() > 0) {\r
+                    g.drawImage(cache, x - cutOffsets[position], y);\r
+                }\r
+                x += charWidth[position];\r
+                g.setClip(clipX, clipY, clipWidth, clipHeight);\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public String getCharset() {\r
+        return charsets;\r
+    }\r
+}\r
diff --git a/core/java/com/sun/lwuit/Dialog.java b/core/java/com/sun/lwuit/Dialog.java
new file mode 100644 (file)
index 0000000..6031d67
--- /dev/null
@@ -0,0 +1,652 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.lwuit;
+
+import com.sun.lwuit.animations.Transition;
+import com.sun.lwuit.geom.Dimension;
+import com.sun.lwuit.layouts.BorderLayout;
+import com.sun.lwuit.plaf.LookAndFeel;
+import com.sun.lwuit.plaf.Style;
+import com.sun.lwuit.plaf.UIManager;
+
+/**
+ * A dialog is a form that occupies a part of the screen and appears as a modal
+ * entity to the developer. Dialogs allow us to prompt users for information and
+ * rely on the information being available on the next line after the show method.
+ * <p>Modality indicates that a dialog will block the calling thread even if the
+ * calling thread is the EDT. Notice that a dialog will not release the block
+ * until dispose is called even if show() from another form is called!
+ * <p>To determin the size of the dialog use the show method that accepts 4 integer
+ * values, notice that these values accept margin from the four sides rather than x, y, width
+ * and height values!
+ * <p>To style the dialog you would usually want to style the content pane rather than
+ * the dialog itself.
+ *
+ * @author Shai Almog
+ */
+public class Dialog extends Form {
+    /**
+     * Indicates whether the dialog has been disposed
+     */
+    private boolean disposed;
+    
+    /**
+     * Constant indicating the type of alert to indicate the sound to play or
+     * icon if none are explicitly set
+     */
+    public static final int TYPE_ALARM = 1;
+    /**
+     * Constant indicating the type of alert to indicate the sound to play or
+     * icon if none are explicitly set
+     */
+    public static final int TYPE_CONFIRMATION = 2;
+    /**
+     * Constant indicating the type of alert to indicate the sound to play or
+     * icon if none are explicitly set
+     */
+    public static final int TYPE_ERROR = 3;
+    /**
+     * Constant indicating the type of alert to indicate the sound to play or
+     * icon if none are explicitly set
+     */
+    public static final int TYPE_INFO = 4;
+    /**
+     * Constant indicating the type of alert to indicate the sound to play or
+     * icon if none are explicitly set
+     */
+    public static final int TYPE_WARNING = 5;
+    /**
+     * Indicates the time in which the alert should be disposed
+     */
+    private long time;
+    /**
+     * Indicates the last command selected by the user in this form
+     */
+    private Command lastCommandPressed;
+    /**
+     * Indicates that this is a menu preventing getCurrent() from ever returning this class
+     */
+    private boolean menu;
+    private String dialogUIID;
+    private String dialogTitleUIID;
+    private int dialogType;
+    private int top = -1;
+    private int bottom;
+    private int left;
+    private int right;
+    private boolean includeTitle;
+
+    /**
+     * Determins whether the execution of a command on this dialog implicitly 
+     * disposes the dialog. This defaults to true which is a sensible default for
+     * simple dialogs.
+     */
+    private boolean autoDispose = true;
+
+    private boolean modal = true;
+    
+    /**
+     * Constructs a Dialog with a title
+     * 
+     * @param title the title of the dialog
+     */
+    public Dialog(String title) {
+        this();
+        setTitle(title);
+    }
+
+    /**
+     * Constructs a Dialog with a title
+     * 
+     */
+    public Dialog() {
+        this("Dialog", "DialogTitle");
+    }
+
+    Dialog(String dialogUIID, String dialogTitleUIID) {
+        super();
+        this.dialogUIID = dialogUIID;
+        this.dialogTitleUIID = dialogTitleUIID;
+        setDialogStyle(UIManager.getInstance().getComponentStyle(dialogUIID));
+        setTitleStyle(UIManager.getInstance().getComponentStyle(dialogTitleUIID));
+        super.getStyle().setBgTransparency(0);
+        super.getStyle().setBgImage(null);
+        setSmoothScrolling(false);
+        deregisterAnimated(this);
+    }
+
+    
+    /**
+     * Simple setter to set the Dialog Style
+     * 
+     * @param style
+     */
+    public void setDialogStyle(Style style){
+        getContentPane().setStyle(style);
+    }
+
+    /**
+     * Simple getter to get the Dialog Style
+     */
+    public Style getDialogStyle(){
+        return getContentPane().getStyle();
+    }
+
+    /**
+     * Initialize the default transition for the dialogs overriding the forms
+     * transition
+     * 
+     * @param laf the default transition for the dialog
+     */
+    void initLaf(LookAndFeel laf) {
+        setTransitionOutAnimator(laf.getDefaultDialogTransitionOut());
+        setTransitionInAnimator(laf.getDefaultDialogTransitionIn());
+    }
+
+    /**
+     * This method shows the form as a modal alert allowing us to produce a behavior
+     * of an alert/dialog box. This method will block the calling thread even if the
+     * calling thread is the EDT. Notice that this method will not release the block
+     * until dispose is called even if show() from another form is called!
+     * <p>Modal dialogs Allow the forms "content" to "hang in mid air" this is especially useful for
+     * dialogs where you would want the underlying form to "peek" from behind the 
+     * form. 
+     * 
+     * @param top space in pixels between the top of the screen and the form
+     * @param bottom space in pixels between the bottom of the screen and the form
+     * @param left space in pixels between the left of the screen and the form
+     * @param right space in pixels between the right of the screen and the form
+     * @param includeTitle whether the title should hang in the top of the screen or
+     * be glued onto the content pane
+     * @return the last command pressed by the user if such a command exists
+     */
+    public Command show(int top, int bottom, int left, int right, boolean includeTitle) {
+        return show(top, bottom, left, right, includeTitle, true);
+    }
+
+    /**
+     * This method shows the form as a modal alert allowing us to produce a behavior
+     * of an alert/dialog box. This method will block the calling thread even if the
+     * calling thread is the EDT. Notice that this method will not release the block
+     * until dispose is called even if show() from another form is called!
+     * <p>Modal dialogs Allow the forms "content" to "hang in mid air" this is especially useful for
+     * dialogs where you would want the underlying form to "peek" from behind the 
+     * form. 
+     * 
+     * @param top space in pixels between the top of the screen and the form
+     * @param bottom space in pixels between the bottom of the screen and the form
+     * @param left space in pixels between the left of the screen and the form
+     * @param right space in pixels between the right of the screen and the form
+     * @param includeTitle whether the title should hang in the top of the screen or
+     * be glued onto the content pane
+     * @param modal indicates the dialog should be modal set to false for modeless dialog
+     * which is useful for some use cases
+     * @return the last command pressed by the user if such a command exists
+     */
+    public Command show(int top, int bottom, int left, int right, boolean includeTitle, boolean modal) {
+        this.top = top;
+        this.bottom = bottom;
+        this.left = left;
+        this.right = right;
+        this.includeTitle = includeTitle;
+        setDisposed(false);
+        this.modal = modal;
+        super.showModal(top, bottom, left, right, includeTitle, modal);
+        return lastCommandPressed;
+    }
+
+    /**
+     * Indicates the time (in milliseconds) afterwhich the dialog will be disposed 
+     * implicitly
+     * 
+     * @param time a milliseconds time used to dispose the dialog
+     */
+    public void setTimeout(long time) {
+        this.time = System.currentTimeMillis() + time;
+        super.registerAnimated(this);
+    }
+
+    /**
+     * Shows a modal prompt dialog with the given title and text.
+     * 
+     * @param title The title for the dialog optionally null;
+     * @param text the text displayed in the dialog
+     * @param type the type of the alert one of TYPE_WARNING, TYPE_INFO, 
+     * TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
+     * @param icon the icon for the dialog, can be null
+     * @param okText the text to appear in the command dismissing the dialog
+     * @param cancelText optionally null for a text to appear in the cancel command
+     * for canceling the dialog
+     * @return true if the ok command was pressed or if cancelText is null. False otherwise.
+     */
+    public static boolean show(String title, String text, int type, Image icon, String okText, String cancelText) {
+        return show(title, text, type, icon, okText, cancelText, 0);
+    }
+
+    /**
+     * Shows a modal prompt dialog with the given title and text.
+     * 
+     * @param title The title for the dialog optionally null;
+     * @param text the text displayed in the dialog
+     * @param type the type of the alert one of TYPE_WARNING, TYPE_INFO, 
+     * TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
+     * @param icon the icon for the dialog, can be null
+     * @param okText the text to appear in the command dismissing the dialog
+     * @param cancelText optionally null for a text to appear in the cancel command
+     * for canceling the dialog
+     * @param timeout a timeout after which null would be returned if timeout is 0 inifinite time is used
+     * @return true if the ok command was pressed or if cancelText is null. False otherwise.
+     */
+    public static boolean show(String title, String text, int type, Image icon, String okText, String cancelText, long timeout) {
+        Command[] cmds;
+        Command okCommand = new Command(okText);
+        if (cancelText != null) {
+            cmds = new Command[]{new Command(cancelText), okCommand};
+        } else {
+            cmds = new Command[]{okCommand};
+        }
+        return show(title, text, okCommand, cmds, type, icon, timeout) == okCommand;
+    }
+
+    /**
+     * Shows a modal prompt dialog with the given title and text.
+     * 
+     * @param title The title for the dialog optionally null;
+     * @param text the text displayed in the dialog
+     * @param cmds commands that are added to the form any click on any command
+     * will dispose the form
+     * @param type the type of the alert one of TYPE_WARNING, TYPE_INFO, 
+     * TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
+     * @param icon the icon for the dialog, can be null
+     * @param timeout a timeout after which null would be returned if timeout is 0 inifinite time is used
+     * @return the command pressed by the user
+     */
+    public static Command show(String title, String text, Command[] cmds, int type, Image icon, long timeout) {
+        return show(title, text, null, cmds, type, icon, timeout);
+    }
+
+    /**
+     * Shows a modal prompt dialog with the given title and text.
+     * 
+     * @param title The title for the dialog optionally null;
+     * @param text the text displayed in the dialog
+     * @param defaultCommand command to be assigned as the default command or null
+     * @param cmds commands that are added to the form any click on any command
+     * will dispose the form
+     * @param type the type of the alert one of TYPE_WARNING, TYPE_INFO, 
+     * TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
+     * @param icon the icon for the dialog, can be null
+     * @param timeout a timeout after which null would be returned if timeout is 0 inifinite time is used
+     * @return the command pressed by the user
+     */
+    public static Command show(String title, String text, Command defaultCommand, Command[] cmds, int type, Image icon, long timeout) {
+        return show(title, text, defaultCommand, cmds, type, icon, timeout, null);
+    }
+
+    /**
+     * Shows a modal prompt dialog with the given title and text.
+     * 
+     * @param title The title for the dialog optionally null;
+     * @param text the text displayed in the dialog
+     * @param cmds commands that are added to the form any click on any command
+     * will dispose the form
+     * @param type the type of the alert one of TYPE_WARNING, TYPE_INFO, 
+     * TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
+     * @param icon the icon for the dialog, can be null
+     * @param timeout a timeout after which null would be returned if timeout is 0 inifinite time is used
+     * @param transition the transition installed when the dialog enters/leaves
+     * @return the command pressed by the user
+     */
+    public static Command show(String title, String text, Command[] cmds, int type, Image icon, long timeout, Transition transition) {
+        return show(title, text, null, cmds, type, icon, timeout, transition);
+    }
+
+    /**
+     * Shows a modal prompt dialog with the given title and text.
+     * 
+     * @param title The title for the dialog optionally null;
+     * @param text the text displayed in the dialog
+     * @param defaultCommand command to be assigned as the default command or null
+     * @param cmds commands that are added to the form any click on any command
+     * will dispose the form
+     * @param type the type of the alert one of TYPE_WARNING, TYPE_INFO, 
+     * TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
+     * @param icon the icon for the dialog, can be null
+     * @param timeout a timeout after which null would be returned if timeout is 0 inifinite time is used
+     * @param transition the transition installed when the dialog enters/leaves
+     * @return the command pressed by the user
+     */
+    public static Command show(String title, String text, Command defaultCommand, Command[] cmds, int type, Image icon, long timeout, Transition transition) {
+        TextArea t = new TextArea(text, 3, 30);
+        t.setStyle(UIManager.getInstance().getComponentStyle("DialogBody"));
+        t.setEditable(false);
+        return show(title, t, defaultCommand, cmds, type, icon, timeout, transition);
+    }
+
+    /**
+     * Shows a modal prompt dialog with the given title and text.
+     * 
+     * @param title The title for the dialog optionally null;
+     * @param text the text displayed in the dialog
+     * @param okText the text to appear in the command dismissing the dialog
+     * @param cancelText optionally null for a text to appear in the cancel command
+     * for canceling the dialog
+     * @return true if the ok command was pressed or if cancelText is null. False otherwise.
+     */
+    public static boolean show(String title, String text, String okText, String cancelText) {
+        return show(title, text, TYPE_INFO, null, okText, cancelText);
+    }
+
+    /**
+     * Shows a modal dialog with the given component as its "body" placed in the
+     * center. 
+     * 
+     * @param title title for the dialog
+     * @param body component placed in the center of the dialog
+     * @param cmds commands that are added to the form any click on any command
+     * will dispose the form
+     * @return the command pressed by the user
+     */
+    public static Command show(String title, Component body, Command[] cmds) {
+        return show(title, body, cmds, TYPE_INFO, null);
+    }
+
+    /**
+     * Shows a modal dialog with the given component as its "body" placed in the
+     * center. 
+     * 
+     * @param title title for the dialog
+     * @param body component placed in the center of the dialog
+     * @param cmds commands that are added to the form any click on any command
+     * will dispose the form
+     * @param type the type of the alert one of TYPE_WARNING, TYPE_INFO, 
+     * TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
+     * @param icon the icon for the dialog, can be null
+     * @return the command pressed by the user
+     */
+    public static Command show(String title, Component body, Command[] cmds, int type, Image icon) {
+        return show(title, body, cmds, type, icon, 0);
+    }
+
+    /**
+     * Shows a modal dialog with the given component as its "body" placed in the
+     * center. 
+     * 
+     * @param title title for the dialog
+     * @param body component placed in the center of the dialog
+     * @param cmds commands that are added to the form any click on any command
+     * will dispose the form
+     * @param type the type of the alert one of TYPE_WARNING, TYPE_INFO, 
+     * TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
+     * @param icon the icon for the dialog, can be null
+     * @param timeout a timeout after which null would be returned if timeout is 0 inifinite time is used
+     * @return the command pressed by the user
+     */
+    public static Command show(String title, Component body, Command[] cmds, final int type, Image icon, long timeout) {
+        return show(title, body, cmds, type, icon, timeout, null);
+    }
+    
+    /**
+     * Shows a modal dialog with the given component as its "body" placed in the
+     * center. 
+     * 
+     * @param title title for the dialog
+     * @param body component placed in the center of the dialog
+     * @param cmds commands that are added to the form any click on any command
+     * will dispose the form
+     * @param type the type of the alert one of TYPE_WARNING, TYPE_INFO, 
+     * TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
+     * @param icon the icon for the dialog, can be null
+     * @param timeout a timeout after which null would be returned if timeout is 0 inifinite time is used
+     * the transition installed when the dialog enters/leaves
+     * @return the command pressed by the user
+     */
+    public static Command show(String title, Component body, Command[] cmds, int type, Image icon, long timeout, Transition transition) {
+        return show(title, body, null, cmds, type, icon, timeout, transition);
+    }
+
+    /**
+     * Shows a modal dialog with the given component as its "body" placed in the
+     * center. 
+     * 
+     * @param title title for the dialog
+     * @param body component placed in the center of the dialog
+     * @param defaultCommand command to be assigned as the default command or null
+     * @param cmds commands that are added to the form any click on any command
+     * will dispose the form
+     * @param type the type of the alert one of TYPE_WARNING, TYPE_INFO, 
+     * TYPE_ERROR, TYPE_CONFIRMATION or TYPE_ALARM
+     * @param icon the icon for the dialog, can be null
+     * @param timeout a timeout after which null would be returned if timeout is 0 inifinite time is used
+     * the transition installed when the dialog enters/leaves
+     * @return the command pressed by the user
+     */
+    public static Command show(String title, Component body, Command defaultCommand, Command[] cmds, int type, Image icon, long timeout, Transition transition) {
+        Dialog dialog = new Dialog(title);
+        dialog.dialogType = type;
+        dialog.setTransitionInAnimator(transition);
+        dialog.setTransitionOutAnimator(transition);
+        dialog.lastCommandPressed = null;
+        if(cmds != null) {
+            for(int iter = 0 ; iter < cmds.length ; iter++) {
+                dialog.addCommand(cmds[iter]);
+            }
+        }
+        dialog.setLayout(new BorderLayout());
+        dialog.addComponent(BorderLayout.CENTER, body);
+        if (icon != null) {
+            dialog.addComponent(BorderLayout.EAST, new Label(icon));
+        }
+        if (timeout != 0) {
+            dialog.setTimeout(timeout);
+        }
+        dialog.show();
+        return dialog.lastCommandPressed;
+    }
+    
+    /**
+     * @inheritDoc
+     */
+    protected void onShow() {
+        if (dialogType > 0) {
+            Display.getInstance().playDialogSound(dialogType);
+        }
+    }
+    
+
+    /**
+     * The default version of show modal shows the dialog occupying the center portion
+     * of the screen.
+     */
+    public void show() {
+        // this behavior allows a use case where dialogs of various sizes are layered 
+        // one on top of the other
+        setDisposed(false);
+        if(top > -1) {
+            show(top, bottom, left, right, includeTitle, modal);
+        } else {
+            if(modal) {
+                super.showModal();
+            } else {
+                showModeless();
+            }
+        }
+    }
+
+    /**
+     * Shows a modeless dialog which is useful for some simpler use cases such as
+     * progress indication etc...
+     */
+    public void showModeless() {
+        // this behavior allows a use case where dialogs of various sizes are layered 
+        // one on top of the other
+        modal = false;
+        setDisposed(false);
+        if(top > -1) {
+            show(top, bottom, left, right, includeTitle, false);
+        } else {
+            showDialog(false);
+        }
+    }
+
+    /**
+     * Closes the current form and returns to the previous form, releasing the 
+     * EDT in the process
+     */
+    public void dispose() {
+        setDisposed(true);
+        if(!menu) {
+            super.dispose();
+        }
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public void refreshTheme() {
+        Container content = getContentPane();
+        content.refreshTheme(dialogUIID);
+
+        Style titleStyle = getTitleStyle();
+        if (titleStyle.isModified()) {
+            titleStyle.merge(UIManager.getInstance().getComponentStyle(dialogTitleUIID));
+        } else {
+            setTitleStyle(UIManager.getInstance().getComponentStyle(dialogTitleUIID));
+        }
+
+        int size = content.getComponentCount();
+        for (int i = 0; i < size; i++) {
+            Component cmp = content.getComponentAt(i);
+            cmp.refreshTheme();
+        }
+    }
+
+    /**
+     * Shows a modal dialog and returns the command pressed within the modal dialog
+     * 
+     * @return last command pressed in the modal dialog
+     */
+    public Command showDialog() {
+        lastCommandPressed = null;
+        show();
+        return lastCommandPressed;
+    }
+    
+    /**
+     * Invoked to allow subclasses of form to handle a command from one point
+     * rather than implementing many command instances
+     * 
+     * @param cmd the action command
+     */
+    protected void actionCommand(Command cmd) {
+        lastCommandPressed = cmd;
+        if(menu || (autoDispose && cmd.isDisposesDialog())) {
+            dispose();
+        }
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public boolean animate() {
+        if (time != 0 && System.currentTimeMillis() >= time) {
+            time = 0;
+            dispose();
+        }
+        return false;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    protected void sizeChanged(int w, int h) {
+        Form frm = getPreviousForm();
+        while (frm instanceof Dialog) {
+            frm = frm.getPreviousForm();
+        }
+        frm.setSize(new Dimension(w, h));
+        frm.setShouldCalcPreferredSize(true);
+        frm.doLayout();
+
+        super.sizeChanged(w, h);
+    }
+
+    /**
+     * Indicates that this is a menu preventing getCurrent() from ever returning this class
+     */
+    boolean isMenu() {
+        return menu;
+    }
+
+    /**
+     * Indicates that this is a menu preventing getCurrent() from ever returning this class
+     */
+    void setMenu(boolean menu) {
+        this.menu = menu;
+    }
+
+    /**
+     * Prevent a menu from adding the select button
+     */
+    void addSelectCommand() {
+        if (!menu) {
+            super.addSelectCommand();
+        }
+    }
+
+    
+    /**
+     * Allows us to indicate disposed state for dialogs
+     */
+    boolean isDisposed() {
+        return disposed;
+    }
+
+    /**
+     * Allows us to indicate disposed state for dialogs
+     */
+    void setDisposed(boolean disposed) {
+        this.disposed = disposed;
+    }
+
+    /**
+     * Determins whether the execution of a command on this dialog implicitly 
+     * disposes the dialog. This defaults to true which is a sensible default for
+     * simple dialogs.
+     */
+    public boolean isAutoDispose() {
+        return autoDispose;
+    }
+
+
+    /**
+     * Determins whether the execution of a command on this dialog implicitly 
+     * disposes the dialog. This defaults to true which is a sensible default for
+     * simple dialogs.
+     */
+    public void setAutoDispose(boolean autoDispose) {
+        this.autoDispose = autoDispose;
+    }
+}
diff --git a/core/java/com/sun/lwuit/Display.java b/core/java/com/sun/lwuit/Display.java
new file mode 100644 (file)
index 0000000..29fe63c
--- /dev/null
@@ -0,0 +1,858 @@
+/*\r
+ * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.\r
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\r
+ *\r
+ * This code is free software; you can redistribute it and/or modify it\r
+ * under the terms of the GNU General Public License version 2 only, as\r
+ * published by the Free Software Foundation.  Sun designates this\r
+ * particular file as subject to the "Classpath" exception as provided\r
+ * by Sun in the LICENSE file that accompanied this code.\r
+ *\r
+ * This code is distributed in the hope that it will be useful, but WITHOUT\r
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
+ * version 2 for more details (a copy is included in the LICENSE file that\r
+ * accompanied this code).\r
+ *\r
+ * You should have received a copy of the GNU General Public License version\r
+ * 2 along with this work; if not, write to the Free Software Foundation,\r
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,\r
+ * CA 95054 USA or visit www.sun.com if you need additional information or\r
+ * have any questions.\r
+ */\r
+package com.sun.lwuit;\r
+\r
+import com.sun.lwuit.animations.Animation;\r
+import com.sun.lwuit.animations.CommonTransitions;\r
+import com.sun.lwuit.animations.Transition;\r
+import com.sun.lwuit.geom.Dimension;\r
+import java.util.Enumeration;\r
+import java.util.Vector;\r
+\r
+/**\r
+ * Central class for the API that manages rendering/events and is used to place top\r
+ * level components ({@link Form}) on the "display". Before any Form is shown the Developer must\r
+ * invoke Display.init(Object m) in order to register the current MIDlet.\r
+ * <p>This class handles the main thread for the toolkit referenced here on as the EDT \r
+ * (Event Dispatch Thread) similar to the Swing EDT. This thread encapsulates the platform\r
+ * specific event delivery and painting semantics and enables threading features such as\r
+ * animations etc...\r
+ * <p>The EDT should not be blocked since paint operations and events would also be blocked \r
+ * in much the same way as they would be in other platforms. In order to serialize calls back\r
+ * into the EDT use the methods {@link Display#callSerially} &amp; {@link Display#callSeriallyAndWait}.\r
+ * <p>Notice that all LWUIT calls occur on the EDT (events, painting, animations etc...), LWUIT \r
+ * should normally be manipulated on the EDT as well (hence the {@link Display#callSerially} &amp; \r
+ * {@link Display#callSeriallyAndWait} methods). Theoretically it should be possible to manipulate\r
+ * some LWUIT features from other threads but this can't be guaranteed to work for all use cases.\r
+ * \r
+ * @author Chen Fishbein, Shai Almog\r
+ */\r
+public final class Display {\r
+    /**\r
+     * Indicates whether this is a touch device\r
+     */\r
+    private boolean touchScreen;\r
+    \r
+    /**\r
+     * Light mode allows the UI to adapt and show less visual effects/lighter versions\r
+     * of these visual effects to work properly on low end devices.\r
+     */\r
+    private boolean lightMode;\r
+    \r
+    /**\r
+     * Game action for fire\r
+     */\r
+    public static final int GAME_FIRE = 8;\r
+\r
+    /**\r
+     * Game action for left key\r
+     */\r
+    public static final int GAME_LEFT = 2;\r
+\r
+    /**\r
+     * Game action for right key\r
+     */\r
+    public static final int GAME_RIGHT = 5;\r
+\r
+    /**\r
+     * Game action for UP key\r
+     */\r
+    public static final int GAME_UP = 1;\r
+\r
+    /**\r
+     * Game action for left key\r
+     */\r
+    public static final int GAME_DOWN = 6;\r
+    \r
+    /**\r
+     * An attribute that encapsulates '#' int value.\r
+     */\r
+    public static final int KEY_POUND = '#';\r
+\r
+    private static final Display INSTANCE = new Display();\r
+    \r
+    /**\r
+     * On some devices getKeyCode returns numeric values for game actions,\r
+     * this breaks the code since we filter these values. We pick unused \r
+     * negative values for game keys and assign them to game keys for getKeyCode.\r
+     */\r
+    private static int[] portableKeyCodes;\r
+    private static int[] portableKeyCodeValues;\r
+    \r
+    private Form current;\r
+    \r
+    private VirtualImplementation implementation = new VirtualImplementation();\r
+    \r
+    /**\r
+     * Contains the call serially pending elements\r
+     */\r
+    private Vector pendingSerialCalls = new Vector();\r
+    \r
+    /**\r
+     * This is the instance of the EDT used internally to indicate whether\r
+     * we are executing on the EDT or some arbitrary thread\r
+     */ \r
+    private Thread edt; \r
+\r
+    /**\r
+     * Contains animations that must be played in full by the EDT before anything further\r
+     * may be processed. This is useful for transitions/intro's etc... that animate without\r
+     * user interaction.\r
+     */\r
+    private Vector animationQueue;\r
+\r
+    /**\r
+     * Indicates whether the 3rd softbutton should be supported on this device\r
+     */\r
+    private boolean thirdSoftButton = false;\r
+    \r
+    private boolean editingText;\r
+\r
+    /**\r
+     * Ignore all calls to show occuring during edit, they are discarded immediately\r
+     */\r
+    public static final int SHOW_DURING_EDIT_IGNORE = 1;\r
+\r
+    /**\r
+     * If show is called while editing text in the native text box an exception is thrown\r
+     */\r
+    public static final int SHOW_DURING_EDIT_EXCEPTION = 2;\r
+    \r
+    /**\r
+     * Allow show to occur during edit and discard all user input at this moment\r
+     */\r
+    public static final int SHOW_DURING_EDIT_ALLOW_DISCARD = 3;\r
+\r
+    /**\r
+     * Allow show to occur during edit and save all user input at this moment\r
+     */\r
+    public static final int SHOW_DURING_EDIT_ALLOW_SAVE = 4;\r
+\r
+    /**\r
+     * Show will update the current form to which the OK button of the text box\r
+     * will return\r
+     */\r
+    public static final int SHOW_DURING_EDIT_SET_AS_NEXT = 5;\r
+     \r
+    private int showDuringEdit;\r
+    \r
+    static final Object lock = new Object();\r
+    \r
+    \r
+    /** \r
+     * Private constructor to prevent instanciation\r
+     */\r
+    private Display() {\r
+    }\r
+\r
+    Vector getAnimationQueue() {\r
+        return animationQueue;\r
+    }\r
+    \r
+    /**\r
+     * This is the Display initalization method.\r
+     * This method must be called before any Form is shown\r
+     * \r
+     * @param m the main running MIDlet\r
+     */\r
+    public static void init(Object m) {\r
+        INSTANCE.implementation.init(m);\r
+        \r
+        int width = INSTANCE.getDisplayWidth();\r
+        int height = INSTANCE.getDisplayHeight();\r
+        int colors = INSTANCE.numColors();\r
+        \r
+        // if the resolution is very high and the amount of memory is very low while the device \r
+        // itself has many colors (requiring 32 bits per pixel) then we should concerve memory\r
+        // by activating light mode.\r
+        INSTANCE.lightMode = colors > 65536 && width * height * 30 > Runtime.getRuntime().totalMemory();\r
+        \r
+        // this can happen on some cases where an application was restarted etc...\r
+        // generally its probably a bug but we can let it slide...\r
+        if(INSTANCE.edt == null) {\r
+            INSTANCE.touchScreen = INSTANCE.implementation.hasPointerEvents();\r
+            // initialize the JWT EDT which from now on will take all responsibility\r
+            // for the event delivery.\r
+            INSTANCE.edt = new Thread(INSTANCE.implementation, "EDT");\r
+            INSTANCE.edt.start();\r
+        }\r
+    }\r
+    \r
+    /**\r
+     * Return the Display instance\r
+     * \r
+     * @return the Display instance\r
+     */\r
+    public static Display getInstance(){\r
+        return INSTANCE;\r
+    }\r
+\r
+    /**\r
+     * Indicates the maximum frames the API will try to draw every second\r
+     * by defult this is set to 10. The advantage of limiting\r
+     * framerate is to allow the CPU to perform other tasks besides drawing.\r
+     * Notice that when no change is occuring on the screen no frame is drawn and\r
+     * so a high/low FPS will have no effect then.\r
+     * 10FPS would be very reasonable for a business application.\r
+     * \r
+     * @param rate the frame rate\r
+     */\r
+    public void setFramerate(int rate) {\r
+        implementation.setFramerate(rate);\r
+    }\r
+    \r
+    /**\r
+     * Vibrates the device for the given length of time\r
+     * \r
+     * @param duration length of time to vibrate\r
+     */\r
+    public void vibrate(int duration) {\r
+        implementation.vibrate(duration);\r
+    }\r
+    \r
+    /**\r
+     * Flash the backlight of the device for the given length of time\r
+     * \r
+     * @param duration length of time to flash the backlight\r
+     */\r
+    public void flashBacklight(int duration) {\r
+        implementation.flashBacklight(duration);\r
+    }\r
+\r
+    void blockEvents(boolean block){\r
+        implementation.blockEvents(block);\r
+    }\r
+    /**\r
+     * Invoking the show() method of a form/dialog while the user is editing\r
+     * text in the native text box can have several behaviors: SHOW_DURING_EDIT_IGNORE, \r
+     * SHOW_DURING_EDIT_EXCEPTION, SHOW_DURING_EDIT_ALLOW_DISCARD, \r
+     * SHOW_DURING_EDIT_ALLOW_SAVE, SHOW_DURING_EDIT_SET_AS_NEXT\r
+     * \r
+     * @param showDuringEdit one of the following: SHOW_DURING_EDIT_IGNORE, \r
+     * SHOW_DURING_EDIT_EXCEPTION, SHOW_DURING_EDIT_ALLOW_DISCARD, \r
+     * SHOW_DURING_EDIT_ALLOW_SAVE, SHOW_DURING_EDIT_SET_AS_NEXT\r
+     */\r
+    public void setShowDuringEditBehavior(int showDuringEdit) {\r
+        this.showDuringEdit = showDuringEdit;\r
+    }\r
+\r
+    /**\r
+     * Returns the status of the show during edit flag\r
+     * \r
+     * @return one of the following: SHOW_DURING_EDIT_IGNORE, \r
+     * SHOW_DURING_EDIT_EXCEPTION, SHOW_DURING_EDIT_ALLOW_DISCARD, \r
+     * SHOW_DURING_EDIT_ALLOW_SAVE, SHOW_DURING_EDIT_SET_AS_NEXT\r
+     */\r
+    public int getShowDuringEditBehavior() {\r
+        return showDuringEdit;\r
+    }\r
+\r
+    /**\r
+     * Indicates the maximum frames the API will try to draw every second\r
+     * \r
+     * @return the frame rate\r
+     */\r
+    public int getFrameRate() {\r
+        return implementation.getFrameRate();\r
+    }\r
+        \r
+    /**\r
+     * Returns true if we are currently in the event dispatch thread.\r
+     * This is useful for generic code that can be used both with the\r
+     * EDT and outside of it.\r
+     * \r
+     * @return true if we are currently in the event dispatch thread; \r
+     * otherwise false\r
+     */\r
+    public boolean isEdt() {\r
+        return edt == Thread.currentThread();\r
+    }\r
+    \r
+    /**\r
+     * Plays sound for the dialog\r
+     */\r
+    void playDialogSound(final int type) {\r
+        implementation.playDialogSound(type);\r
+    }\r
+    \r
+    /**\r
+     * Causes the runnable to be invoked on the event dispatch thread. This method\r
+     * returns immediately and will not wait for the serial call to occur \r
+     * \r
+     * @param r runnable (NOT A THREAD!) that will be invoked on the EDT serial to\r
+     * the paint and key handling events \r
+     * @throws IllegalStateException if this method is invoked on the event dispatch thread (e.g. during\r
+     * paint or event handling).\r
+     */\r
+    public void callSerially(Runnable r){\r
+        if(isEdt()) {\r
+            throw new IllegalStateException("Call serially must never be invoked from the EDT");\r
+        }\r
+        synchronized(lock) {\r
+            pendingSerialCalls.addElement(r);\r
+            lock.notify();\r
+        }\r
+    }\r
+    \r
+    \r
+    /**\r
+     * Identical to callSerially with the added benefit of waiting for the Runnable method to complete.\r
+     * \r
+     * @param r runnable (NOT A THREAD!) that will be invoked on the EDT serial to\r
+     * the paint and key handling events \r
+     * @throws IllegalStateException if this method is invoked on the event dispatch thread (e.g. during\r
+     * paint or event handling).\r
+     */\r
+    public void callSeriallyAndWait(Runnable r){\r
+        RunnableWrapper c = new RunnableWrapper(r, 0);\r
+        callSerially(c);\r
+        synchronized(lock) {\r
+            while(!c.isDone()) {\r
+                try {\r
+                    lock.wait();\r
+                } catch(InterruptedException err) {}\r
+            }\r
+        }\r
+    }\r
+    \r
+    /**\r
+     * Allows us to "flush" the edt to allow any pending transitions and input to go\r
+     * by before continuing with our other tasks.\r
+     */\r
+    void flushEdt() {\r
+        while(!implementation.shouldEDTSleepNoFormAnimation()) {\r
+            implementation.edtLoopImpl();\r
+        }\r
+    }\r
+    \r
+    boolean hasNoSerialCallsPending() {\r
+        return pendingSerialCalls.size() == 0;\r
+    }\r
+    \r
+    /**\r
+     * Used by the EDT to process all the calls submitted via call serially\r
+     */\r
+    void processSerialCalls() {\r
+        int size = pendingSerialCalls.size();\r
+        if(size > 0) {\r
+            Runnable[] array = new Runnable[size];\r
+\r
+            // copy all elements to an array and remove them otherwise invokeAndBlock from\r
+            // within a callSerially() can cause an infinite loop...\r
+            for(int iter = 0 ; iter < size ; iter++) {\r
+                array[iter] = (Runnable)pendingSerialCalls.elementAt(iter);\r
+            }\r
+\r
+            pendingSerialCalls.removeAllElements();\r
+\r
+            for(int iter = 0 ; iter < size ; iter++) {\r
+                array[iter].run();\r
+            }\r
+\r
+            // after finishing an event cycle there might be serial calls waiting\r
+            // to return.\r
+            synchronized(lock){\r
+                lock.notify();\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Invokes runnable and blocks the current thread, if the current thread is the\r
+     * edt it will still be blocked however a separate thread would be launched\r
+     * to perform the duties of the EDT while it is blocked. Once blocking is finished\r
+     * the EDT would be restored to its original position. This is very similar to the\r
+     * "foxtrot" Swing toolkit and allows coding "simpler" logic that requires blocking\r
+     * code in the middle of event sensitive areas.\r
+     * \r
+     * @param r runnable (NOT A THREAD!) that will be invoked synchroniously by this method\r
+     */\r
+    public void invokeAndBlock(Runnable r){\r
+        if(isEdt()) {\r
+            synchronized(lock) {\r
+                // this class allows a runtime exception to propogate correctly out of the\r
+                // internal thread\r
+                RunnableWrapper w = new RunnableWrapper(r, 1);\r
+                Thread t = new Thread(w);\r
+                t.start();\r
+\r
+                // loop over the EDT until the thread completes then return\r
+                while(t.isAlive()) {\r
+                    try {\r
+                        if(implementation.shouldEDTSleep()) {\r
+                            lock.wait(50);\r
+                        } else {\r
+                            implementation.edtLoopImpl();\r
+                        }\r
+                    } catch (InterruptedException ex) {\r
+                        ex.printStackTrace();\r
+                    }\r
+                }\r
+                // if the thread thew an exception we need to throw it onwards\r
+                if(w.getErr() != null) {\r
+                    throw w.getErr();\r
+                }\r
+            }\r
+        } else {\r
+            r.run();\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Indicates if this is a touch screen device that will return pen events,\r
+     * defaults to true if the device has pen events but can be overriden by\r
+     * the developer.\r
+     */\r
+    public boolean isTouchScreenDevice() {\r
+        return touchScreen;\r
+    }\r
+    \r
+    /**\r
+     * Indicates if this is a touch screen device that will return pen events,\r
+     * defaults to true if the device has pen events but can be overriden by\r
+     * the developer.\r
+     */\r
+    public void setTouchScreenDevice(boolean touchScreen) {\r
+        this.touchScreen = touchScreen;\r
+    }\r
+    \r
+    /**\r
+     * Displays the given Form on the screen.\r
+     * \r
+     * @param newForm the Form to Display\r
+     */\r
+    void setCurrent(final Form newForm){\r
+        if(edt == null) {\r
+            throw new IllegalStateException("Initialize must be invoked before setCurrent!");\r
+        }\r
+        \r
+        if(editingText) {\r
+            switch(showDuringEdit) {\r
+                case SHOW_DURING_EDIT_ALLOW_DISCARD:\r
+                    break;\r
+                case SHOW_DURING_EDIT_ALLOW_SAVE:\r
+                    implementation.saveTextBox();\r
+                    break;\r
+                case SHOW_DURING_EDIT_EXCEPTION:\r
+                    throw new IllegalStateException("Show during edit");\r
+                case SHOW_DURING_EDIT_IGNORE:\r
+                    return;\r
+                case SHOW_DURING_EDIT_SET_AS_NEXT:\r
+                    current = newForm;\r
+                    return;\r
+            }\r
+        }\r
+        \r
+        if(!isEdt()) {\r
+            callSerially(new RunnableWrapper(newForm, null));\r
+            return;\r
+        }\r
+        \r
+        if(current != null){\r
+            current.hidePopups();\r
+            if(current.isInitialized()) {\r
+                current.deinitializeImpl();\r
+            }\r
+        }\r
+        if(!newForm.isInitialized()) {\r
+            newForm.initComponentImpl();\r
+        }\r
+        \r
+        newForm.setShouldCalcPreferredSize(true);\r
+        newForm.layoutContainer();\r
+\r
+        synchronized(lock) {\r
+            boolean transitionExists = false;\r
+            Form current = this.current;\r
+            if(animationQueue != null && animationQueue.size() > 0) {\r
+                Object o = animationQueue.lastElement();\r
+                if(o instanceof Transition) {\r
+                    current = (Form)((Transition)o).getDestination();\r
+                }\r
+            }\r
+\r
+            // make sure the fold menu occurs as expected then set the current\r
+            // to the correct parent!\r
+            if(current != null && current instanceof Dialog && ((Dialog)current).isMenu()) {\r
+                Transition t = current.getTransitionOutAnimator();\r
+                if(t != null) {\r
+                    // go back to the parent form first\r
+                    initTransition(t.copy(), current, ((Dialog)current).getPreviousForm());\r
+                }\r
+                current = ((Dialog)current).getPreviousForm();\r
+            }\r
+            \r
+            // prevent the transition from occuring from a form into itself\r
+            if(newForm != current) {\r
+                if((current != null && current.getTransitionOutAnimator() != null) || newForm.getTransitionInAnimator() != null) {\r
+                    if(animationQueue == null) {\r
+                        animationQueue = new Vector();\r
+                    }\r
+                    // prevent form transitions from breaking our dialog based\r
+                    // transitions which are a bit sensitive\r
+                    if(current != null && (!(newForm instanceof Dialog))) {\r
+                        Transition t = current.getTransitionOutAnimator();\r
+                        if(current != null && t != null) {\r
+                            initTransition(t.copy(), current, newForm);\r
+                            transitionExists = true;\r
+                        }\r
+                    }\r
+                    if(current != null && !(current instanceof Dialog)) {\r
+                        Transition t = newForm.getTransitionInAnimator();\r
+                        if(t != null) {\r
+                            initTransition(t.copy(), current, newForm);\r
+                            transitionExists = true;\r
+                        }\r
+                    }\r
+                }\r
+            } \r
+            lock.notify();\r
+            \r
+            if(!transitionExists) {\r
+                if(animationQueue == null || animationQueue.size() == 0) {\r
+                    setCurrentForm(newForm);\r
+                } else {\r
+                    // we need to add an empty transition to "serialize" this\r
+                    // screen change...\r
+                    Transition t = CommonTransitions.createEmpty();\r
+                    initTransition(t, current, newForm);\r
+                }\r
+            }\r
+        }\r
+    }\r
+    \r
+    /**\r
+     * Initialize the transition and add it to the queue\r
+     */\r
+    private void initTransition(Transition transition, Form source, Form dest) {\r
+        dest.setVisible(true);\r
+        transition.init(source, dest);\r
+        animationQueue.addElement(transition);\r
+        if(animationQueue.size() == 1) {\r
+            transition.initTransition();\r
+        }\r
+    }\r
+    \r
+    void setCurrentForm(Form newForm){\r
+        if(this.current != null){\r
+            this.current.setVisible(false);\r
+        }\r
+        this.current = newForm;\r
+        this.current.setVisible(true);\r
+        \r
+        //implementation.confirmControlsView();\r
+        \r
+        if(isEdt() && (this.current.getWidth() != implementation.getDisplayWidth() ||\r
+           this.current.getHeight() != implementation.getDisplayHeight())){\r
+           this.current.setSize(new Dimension(implementation.getDisplayWidth(),implementation.getDisplayHeight()));\r
+           this.current.setShouldCalcPreferredSize(true);\r
+           this.current.layoutContainer();\r
+        }\r
+        repaint(current);\r
+    }\r
+    \r
+    /**\r
+     * Indicate to the implementation whether the flush graphics bug exists on this\r
+     * device. By default the flushGraphics bug is set to "true" and only disabled\r
+     * on handsets known 100% to be safe\r
+     * \r
+     * @param flushGraphicsBug true if the bug exists on this device (the safe choice)\r
+     * false for slightly higher performance.\r
+     */\r
+    public void setFlashGraphicsBug(boolean flushGraphicsBug) {\r
+        implementation.setFlashGraphicsBug(flushGraphicsBug);\r
+    }\r
+    \r
+    /**\r
+     * Indicates whether a delay should exist between calls to flush graphics during\r
+     * transition. In some devices flushGraphics is asynchronious causing it to be\r
+     * very slow with our background thread. The solution is to add a short wait allowing\r
+     * the implementation time to paint the screen. This value is set automatically by default\r
+     * but can be overriden for some devices.\r
+     * \r
+     * @param transitionDelay -1 for no delay otherwise delay in milliseconds\r
+     */\r
+    public void setTransitionYield(int transitionDelay) {\r
+        implementation.setTransitionYield(transitionDelay);\r
+    }\r
+\r
+    /**\r
+     * Encapsulates the editing code which is specific to the platform, some platforms\r
+     * would allow "in place editing" MIDP does not.\r
+     * \r
+     * @param cmp the {@link TextArea} component\r
+     */\r
+    void editString(Component cmp, int maxSize, int constraint, String text) {\r
+        editingText = true;\r
+        implementation.editString(cmp, maxSize, constraint, text);\r
+        editingText = false;\r
+    }\r
+\r
+   /**\r
+    * Returns the video control for the media player\r
+    * \r
+    * @param player the media player\r
+    * @return the video control for the media player\r
+    */\r
+    Object getVideoControl(Object player) {\r
+        return implementation.getVideoControl(player);\r
+    }\r
+    \r
+    Form getCurrentInternal() {\r
+        return current;\r
+    }\r
+        \r
+    /**\r
+     * Same as getCurrent with the added exception of looking into the future\r
+     * transitions and returning the last current in the transition (the upcoming\r
+     * value for current)\r
+     * \r
+     * @return the form currently displayed on the screen or null if no form is\r
+     * currently displayed\r
+     */\r
+    Form getCurrentUpcoming() {\r
+        Form upcoming = null;\r
+        \r
+        // we are in the middle of a transition so we should extract the next form\r
+        if(animationQueue != null) {\r
+            Enumeration e = animationQueue.elements();\r
+            while(e.hasMoreElements()) {\r
+                Object o = e.nextElement();\r
+                if(o instanceof Transition) {\r
+                    upcoming = (Form)((Transition)o).getDestination();\r
+                }\r
+            }\r
+        }\r
+        if(upcoming == null) {\r
+            return getCurrent();\r
+        }\r
+        return upcoming;\r
+    }\r
+\r
+    /**\r
+     * Return the form currently displayed on the screen or null if no form is\r
+     * currently displayed.\r
+     * \r
+     * @return the form currently displayed on the screen or null if no form is\r
+     * currently displayed\r
+     */\r
+    public Form getCurrent(){\r
+        if(current != null && current instanceof Dialog && ((Dialog)current).isMenu()) {\r
+            Form p = current.getPreviousForm();\r
+            if(p != null) {\r
+                return p;\r
+            }\r
+            \r
+            // we are in the middle of a transition so we should extract the next form\r
+            Enumeration e = animationQueue.elements();\r
+            while(e.hasMoreElements()) {\r
+                Object o = e.nextElement();\r
+                if(o instanceof Transition) {\r
+                    return (Form)((Transition)o).getDestination();\r
+                }\r
+            }\r
+        }\r
+        return current;\r
+    }\r
+    \r
+    /**\r
+     * Return the number of alpha levels supported by the implementation.\r
+     * \r
+     * @return the number of alpha levels supported by the implementation\r
+     */\r
+    public int numAlphaLevels(){\r
+        return implementation.numAlphaLevels();\r
+    }\r
+\r
+    /**\r
+     * Returns the number of colors applicable on the device, note that the API\r
+     * does not support gray scale devices.\r
+     * \r
+     * @return the number of colors applicable on the device\r
+     */\r
+    public int numColors() {\r
+        return implementation.numColors();\r
+    }\r
+\r
+    /**\r
+     * Light mode allows the UI to adapt and show less visual effects/lighter versions\r
+     * of these visual effects to work properly on low end devices.\r
+     */\r
+    public boolean isLightMode() {\r
+        return lightMode;\r
+    }\r
+\r
+    /**\r
+     * Light mode allows the UI to adapt and show less visual effects/lighter versions\r
+     * of these visual effects to work properly on low end devices.\r
+     */\r
+    public void setLightMode(boolean lightMode) {\r
+        this.lightMode = lightMode;\r
+    }\r
+    \r
+    \r
+    /**\r
+     * Return the width of the display\r
+     * \r
+     * @return the width of the display\r
+     */\r
+    public int getDisplayWidth(){\r
+        return implementation.getDisplayWidth();\r
+    }\r
+    \r
+    /**\r
+     * Return the height of the display\r
+     * \r
+     * @return the height of the display\r
+     */\r
+    public int getDisplayHeight(){\r
+        return implementation.getDisplayHeight();\r
+    }\r
+    \r
+    /**\r
+     * Causes the given component to repaint, used internally by Form\r
+     * \r
+     * @param cmp the given component to repaint\r
+     */\r
+    void repaint(final Animation cmp){\r
+        implementation.repaint(cmp);\r
+    }\r
+        \r
+    /**\r
+     * Returns the game action code matching the given key combination\r
+     * \r
+     * @param keyCode key code received from the event\r
+     * @return game action matching this keycode\r
+     */\r
+    public int getGameAction(int keyCode){\r
+        try {\r
+            // prevent game actions from being returned by numeric keypad thus screwing up\r
+            // keypad based navigation and text input\r
+            if(keyCode >= '0' && keyCode <= '9') {\r
+                return 0;\r
+            }\r
+            if(portableKeyCodes != null) {\r
+                for(int iter = 0 ; iter < portableKeyCodeValues.length ; iter++) {\r
+                    if(portableKeyCodeValues[iter] == keyCode) {\r
+                        return portableKeyCodes[iter];\r
+                    }\r
+                }\r
+            }\r
+            \r
+            return implementation.getGameAction(keyCode);\r
+        } catch(IllegalArgumentException err) {\r
+            // this is a stupid MIDP requirement some implementations throw this\r
+            // exception for some keys\r
+            return 0;\r
+        }\r
+    }\r
+    \r
+    /**\r
+     * Returns the keycode matching the given game action constant (the opposite of getGameAction).\r
+     * On some devices getKeyCode returns numeric keypad values for game actions,\r
+     * this breaks the code since we filter these values (to prevent navigation on '2'). \r
+     * We pick unused negative values for game keys and assign them to game keys for \r
+     * getKeyCode so they will work with getGameAction.\r
+     * \r
+     * @param gameAction game action constant from this class\r
+     * @return keycode matching this constant\r
+     * @deprecated this method doesn't work properly across device and is mocked up here\r
+     * mostly for the case of unit testing. Do not use it for anything other than that! Do\r
+     * not rely on getKeyCode(GAME_*) == keyCodeFromKeyEvent, this will never actually happen!\r
+     */\r
+    public int getKeyCode(int gameAction){\r
+        if(portableKeyCodes == null) {\r
+            portableKeyCodes = new int[] {GAME_DOWN, GAME_LEFT, GAME_RIGHT, GAME_UP, GAME_FIRE};\r
+            portableKeyCodeValues = new int[5];\r
+            int currentValue = -500;\r
+            int offset = 0;\r
+            while(offset < portableKeyCodeValues.length) {\r
+                currentValue--;\r
+                try {\r
+                    if(implementation.getGameAction(currentValue) != 0) {\r
+                        continue;\r
+                    }\r
+                } catch(IllegalArgumentException ignor) {\r
+                    // this is good, the game key is unassigned\r
+                }\r
+                portableKeyCodeValues[offset] = currentValue;\r
+                offset++;\r
+            }\r
+        }\r
+        for(int iter = 0 ; iter < portableKeyCodes.length ; iter++) {\r
+            if(portableKeyCodes[iter] == gameAction) {\r
+                return portableKeyCodeValues[iter];\r
+            }\r
+        }\r
+        return 0;\r
+    }\r
+     \r
+    /**\r
+     * Allows overriding the softkeys initialized by the software to a different value.\r
+     * This method MUST be invoked after init() has completed. \r
+     * <p>In order to maintain the default value 0 can be passed as a value for a softkey\r
+     * thus resulting in no effect e.g. setSoftkeyCodes(0, 0, 0, -8); will only affect the back key.\r
+     * @param left the left softkey code\r
+     * @param right the right softkey code\r
+     * @param clear the clear softkey code\r
+     * @param back the back softkey code\r
+     */\r
+    public void setSoftkeyCodes(int left, int right, int clear, int back) {\r
+        if(left != 0) {\r
+            Form.leftSK = left;\r
+        }\r
+        if(right != 0) {\r
+            Form.rightSK = right;\r
+        }\r
+        if(clear != 0) {\r
+            Form.clearSK = clear;\r
+        }\r
+        if(back != 0) {\r
+            Form.backSK = back;\r
+        }\r
+    }\r
+    \r
+    \r
+    /**\r
+     * Indicates whether the 3rd softbutton should be supported on this device\r
+     */\r
+    public boolean isThirdSoftButton() {\r
+        return thirdSoftButton;\r
+    }\r
+\r
+    /**\r
+     * Indicates whether the 3rd softbutton should be supported on this device\r
+     */\r
+    public void setThirdSoftButton(boolean thirdSoftButton) {\r
+        this.thirdSoftButton = thirdSoftButton;\r
+    }\r
+\r
+    VirtualImplementation getVirtualImplementation() {\r
+        return implementation;\r
+    }\r
+    \r
+    \r
+\r
+}\r
diff --git a/core/java/com/sun/lwuit/EditForm.java b/core/java/com/sun/lwuit/EditForm.java
new file mode 100644 (file)
index 0000000..ba535bb
--- /dev/null
@@ -0,0 +1,1132 @@
+package com.sun.lwuit;\r
+\r
+import java.util.Vector;\r
+\r
+import org.thenesis.microbackend.ui.KeyConstants;\r
+import org.thenesis.microbackend.ui.graphics.VirtualKeyboard;\r
+\r
+import com.sun.lwuit.events.ActionEvent;\r
+import com.sun.lwuit.events.ActionListener;\r
+import com.sun.lwuit.geom.Dimension;\r
+import com.sun.lwuit.geom.Rectangle;\r
+import com.sun.lwuit.layouts.BorderLayout;\r
+import com.sun.lwuit.layouts.BoxLayout;\r
+import com.sun.lwuit.plaf.Style;\r
+import com.sun.lwuit.plaf.UIManager;\r
+import com.sun.lwuit.util.Log;\r
+\r
+public class EditForm extends Form {\r
+\r
+    private VirtualKeyboardComponent keyboardComponent = new VirtualKeyboardComponent();\r
+    VirtualImplementation implementation;\r
+    private Form lastForm;\r
+    private TextArea textArea;\r
+    private EditableTextArea editableTextArea;\r
+\r
+    private Command okCommand;\r
+    private Command disableCommand;\r
+    private Command enableCommand;\r
+    private Command cancelCommand;\r
+\r
+    public EditForm(VirtualImplementation implementation, Form lastForm, TextArea textArea) {\r
+        super("Edit");\r
+        this.implementation = implementation;\r
+        this.lastForm = lastForm;\r
+        this.textArea = textArea;\r
+        setScrollable(false);\r
+\r
+        // Create subcomponent\r
+        keyboardComponent.setFocusable(true);\r
+        editableTextArea = new EditableTextArea(this, textArea);\r
+        editableTextArea.setFocusable(false);\r
+\r
+        // Add subcomponents to the form\r
+        setLayout(new BorderLayout());\r
+        addComponent(BorderLayout.CENTER, editableTextArea);\r
+        addComponent(BorderLayout.SOUTH, keyboardComponent);\r
+\r
+        // Create commands\r
+        okCommand = new Command("Ok");\r
+        addCommand(okCommand);\r
+        disableCommand = new Command("Disable Virtual Keyboard");\r
+        addCommand(disableCommand);\r
+        enableCommand = new Command("Enable Virtual Keyboard");\r
+        cancelCommand = new Command("Cancel");\r
+        addCommand(cancelCommand);\r
+        setCommandListener(new ActionListener() {\r
+            public void actionPerformed(ActionEvent e) {\r
+                if (e.getCommand() == okCommand) {\r
+                    saveAndExit();\r
+                } else if (e.getCommand() == disableCommand) {\r
+                    removeComponent(keyboardComponent);\r
+                    removeCommand(disableCommand);\r
+                    addCommand(enableCommand);\r
+                    editableTextArea.setFocusable(true);\r
+                } else if (e.getCommand() == enableCommand) {\r
+                    addComponent(BorderLayout.SOUTH, keyboardComponent);\r
+                    removeCommand(enableCommand);\r
+                    addCommand(disableCommand);\r
+                    editableTextArea.setFocusable(false);\r
+                } else if (e.getCommand() == cancelCommand) {\r
+                    cancel();\r
+                }\r
+                e.consume();\r
+            }\r
+        });\r
+\r
+        //registerAnimated(editableTextArea);\r
+\r
+    }\r
+\r
+    public void cancel() {\r
+        Display.getInstance().setCurrent(lastForm);\r
+    }\r
+\r
+    public void saveAndExit() {\r
+        textArea.setText(editableTextArea.getText());\r
+        Display.getInstance().setCurrent(lastForm);\r
+    }\r
+\r
+    private class VirtualKeyboardComponent extends Label {\r
+\r
+        private Dimension dim = new Dimension(VirtualKeyboard.WIDTH, VirtualKeyboard.HEIGHT);\r
+        private int posX;\r
+        private int posY;\r
+        private VirtualKeyboard keyboard = new VirtualKeyboard();\r
+        private int[] buffer;\r
+\r
+        /**\r
+         * Construct an empty label\r
+         */\r
+        public VirtualKeyboardComponent() {\r
+            VirtualKeyboardComponent.this.setHandlesInput(true);\r
+            VirtualKeyboardComponent.this.setFocusPainted(false);\r
+\r
+            buffer = new int[VirtualKeyboard.HEIGHT * VirtualKeyboard.WIDTH];\r
+            keyboard.activateCursor(true);\r
+        }\r
+\r
+        /**\r
+         * @inheritDoc\r
+         */\r
+        protected Dimension calcPreferredSize() {\r
+            return dim;\r
+        }\r
+\r
+        protected void initComponent() {\r
+            super.initComponent();\r
+            VirtualKeyboardComponent.this.requestFocus();\r
+        }\r
+\r
+        public void paint(Graphics g) {\r
+\r
+            System.out.println("getClipX=" + g.getClipX() + " getY=" + g.getClipY() + " getClipW=" + g.getClipWidth() + " getClipH="\r
+                    + g.getClipHeight());\r
+\r
+            if (keyboard.isDirty()) {\r
+                keyboard.draw(buffer);\r
+            }\r
+\r
+            calcPosition();\r
+            g.drawRGB(buffer, 0, VirtualKeyboard.WIDTH, posX, posY, VirtualKeyboard.WIDTH, VirtualKeyboard.HEIGHT, false);\r
+\r
+        }\r
+\r
+        public void handleKey(int key) {\r
+\r
+            boolean needRepaint = false;\r
+\r
+            if (key >= 0) {\r
+                //System.out.println("key " + key);\r
+                switch (key) {\r
+                case 10: // Enter\r
+                    editableTextArea.insertChar('\n');\r
+                    needRepaint = true;\r
+                    //completeInputMode(true);\r
+                    break;\r
+                case 24: // Cancel\r
+                    //completeInputMode(false);\r
+                    break;\r
+                case 8: // Backspace\r
+                    if (editableTextArea.deletePreviousChar()) {\r
+                        needRepaint = true;\r
+                    }\r
+                    break;\r
+                case VirtualKeyboard.KEY_UP:\r
+                    editableTextArea.moveCaret(Display.GAME_UP);\r
+                    needRepaint = true;\r
+                    break;\r
+                case VirtualKeyboard.KEY_DOWN:\r
+                    editableTextArea.moveCaret(Display.GAME_DOWN);\r
+                    needRepaint = true;\r
+                    break;\r
+                case VirtualKeyboard.KEY_LEFT:\r
+                    editableTextArea.moveCaret(Display.GAME_LEFT);\r
+                    needRepaint = true;\r
+                    break;\r
+                case VirtualKeyboard.KEY_RIGHT:\r
+                    editableTextArea.moveCaret(Display.GAME_RIGHT);\r
+                    needRepaint = true;\r
+                    break;\r
+                default:\r
+                    editableTextArea.insertChar((char) key);\r
+                    needRepaint = true;\r
+                    //textField.insert(String.valueOf((char)key), textField.size());\r
+                }\r
+            }\r
+\r
+            if (needRepaint) {\r
+                editableTextArea.repaint();\r
+            }\r
+        }\r
+\r
+        public void keyPressed(int keyCode) {\r
+\r
+            if (Log.TRACE_ENABLED)\r
+                System.out.println("[DEBUG] VirtualKeyboardComponent.keyPressed()");\r
+\r
+            int gameAction = Display.getInstance().getGameAction(keyCode);\r
+\r
+            switch (gameAction) {\r
+            case Display.GAME_UP:\r
+                keyboard.moveUp();\r
+                break;\r
+            case Display.GAME_DOWN:\r
+                keyboard.moveDown();\r
+                break;\r
+            case Display.GAME_LEFT:\r
+                keyboard.moveLeft();\r
+                break;\r
+            case Display.GAME_RIGHT:\r
+                keyboard.moveRight();\r
+                break;\r
+            case Display.GAME_FIRE:\r
+                int key = keyboard.pushKey();\r
+                handleKey(key);\r
+                break;\r
+            }\r
+\r
+            if (keyboard.isDirty())\r
+                repaint();\r
+\r
+        }\r
+\r
+        public void keyReleased(int keyCode) {\r
+            keyboard.releaseKey();\r
+            if (keyboard.isDirty())\r
+                repaint();\r
+        }\r
+\r
+        public void pointerPressed(int x, int y) {\r
+            calcPosition();\r
+\r
+            //System.out.println("x=" + x + " y=" + y);\r
+            //            System.out.println("getX=" + getX() + " getY=" + getY() + " getW=" + getWidth() + " getH=" + getHeight());\r
+            //            System.out.println("Padding(LEFT)=" + getStyle().getPadding(Component.LEFT) + " Padding(RIGHT)=" + getStyle().getPadding(Component.RIGHT) + " Padding(TOP)=" + getStyle().getPadding(Component.TOP) + " Padding(BOTTOM)=" + getStyle().getPadding(Component.BOTTOM));\r
+            //            System.out.println("Margin(LEFT)=" + getStyle().getMargin(Component.LEFT) + " Margin(RIGHT)=" + getStyle().getMargin(Component.RIGHT) + " Margin(TOP)=" + getStyle().getMargin(Component.TOP) + " Margin(BOTTOM)=" + getStyle().getMargin(Component.BOTTOM));\r
+            //            System.out.println("posX=" + posX + " posY=" + posY);\r
+            //System.out.println("getAbsoluteX=" + getAbsoluteX() + " getAbsoluteY=" + getAbsoluteY());\r
+            //            System.out.println("(x - posX)=" + (x - posX) + "  (y - posY)=" + (y - posY));\r
+            //            int shift = -getStyle().getPadding(Component.TOP) - getStyle().getPadding(Component.BOTTOM) - getStyle().getMargin(Component.TOP) - getStyle().getMargin(Component.BOTTOM);\r
+            //            System.out.println("shift=" + shift)\r
+\r
+            // FIXME Where does the shift come from ? Bug ?\r
+            int shift = getAbsoluteY() - getY();\r
+            int key = keyboard.pushKey(x - posX, y - posY - shift);\r
+            handleKey(key);\r
+\r
+            if (keyboard.isDirty())\r
+                repaint();\r
+        }\r
+\r
+        public void pointerReleased(int x, int y) {\r
+            keyboard.releaseKey();\r
+            if (keyboard.isDirty())\r
+                repaint();\r
+        }\r
+\r
+        private void calcPosition() {\r
+            int x = getX(); // + c.getStyle().getPadding(Component.LEFT);\r
+            int y = getY(); // + c.getStyle().getPadding(Component.TOP);\r
+            int w = getWidth(); // - c.getStyle().getPadding(Component.LEFT) - c.getStyle().getPadding(Component.RIGHT);\r
+            int h = getHeight(); // - c.getStyle().getPadding(Component.TOP) - c.getStyle().getPadding(Component.BOTTOM) - c.getStyle().getMargin(Component.TOP) - c.getStyle().getMargin(Component.BOTTOM);\r
+            //System.out.println("w=" + w + " h=" + h);\r
+            posX = x + (w - VirtualKeyboard.WIDTH) / 2;\r
+            posY = y + (h - VirtualKeyboard.HEIGHT) / 2;\r
+        }\r
+\r
+    }\r
+\r
+}\r
+\r
+/**\r
+ * An multi-line editable region that can display text and allow a user to edit\r
+ * it.\r
+ */\r
+class EditableTextArea extends Component {\r
+    private static int defaultMaxSize = 124;\r
+    private static boolean autoDegradeMaxSize = false;\r
+    private static boolean hadSuccessfulEdit = false;\r
+\r
+    /**\r
+     * Allows any type of input into a text field, if a constraint is not\r
+     * supported by an underlying implementation this will be the default.\r
+     */\r
+    public static final int ANY = 0;\r
+\r
+    /**\r
+     * The user is allowed to enter an e-mail address.\r
+     */\r
+    public static final int EMAILADDR = 1;\r
+\r
+    /**\r
+     * The user is allowed to enter only an integer value.\r
+     */\r
+    public static final int NUMERIC = 2;\r
+\r
+    /**\r
+     * The user is allowed to enter a phone number.\r
+     */\r
+    public static final int PHONENUMBER = 3;\r
+\r
+    /**\r
+     * The user is allowed to enter a URL.\r
+     */\r
+    public static final int URL = 4;\r
+\r
+    /**\r
+     * The user is allowed to enter numeric values with optional decimal\r
+     * fractions, for example "-123", "0.123", or ".5".\r
+     */\r
+    public static final int DECIMAL = 5;\r
+\r
+    /**\r
+     * Indicates that the text entered is confidential data that should be\r
+     * obscured whenever possible.\r
+     */\r
+    public static final int PASSWORD = 0x10000;\r
+\r
+    /**\r
+     * Indicates that editing is currently disallowed.\r
+     */\r
+    public static final int UNEDITABLE = 0x20000;\r
+\r
+    /**\r
+     * Indicates that the text entered is sensitive data that the implementation\r
+     * must never store into a dictionary or table for use in predictive,\r
+     * auto-completing, or other accelerated input schemes.\r
+     */\r
+    public static final int SENSITIVE = 0x40000;\r
+\r
+    /**\r
+     * Indicates that the text entered does not consist of words that are likely\r
+     * to be found in dictionaries typically used by predictive input schemes.\r
+     */\r
+    public static final int NON_PREDICTIVE = 0x80000;\r
+\r
+    /**\r
+     * This flag is a hint to the implementation that during text editing, the\r
+     * initial letter of each word should be capitalized.\r
+     */\r
+    public static final int INITIAL_CAPS_WORD = 0x100000;\r
+\r
+    /**\r
+     * This flag is a hint to the implementation that during text editing, the\r
+     * initial letter of each sentence should be capitalized.\r
+     */\r
+    public static final int INITIAL_CAPS_SENTENCE = 0x200000;\r
+    //private int modifierFlag = 0x00000;\r
+\r
+    /**\r
+     * Input constraint which should be one of CONSTRAINT_ANY,\r
+     * CONSTRAINT_NUMERIC, CONSTRAINT_PHONENUMBER, CONSTRAINT_URL or\r
+     * CONSTRAINT_EMAIL\r
+     */\r
+    private int constraint = ANY;\r
+\r
+    private String text = "";\r
+\r
+    private boolean editable = true;\r
+\r
+    private int maxSize = defaultMaxSize; //maximum size (number of characters) that can be stored in this TextField.\r
+\r
+    private int rows = 1;\r
+\r
+    private int columns = 1;\r
+\r
+    // problematic  maxSize = 20; //maximum size (number of characters) that can be stored in this TextField.\r
+\r
+    private static String id = "TextArea";\r
+\r
+    private Vector rowStrings;\r
+    private int widthForRowCalculations = -1;\r
+\r
+    private int rowsGap = 2;\r
+\r
+    private boolean triggerClose;\r
+\r
+    private Vector actionListeners = null;\r
+\r
+    /**\r
+     * Indicates that the text area should "grow" in height based on the content\r
+     * beyond the limits indicate by the rows variable\r
+     */\r
+    private boolean growByContent = true;\r
+\r
+    private int cursorRow = 0;\r
+    private int cursorColumn = 0;\r
+\r
+    private EditForm editForm;\r
+\r
+    /**\r
+     * Creates an area with the given text, maximum size, rows, columns and\r
+     * constrint\r
+     * \r
+     * @param text\r
+     *            the text to be displayed; if text is null, the empty string ""\r
+     *            will be displayed\r
+     * @param maxSize\r
+     *            text area maximum size\r
+     * @param rows\r
+     *            the number of rows\r
+     * @param columns\r
+     *            - the number of columns\r
+     * @param constraint\r
+     *            one of ANY, EMAILADDR, NUMERIC, PHONENUMBER, URL, DECIMAL it\r
+     *            can be bitwised or'd with one of PASSWORD, UNEDITABLE,\r
+     *            SENSITIVE, NON_PREDICTIVE, INITIAL_CAPS_SENTENCE,\r
+     *            INITIAL_CAPS_WORD. E.g. ANY | PASSWORD.\r
+     */\r
+    public EditableTextArea(EditForm form, TextArea ta) {\r
+        // FIXME\r
+        this(ta.getText(), ta.getMaxSize(), 2, ta.getColumns(), ta.getConstraint());\r
+        //this(ta.getText(), ta.getMaxSize(), ta.getRows(), ta.getColumns(), ta.getConstraint());\r
+        this.editForm = form;\r
+    }\r
+\r
+    private EditableTextArea(String text, int maxSize, int rows, int columns, int constraint) {\r
+        this.maxSize = maxSize;\r
+        setText(text);\r
+        setConstraint(constraint);\r
+        this.rows = rows;\r
+        this.columns = columns;\r
+        setSmoothScrolling(false);\r
+        setHandlesInput(true);\r
+\r
+        //            Style style = new Style();\r
+        //            style.setBgColor(0xFFFFFF, false);\r
+        //            style.setFgColor(0x000000, false);\r
+        //            style.setBgSelectionColor(0xFFFFFF, false);\r
+        //            style.setFgSelectionColor(0x000000, false);\r
+        //            style.setFont(Font.getDefaultFont(), false);\r
+        //            setStyle(style);\r
+    }\r
+\r
+    //        public boolean animate() {\r
+    //            return true;\r
+    //        }\r
+\r
+    /**\r
+     * Sets the constraint\r
+     * \r
+     * @param constraint\r
+     *            one of ANY, EMAILADDR, NUMERIC, PHONENUMBER, URL, DECIMAL it\r
+     *            can be bitwised or'd with one of PASSWORD, UNEDITABLE,\r
+     *            SENSITIVE, NON_PREDICTIVE, INITIAL_CAPS_SENTENCE,\r
+     *            INITIAL_CAPS_WORD. E.g. ANY | PASSWORD.\r
+     */\r
+    public void setConstraint(int constraint) {\r
+        this.constraint = constraint;\r
+    }\r
+\r
+    /**\r
+     * Returns the editing constraint value\r
+     * \r
+     * @return the editing constraint value\r
+     * @see #setConstraint\r
+     */\r
+    public int getConstraint() {\r
+        return constraint;\r
+    }\r
+\r
+    /**\r
+     * Sets the text within this text area\r
+     * \r
+     * @param t\r
+     *            new value for the text area\r
+     */\r
+    public void setText(String t) {\r
+        setTextInternal(t);\r
+        repaint();\r
+    }\r
+\r
+    private void setTextInternal(String t) {\r
+        this.text = (t != null) ? t : "";\r
+        setShouldCalcPreferredSize(true);\r
+        if (maxSize < text.length()) {\r
+            maxSize = text.length() + 1;\r
+        }\r
+        // special case to make the text field really fast...\r
+        rowStrings = null; //zero the vector inorder to initialize it on the next paint\r
+    }\r
+\r
+    /**\r
+     * Returns the text in the text area\r
+     * \r
+     * @return the text in the text area\r
+     */\r
+    public String getText() {\r
+        return text;\r
+    }\r
+\r
+    /**\r
+     * Returns true if this area is editable\r
+     * \r
+     * @return true if this area is editable\r
+     */\r
+    public boolean isEditable() {\r
+        return editable;\r
+    }\r
+\r
+    /**\r
+     * Sets this text area to be editable or readonly\r
+     * \r
+     * @param b\r
+     *            true is text are is editable; otherwise false\r
+     */\r
+    public void setEditable(boolean b) {\r
+        editable = b;\r
+    }\r
+\r
+    /**\r
+     * Returns the maximum size for the text area\r
+     * \r
+     * @return the maximum size for the text area\r
+     */\r
+    public int getMaxSize() {\r
+        return maxSize;\r
+    }\r
+\r
+    /**\r
+     * Sets the maximum size of the text area\r
+     * \r
+     * @param maxSize\r
+     *            the maximum size of the text area\r
+     */\r
+    public void setMaxSize(int maxSize) {\r
+        this.maxSize = maxSize;\r
+    }\r
+\r
+    private int getCursorPosition(int row, int column) {\r
+        Vector rowsV = getRowStrings();\r
+        int index = 0;\r
+        for (int i = 0; i <= row; i++) {\r
+            if (i == cursorRow) {\r
+                index += cursorColumn;\r
+            } else {\r
+                String s = (String) rowsV.elementAt(i);\r
+                index += s.length();\r
+            }\r
+        }\r
+        return index;\r
+    }\r
+\r
+    private void setCursorPosition(int position) {\r
+        Vector rowsV = getRowStrings();\r
+        int index = 0;\r
+        for (int i = 0; i < rowsV.size(); i++) {\r
+            int rowSize = ((String) rowsV.elementAt(i)).length();\r
+            if ((position >= index) && (position < (index + rowSize))) {\r
+                cursorRow = i;\r
+                cursorColumn = position - index;\r
+                break;\r
+            } else {\r
+                index += rowSize;\r
+            }\r
+        }\r
+\r
+    }\r
+\r
+    public void insertChar(char c) {\r
+        int position = getCursorPosition(cursorRow, cursorColumn);\r
+        insertChar(c, position);\r
+    }\r
+\r
+    private void insertChar(char c, int position) {\r
+        String newText = text.substring(0, position) + c + text.substring(position, text.length());\r
+        setTextInternal(newText);\r
+        setCursorPosition(position + 1);\r
+    }\r
+\r
+    public boolean deleteChar() {\r
+        int position = getCursorPosition(cursorRow, cursorColumn);\r
+        return deleteChar(position);\r
+    }\r
+\r
+    private boolean deleteChar(int position) {\r
+        if (text.length() > 0) {\r
+            System.out.println("text.charAt(position)=" + text.charAt(position));\r
+            String newText = text.substring(0, position) + text.substring(position + 1, text.length());\r
+            setTextInternal(newText);\r
+            return true;\r
+        }\r
+        return false;\r
+    }\r
+\r
+    public boolean deletePreviousChar() {\r
+        int position = getCursorPosition(cursorRow, cursorColumn);\r
+        if (position > 0) {\r
+            setCursorPosition(position - 1);\r
+            deleteChar(position - 1);\r
+            return true;\r
+        }\r
+        return false;\r
+    }\r
+\r
+    public void moveCaret(int action) {\r
+\r
+        //scroll the TextArea\r
+        Rectangle rect = new Rectangle(getScrollX(), getScrollY(), getWidth(), getHeight());\r
+        Font textFont = getStyle().getFont();\r
+\r
+        // TODO Remove\r
+        //System.out.println("cursorRow =" + cursorRow + " cursorColumn=" + cursorColumn + "rows=" + rows + " column=" + columns);\r
+\r
+        if (action == Display.GAME_DOWN) {\r
+            cursorRow++;\r
+            if ((getScrollY() + getHeight()) < (rowsGap + getStyle().getFont().getHeight()) * getLines()) {\r
+                rect.setY(rect.getY() + textFont.getHeight() + rowsGap);\r
+                scrollRectToVisible(rect, this);\r
+            } else {\r
+                setHandlesInput(false);\r
+            }\r
+        } else if (action == Display.GAME_UP) {\r
+            cursorRow--;\r
+            if (getScrollY() > 0) {\r
+                rect.setY(Math.max(0, rect.getY() - textFont.getHeight() - rowsGap));\r
+                scrollRectToVisible(rect, this);\r
+            } else {\r
+                setHandlesInput(false);\r
+            }\r
+        } else if (action == Display.GAME_LEFT) {\r
+            cursorColumn--;\r
+        } else if (action == Display.GAME_RIGHT) {\r
+            cursorColumn++;\r
+        }\r
+\r
+        // Check bounds\r
+        if (cursorRow < 0) {\r
+            cursorRow = 0;\r
+        }\r
+        int nRows = getRowStrings().size();\r
+        if (nRows > 0) {\r
+            if (cursorRow > nRows - 1) {\r
+                cursorRow = nRows - 1;\r
+            }\r
+            if (cursorColumn < 0) {\r
+                cursorColumn = 0;\r
+            }\r
+            String s = getTextAt(cursorRow);\r
+            if (cursorColumn > s.length() - 1) {\r
+                cursorColumn = s.length() - 1;\r
+            }\r
+            int position = getCursorPosition(cursorRow, cursorColumn);\r
+            System.out.println("position=" + position + " text.charAt(position)=" + text.charAt(position) + " line.charAt(cursorColumn)="\r
+                    + s.charAt(cursorColumn));\r
+            System.out.println("s.length()=" + s.length() + " cursor position=" + getCursorPosition(cursorRow, cursorColumn) + " c="\r
+                    + text.charAt(getCursorPosition(cursorRow, cursorColumn)));\r
+        }\r
+\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void keyPressed(int keyCode) {\r
+        super.keyPressed(keyCode);\r
+\r
+        if (Log.TRACE_ENABLED)\r
+            System.out.println("[DEBUG] EditForm.EditableTextArea.keyPressed(): keyCode=" + keyCode);\r
+\r
+        // Check if the key code is an action\r
+        int action = Display.getInstance().getGameAction(keyCode);\r
+        if (action == Display.GAME_FIRE) {\r
+            insertChar('\n');\r
+            repaint();\r
+            return;\r
+        } else if (action == Display.GAME_DOWN || action == Display.GAME_LEFT || action == Display.GAME_RIGHT || action == Display.GAME_UP) {\r
+            moveCaret(action);\r
+            repaint();\r
+            return;\r
+        }\r
+\r
+        // Check if the keyCode is a system key or a a visible character\r
+        int systemKeyCode = Display.getInstance().getVirtualImplementation().getEventMapper().getSystemKey(keyCode);\r
+        if (systemKeyCode == VirtualImplementation.SYSTEM_KEY_DELETE) {\r
+            if (deleteChar()) {\r
+                repaint();\r
+            }\r
+        } else if (systemKeyCode == VirtualImplementation.SYSTEM_KEY_BACKSPACE) {\r
+            if (deletePreviousChar()) {\r
+                repaint();\r
+            }\r
+        } else { // Insert\r
+            char lastKeyChar = editForm.implementation.getLastKeyChar();\r
+            if (lastKeyChar != KeyConstants.CHAR_UNDEFINED) {\r
+                insertChar(lastKeyChar);\r
+            }\r
+            repaint();\r
+        }\r
+\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    protected void fireClicked() {\r
+        onClick();\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    protected boolean isSelectableInteraction() {\r
+        return editable;\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void keyReleased(int keyCode) {\r
+        //        int action = com.sun.lwuit.Display.getInstance().getGameAction(keyCode);\r
+        //        if (isEditable()) {\r
+        //            // this works around a bug where fire is also a softkey on devices such as newer Nokia\r
+        //            // series 40's\r
+        //            if (triggerClose && action == Display.GAME_FIRE) {\r
+        //                triggerClose = false;\r
+        //                onClick();\r
+        //                return;\r
+        //            }\r
+        //        }\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public boolean isScrollableY() {\r
+        return (rowsGap + getStyle().getFont().getHeight()) * getLines() > getHeight();\r
+    }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    protected void paintScrollbarY(Graphics g) {\r
+        int prefH = (rowsGap + getStyle().getFont().getHeight()) * getLines();\r
+        float offset = ((float) getScrollY()) / ((float) prefH);\r
+        float block = ((float) getHeight()) / ((float) prefH);\r
+        UIManager.getInstance().getLookAndFeel().drawVerticalScroll(g, this, offset, block);\r
+    }\r
+\r
+    void onClick() {\r
+        //            if (isEditable()) {\r
+        //                editString();\r
+        //            }\r
+    }\r
+\r
+    //        void editString() {\r
+    //            if (autoDegradeMaxSize && (!hadSuccessfulEdit) && (maxSize > 1024)) {\r
+    //                try {\r
+    //                    Display.getInstance().editString(this, getMaxSize(), getConstraint(), getText());\r
+    //                } catch (IllegalArgumentException err) {\r
+    //                    maxSize -= 1024;\r
+    //                    setDefaultMaxSize(maxSize);\r
+    //                    editString();\r
+    //                }\r
+    //            } else {\r
+    //                Display.getInstance().editString(this, getMaxSize(), getConstraint(), getText());\r
+    //            }\r
+    //        }\r
+\r
+    /**\r
+     * @inheritDoc\r
+     */\r
+    public void pointerReleased(int x, int y) {\r
+        super.pointerReleased(x, y);\r
+        if (isEditable()) {\r
+            onClick();\r
<