Component.java
上传用户:haobig99
上传日期:2022-06-15
资源大小:369k
文件大小:85k
源码类别:

J2ME

开发平台:

Java

  1. /*
  2.  * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
  3.  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4.  *
  5.  * This code is free software; you can redistribute it and/or modify it
  6.  * under the terms of the GNU General Public License version 2 only, as
  7.  * published by the Free Software Foundation.  Sun designates this
  8.  * particular file as subject to the "Classpath" exception as provided
  9.  * by Sun in the LICENSE file that accompanied this code.
  10.  *
  11.  * This code is distributed in the hope that it will be useful, but WITHOUT
  12.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13.  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14.  * version 2 for more details (a copy is included in the LICENSE file that
  15.  * accompanied this code).
  16.  *
  17.  * You should have received a copy of the GNU General Public License version
  18.  * 2 along with this work; if not, write to the Free Software Foundation,
  19.  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20.  *
  21.  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22.  * CA 95054 USA or visit www.sun.com if you need additional information or
  23.  * have any questions.
  24.  */
  25. package com.sun.lwuit;
  26. import com.sun.lwuit.util.EventDispatcher;
  27. import com.sun.lwuit.geom.Rectangle;
  28. import com.sun.lwuit.geom.Dimension;
  29. import com.sun.lwuit.plaf.Style;
  30. import com.sun.lwuit.animations.Animation;
  31. import com.sun.lwuit.animations.Motion;
  32. import com.sun.lwuit.events.FocusListener;
  33. import com.sun.lwuit.events.StyleListener;
  34. import com.sun.lwuit.plaf.Border;
  35. import com.sun.lwuit.plaf.LookAndFeel;
  36. import com.sun.lwuit.plaf.UIManager;
  37. import java.lang.ref.WeakReference;
  38. import java.util.Hashtable;
  39. /**
  40.  * Base class for all the widgets in the toolkit using the composite pattern in 
  41.  * a similar way to the AWT Container/Component relationship. All components are
  42.  * potentially animated (need to be registered in {@link Display}). 
  43.  * 
  44.  * @author Chen Fishbein
  45.  */
  46. public class Component implements Animation, StyleListener {
  47.     private String selectText = UIManager.getInstance().localize("select", "Select");
  48.     /**
  49.      * Allows us to determine which component will receive focus next when traversing 
  50.      * with the down key
  51.      */
  52.     private Component nextFocusDown;
  53.     private Component nextFocusUp;
  54.     /**
  55.      * Indicates whether component is enabled or disabled
  56.      */
  57.     private boolean enabled = true;
  58.     /**
  59.      * Allows us to determine which component will receive focus next when traversing 
  60.      * with the right key
  61.      */
  62.     private Component nextFocusRight;
  63.     private Component nextFocusLeft;
  64.     /**
  65.      * Indicates whether the component should "trigger" tactile touch when pressed by the user
  66.      * in a touch screen UI.
  67.      */
  68.     private boolean tactileTouch;
  69.     /**
  70.      * Baseline resize behavior constant used to properly align components. 
  71.      * Indicates as the size of the component
  72.      * changes the baseline remains a fixed distance from the top of the
  73.      * component.
  74.      * @see #getBaselineResizeBehavior
  75.      */
  76.     public static final int BRB_CONSTANT_ASCENT = 1;
  77.     /**
  78.      * Baseline resize behavior constant used to properly align components. Indicates as the size of the component
  79.      * changes the baseline remains a fixed distance from the bottom of the 
  80.      * component.
  81.      * @see #getBaselineResizeBehavior
  82.      */
  83.     public static final int BRB_CONSTANT_DESCENT = 2;
  84.     /**
  85.      * Baseline resize behavior constant used to properly align components. Indicates as the size of the component
  86.      * changes the baseline remains a fixed distance from the center of the
  87.      * component.
  88.      * @see #getBaselineResizeBehavior
  89.      */
  90.     public static final int BRB_CENTER_OFFSET = 3;
  91.     /**
  92.      * Baseline resize behavior constant used to properly align components. Indicates as the size of the component
  93.      * changes the baseline can not be determined using one of the other
  94.      * constants.
  95.      * @see #getBaselineResizeBehavior
  96.      */
  97.     public static final int BRB_OTHER = 4;
  98.     private boolean visible = true;
  99.     /**
  100.      * Used as an optimization to mark that this component is currently being
  101.      * used as a cell renderer
  102.      */
  103.     private boolean cellRenderer;
  104.     private Rectangle bounds = new Rectangle(0, 0, new Dimension(0, 0));
  105.     private WeakReference painterBounds;
  106.     private int scrollX;
  107.     private int scrollY;
  108.     private boolean sizeRequestedByUser = false;
  109.     private Dimension preferredSize;
  110.     private boolean scrollSizeRequestedByUser = false;
  111.     private Dimension scrollSize;
  112.     private Style unSelectedStyle;
  113.     private Style selectedStyle;
  114.     private Container parent;
  115.     private boolean focused = false;
  116.     private boolean focusPainted = true;
  117.     private EventDispatcher focusListeners = new EventDispatcher();
  118.     private boolean handlesInput = false;
  119.     private boolean shouldCalcPreferredSize = true;
  120.     private boolean shouldCalcScrollSize = true;
  121.     private boolean focusable = true;
  122.     private boolean isScrollVisible = true;
  123.     /**
  124.      * Indicates that moving through the component should work as an animation
  125.      */
  126.     private boolean smoothScrolling;
  127.     /**
  128.      * Animation speed in milliseconds allowing a developer to slow down or accelerate
  129.      * the smooth animation mode
  130.      */
  131.     private int animationSpeed;
  132.     private Motion animationMotion;
  133.     private Motion draggedMotion;
  134.     /**
  135.      * Allows us to flag a drag operation in action thus preventing the mouse pointer
  136.      * release event from occurring.
  137.      */
  138.     private boolean dragActivated;
  139.     private int initialScrollY = -1;
  140.     private int destScrollY = -1;
  141.     private int lastScrollY;
  142.     private int lastScrollX;
  143.     
  144.     /**
  145.      * Indicates if the component is in the initialized state, a component is initialized
  146.      * when its initComponent() method was invoked. The initMethod is invoked before showing the
  147.      * component to the user.
  148.      */
  149.     private boolean initialized;
  150.     /**
  151.      * Indicates a Component center alignment
  152.      */
  153.     public static final int CENTER = 4;
  154.     /** 
  155.      * Box-orientation constant used to specify the top of a box.
  156.      */
  157.     public static final int TOP = 0;
  158.     /** 
  159.      * Box-orientation constant used to specify the left side of a box.
  160.      */
  161.     public static final int LEFT = 1;
  162.     /** 
  163.      * Box-orientation constant used to specify the bottom of a box.
  164.      */
  165.     public static final int BOTTOM = 2;
  166.     /** 
  167.      * Box-orientation constant used to specify the right side of a box.
  168.      */
  169.     public static final int RIGHT = 3;
  170.     private Hashtable clientProperties;
  171.     private Rectangle dirtyRegion = null;
  172.     private Object dirtyRegionLock = new Object();
  173.     private Label componentLabel;
  174.     private String id;
  175.     /**
  176.      * Is the component a bidi RTL component
  177.      */
  178.     private boolean rtl;
  179.     /** 
  180.      * Creates a new instance of Component 
  181.      */
  182.     protected Component() {
  183.         LookAndFeel laf = UIManager.getInstance().getLookAndFeel();
  184.         animationSpeed = laf.getDefaultSmoothScrollingSpeed();
  185.         rtl = laf.isRTL();
  186.         tactileTouch = isFocusable();
  187.     }
  188.     private void initStyle() {
  189.         unSelectedStyle = UIManager.getInstance().getComponentStyle(getUIID());
  190.         if (unSelectedStyle != null) {
  191.             unSelectedStyle.addStyleListener(this);
  192.             if (unSelectedStyle.getBgPainter() == null) {
  193.                 unSelectedStyle.setBgPainter(new BGPainter());
  194.             }
  195.         }
  196.     }
  197.     /**
  198.      * Returns the current component x location relatively to its parent container
  199.      * 
  200.      * @return the current x coordinate of the components origin
  201.      */
  202.     public int getX() {
  203.         return bounds.getX();
  204.     }
  205.     /**
  206.      * Returns the component y location relatively to its parent container
  207.      * 
  208.      * @return the current y coordinate of the components origin
  209.      */
  210.     public int getY() {
  211.         return bounds.getY();
  212.     }
  213.     /**
  214.      * Returns whether the component is visible or not
  215.      * 
  216.      * @return true if component is visible; otherwise false 
  217.      */
  218.     public boolean isVisible() {
  219.         return visible;
  220.     }
  221.     /**
  222.      * Client properties allow the association of meta-data with a component, this
  223.      * is useful for some applications that construct GUI's on the fly and need
  224.      * to track the connection between the UI and the data. 
  225.      * 
  226.      * @param key the key used for putClientProperty
  227.      * @return the value set to putClientProperty or null if no value is set to the property
  228.      */
  229.     public Object getClientProperty(String key) {
  230.         if (clientProperties == null) {
  231.             return null;
  232.         }
  233.         return clientProperties.get(key);
  234.     }
  235.     /**
  236.      * Client properties allow the association of meta-data with a component, this
  237.      * is useful for some applications that construct GUI's on the fly and need
  238.      * to track the connection between the UI and the data. Setting the value to
  239.      * null will remove the client property from the component.
  240.      * 
  241.      * @param key arbitrary key for the property
  242.      * @param value the value assigned to the given client property
  243.      */
  244.     public void putClientProperty(String key, Object value) {
  245.         if (clientProperties == null) {
  246.             if (value == null) {
  247.                 return;
  248.             }
  249.             clientProperties = new Hashtable();
  250.         }
  251.         if (value == null) {
  252.             clientProperties.remove(key);
  253.             if (clientProperties.size() == 0) {
  254.                 clientProperties = null;
  255.             }
  256.         } else {
  257.             clientProperties.put(key, value);
  258.         }
  259.     }
  260.     /**
  261.      * gets the Component dirty region
  262.      * 
  263.      * @return
  264.      */
  265.     public final Rectangle getDirtyRegion() {
  266.         return dirtyRegion;
  267.     }
  268.     /**
  269.      * sets the Component dirty region
  270.      * 
  271.      * @param dirty
  272.      */
  273.     public final void setDirtyRegion(Rectangle dirty) {
  274.         synchronized (dirtyRegionLock) {
  275.             this.dirtyRegion = dirty;
  276.         }
  277.     }
  278.     /**
  279.      * Toggles visibility of the component
  280.      * 
  281.      * @param visible true if component is visible; otherwise false 
  282.      */
  283.     public void setVisible(boolean visible) {
  284.         this.visible = visible;
  285.     }
  286.     /**
  287.      * Returns the component width
  288.      * 
  289.      * @return the component width
  290.      */
  291.     public int getWidth() {
  292.         return bounds.getSize().getWidth();
  293.     }
  294.     /**
  295.      * Returns the component height
  296.      * 
  297.      * @return the component height
  298.      */
  299.     public int getHeight() {
  300.         return bounds.getSize().getHeight();
  301.     }
  302.     /**
  303.      * Sets the Component x location relative to the parent container, this method
  304.      * is exposed for the purpose of external layout managers and should not be invoked
  305.      * directly.
  306.      * 
  307.      * @param x the current x coordinate of the components origin
  308.      */
  309.     public void setX(int x) {
  310.         bounds.setX(x);
  311.     }
  312.     /**
  313.      * Sets the Component y location relative to the parent container, this method
  314.      * is exposed for the purpose of external layout managers and should not be invoked
  315.      * directly.
  316.      * 
  317.      * @param y the current y coordinate of the components origin
  318.      */
  319.     public void setY(int y) {
  320.         bounds.setY(y);
  321.     }
  322.     /**
  323.      * The baseline for the component text according to which it should be aligned
  324.      * with other components for best visual look.
  325.      * 
  326.      * 
  327.      * @param width the component width
  328.      * @param height the component height
  329.      * @return baseline value from the top of the component
  330.      */
  331.     public int getBaseline(int width, int height) {
  332.         return height - getStyle().getPadding(false, BOTTOM);
  333.     }
  334.     /**
  335.      * Returns a constant indicating how the baseline varies with the size
  336.      * of the component.
  337.      *
  338.      * @return one of BRB_CONSTANT_ASCENT, BRB_CONSTANT_DESCENT,
  339.      *         BRB_CENTER_OFFSET or BRB_OTHER
  340.      */
  341.     public int getBaselineResizeBehavior() {
  342.         return BRB_OTHER;
  343.     }
  344.     /**
  345.      * Sets the Component Preferred Size, there is no guarantee the Component will 
  346.      * be sized at its Preferred Size. The final size of the component may be
  347.      * smaller than its preferred size or even larger than the size.<br>
  348.      * The Layout manager can take this value into consideration, but there is
  349.      * no guarantee or requirement.
  350.      * 
  351.      * @param d the component dimension
  352.      */
  353.     public void setPreferredSize(Dimension d) {
  354.         Dimension dim = preferredSize();
  355.         dim.setWidth(d.getWidth());
  356.         dim.setHeight(d.getHeight());
  357.         sizeRequestedByUser = true;
  358.     }
  359.     /**
  360.      * Returns the Component Preferred Size, there is no guarantee the Component will 
  361.      * be sized at its Preferred Size. The final size of the component may be
  362.      * smaller than its preferred size or even larger than the size.<br>
  363.      * The Layout manager can take this value into consideration, but there is
  364.      * no guarantee or requirement.
  365.      * 
  366.      * @return the component preferred size
  367.      */
  368.     public Dimension getPreferredSize() {
  369.         return preferredSize();
  370.     }
  371.     Dimension getPreferredSizeWithMargin() {
  372.         Dimension d = preferredSize();
  373.         Style s = getStyle();
  374.         return new Dimension(d.getWidth() +s.getMargin(LEFT) + s.getMargin(RIGHT), d.getHeight() + s.getMargin(TOP) + s.getMargin(BOTTOM));
  375.     }
  376.     /**
  377.      * Returns the Components dimension in scrolling, this is very similar to the
  378.      * preferred size aspect only it represents actual scrolling limits.
  379.      * 
  380.      * @return the component actual size with all scrolling
  381.      */
  382.     public Dimension getScrollDimension() {
  383.         if (!scrollSizeRequestedByUser && (scrollSize == null || shouldCalcScrollSize)) {
  384.             scrollSize = calcScrollSize();
  385.             shouldCalcScrollSize = false;
  386.         }
  387.         return scrollSize;
  388.     }
  389.     /**
  390.      * Method that can be overriden to represent the actual size of the component 
  391.      * when it differs from the desireable size for the viewport
  392.      * 
  393.      * @return scroll size, by default this is the same as the preferred size
  394.      */
  395.     protected Dimension calcScrollSize() {
  396.         return calcPreferredSize();
  397.     }
  398.     /**
  399.      * Set the size for the scroll area
  400.      * 
  401.      * @param d dimension of the scroll area
  402.      */
  403.     public void setScrollSize(Dimension d) {
  404.         scrollSize = d;
  405.         scrollSizeRequestedByUser = true;
  406.     }
  407.     /**
  408.      * Helper method to set the preferred width of the component.
  409.      * 
  410.      * @param preferredW the preferred width of the component
  411.      * @see #setPreferredSize
  412.      */
  413.     public void setPreferredW(int preferredW) {
  414.         setPreferredSize(new Dimension(preferredW, getPreferredH()));
  415.     }
  416.     /**
  417.      * Helper method to set the preferred height of the component.
  418.      * 
  419.      * @param preferredH the preferred height of the component
  420.      * @see #setPreferredSize
  421.      */
  422.     public void setPreferredH(int preferredH) {
  423.         setPreferredSize(new Dimension(getPreferredW(), preferredH));
  424.     }
  425.     /**
  426.      * Helper method to retrieve the preferred width of the component.
  427.      * 
  428.      * @return preferred width of the component
  429.      * @see #getPreferredSize
  430.      */
  431.     public int getPreferredW() {
  432.         return getPreferredSize().getWidth();
  433.     }
  434.     /**
  435.      * Helper method to retrieve the preferred height of the component.
  436.      * 
  437.      * @return preferred height of the component
  438.      * @see #getPreferredSize
  439.      */
  440.     public int getPreferredH() {
  441.         return getPreferredSize().getHeight();
  442.     }
  443.     /**
  444.      * Sets the Component width, this method is exposed for the purpose of 
  445.      * external layout managers and should not be invoked directly.<br>
  446.      * If a user wishes to effect the component size setPreferredSize should
  447.      * be used.
  448.      * 
  449.      * @param width the width of the component
  450.      * @see #setPreferredSize
  451.      */
  452.     public void setWidth(int width) {
  453.         bounds.getSize().setWidth(width);
  454.     }
  455.     /**
  456.      * Sets the Component height, this method is exposed for the purpose of 
  457.      * external layout managers and should not be invoked directly.<br>
  458.      * If a user wishes to effect the component size setPreferredSize should
  459.      * be used.
  460.      * 
  461.      * @param height the height of the component
  462.      * @see #setPreferredSize
  463.      */
  464.     public void setHeight(int height) {
  465.         bounds.getSize().setHeight(height);
  466.     }
  467.     /**
  468.      * Sets the Component size, this method is exposed for the purpose of 
  469.      * external layout managers and should not be invoked directly.<br>
  470.      * If a user wishes to effect the component size setPreferredSize should
  471.      * be used.
  472.      * 
  473.      * @param d the component dimension
  474.      * @see #setPreferredSize
  475.      */
  476.     public void setSize(Dimension d) {
  477.         Dimension d2 = bounds.getSize();
  478.         d2.setWidth(d.getWidth());
  479.         d2.setHeight(d.getHeight());
  480.     }
  481.     /**
  482.      * Unique identifier for a component.
  483.      * This id is used to retrieve a suitable Style.
  484.      * 
  485.      * @return unique string identifying this component for the style sheet
  486.      */
  487.     public String getUIID() {
  488.         return id;
  489.     }
  490.     /**
  491.      * This method sets the Component the Unique identifier.
  492.      * This method should be used before a component has been initialized
  493.      * 
  494.      * @param id
  495.      */
  496.     public void setUIID(String id) {
  497.         String tmpId = this.id;
  498.         this.id = id;
  499.         if (tmpId != null && !tmpId.equals(id)) {
  500.             initStyle();
  501.         }
  502.         selectedStyle = null;
  503.     }
  504.     /**
  505.      * Returns the container in which this component is contained
  506.      * 
  507.      * @return the parent container in which this component is contained
  508.      */
  509.     public Container getParent() {
  510.         return parent;
  511.     }
  512.     /**
  513.      * Sets the Component Parent.
  514.      * This method should not be called by the user.
  515.      * 
  516.      * @param parent the parent container
  517.      */
  518.     void setParent(Container parent) {
  519.         this.parent = parent;
  520.     }
  521.     /**
  522.      * Registers interest in receiving callbacks for focus gained events, a focus event 
  523.      * is invoked when the component accepts the focus. A special case exists for the
  524.      * Form which sends a focus even for every selection within the form.
  525.      * 
  526.      * @param l listener interface implementing the observable pattern
  527.      */
  528.     public void addFocusListener(FocusListener l) {
  529.         focusListeners.addListener(l);
  530.     }
  531.     /**
  532.      * Deregisters interest in receiving callbacks for focus gained events
  533.      * 
  534.      * @param l listener interface implementing the observable pattern
  535.      */
  536.     public void removeFocusListener(FocusListener l) {
  537.         focusListeners.removeListener(l);
  538.     }
  539.     /**
  540.      * When working in 3 softbutton mode "fire" key (center softbutton) is sent to this method
  541.      * in order to allow 3 button devices to work properly. When overriding this method
  542.      * you should also override isSelectableInteraction to indicate that a command is placed
  543.      * appropriately on top of the fire key for 3 soft button phones. 
  544.      */
  545.     protected void fireClicked() {
  546.     }
  547.     /**
  548.      * This method allows a component to indicate that it is interested in an "implicit" select
  549.      * command to appear in the "fire" button when 3 softbuttons are defined in a device.
  550.      * 
  551.      * @return true if this is a selectable interaction
  552.      */
  553.     protected boolean isSelectableInteraction() {
  554.         return false;
  555.     }
  556.     /**
  557.      * Fired when component gains focus
  558.      */
  559.     void fireFocusGained() {
  560.         fireFocusGained(this);
  561.     }
  562.     /**
  563.      * Fired when component lost focus
  564.      */
  565.     void fireFocusLost() {
  566.         fireFocusLost(this);
  567.     }
  568.     /**
  569.      * Fired when component gains focus
  570.      */
  571.     void fireFocusGained(Component cmp) {
  572.         if (cmp.isCellRenderer()) {
  573.             return;
  574.         }
  575.         focusListeners.fireFocus(cmp);
  576.         focusGainedInternal();
  577.         focusGained();
  578.         if (isSelectableInteraction()) {
  579.             Form f = getComponentForm();
  580.             if (f != null) {
  581.                 f.addSelectCommand(getSelectCommandText());
  582.             }
  583.         }
  584.     }
  585.     /**
  586.      * Allows determining the text for the select command used in the 3rd softbutton
  587.      * mode.
  588.      *
  589.      * @param selectText text for the interaction with the softkey
  590.      */
  591.     public void setSelectCommandText(String selectText) {
  592.         this.selectText = selectText;
  593.     }
  594.     /**
  595.      * Allows determining the text for the select command used in the 3rd softbutton
  596.      * mode.
  597.      *
  598.      * @return text for the interaction with the softkey
  599.      */
  600.     public String getSelectCommandText() {
  601.         return selectText;
  602.     }
  603.     /**
  604.      * Fired when component lost focus
  605.      */
  606.     void fireFocusLost(Component cmp) {
  607.         if (cmp.isCellRenderer()) {
  608.             return;
  609.         }
  610.         if (isSelectableInteraction()) {
  611.             Form f = getComponentForm();
  612.             if (f != null) {
  613.                 f.removeSelectCommand();
  614.             }
  615.         }
  616.         focusListeners.fireFocus(cmp);
  617.         focusLostInternal();
  618.         focusLost();
  619.     }
  620.     /**
  621.      * This method allows us to detect an action event internally without 
  622.      * implementing the action listener interface.
  623.      */
  624.     void fireActionEvent() {
  625.     }
  626.     /**
  627.      * Allows us to indicate the label associated with this component thus providing
  628.      * visual feedback related for this component e.g. starting the ticker when 
  629.      * the component receives focus.
  630.      * 
  631.      * @param componentLabel a label associated with this component
  632.      */
  633.     public void setLabelForComponent(Label componentLabel) {
  634.         this.componentLabel = componentLabel;
  635.     }
  636.     /**
  637.      * Allows us to indicate the label associated with this component thus providing
  638.      * visual feedback related for this component e.g. starting the ticker when
  639.      * the component receives focus.
  640.      *
  641.      * @return the label associated with this component
  642.      */
  643.     public Label getLabelForComponent() {
  644.         return componentLabel;
  645.     }
  646.     /**
  647.      * This method is useful since it is not a part of the public API yet
  648.      * allows a component within this package to observe focus events
  649.      * without implementing a public interface or creating a new class
  650.      */
  651.     void focusGainedInternal() {
  652.         if (componentLabel != null && componentLabel.isTickerEnabled()) {
  653.             if (componentLabel.shouldTickerStart()) {
  654.                 componentLabel.startTicker(UIManager.getInstance().getLookAndFeel().getTickerSpeed(), true);
  655.             }
  656.         }
  657.     }
  658.     /**
  659.      * Callback allowing a developer to track wheh the component gains focus
  660.      */
  661.     protected void focusGained() {
  662.     }
  663.     /**
  664.      * Callback allowing a developer to track wheh the component loses focus
  665.      */
  666.     protected void focusLost() {
  667.         if (componentLabel != null && componentLabel.isTickerEnabled() && componentLabel.isTickerRunning()) {
  668.             componentLabel.stopTicker();
  669.         }
  670.     }
  671.     /**
  672.      * This method is useful since it is not a part of the public API yet
  673.      * allows a component within this package to observe focus events
  674.      * without implementing a public interface or creating a new class
  675.      */
  676.     void focusLostInternal() {
  677.     }
  678.     /**
  679.      * This method paints all the parents Components Background.
  680.      * 
  681.      * @param g the graphics object
  682.      */
  683.     public void paintBackgrounds(Graphics g) {
  684.         drawPainters(g, this.getParent(), this, getAbsoluteX() + getScrollX(),
  685.                 getAbsoluteY() + getScrollY(),
  686.                 getWidth(), getHeight());
  687.     }
  688.     /**
  689.      * Returns the absolute X location based on the component hierarchy, this method
  690.      * calculates a location on the screen for the component rather than a relative
  691.      * location as returned by getX()
  692.      * 
  693.      * @return the absolute x location of the component
  694.      * @see #getX
  695.      */
  696.     public int getAbsoluteX() {
  697.         int x = getX() - getScrollX();
  698.         Container parent = getParent();
  699.         if (parent != null) {
  700.             x += parent.getAbsoluteX();
  701.         }
  702.         return x;
  703.     }
  704.     /**
  705.      * Returns the absolute Y location based on the component hierarchy, this method
  706.      * calculates a location on the screen for the component rather than a relative
  707.      * location as returned by getX()
  708.      * 
  709.      * @return the absolute y location of the component
  710.      * @see #getY
  711.      */
  712.     public int getAbsoluteY() {
  713.         int y = getY() - getScrollY();
  714.         Container parent = getParent();
  715.         if (parent != null) {
  716.             y += parent.getAbsoluteY();
  717.         }
  718.         return y;
  719.     }
  720.     /**
  721.      * This method performs the paint of the component internally including drawing
  722.      * the scrollbars and scrolling the component. This functionality is hidden
  723.      * from developers to prevent errors
  724.      * 
  725.      * @param g the component graphics
  726.      */
  727.     final void paintInternal(Graphics g) {
  728.         paintInternal(g, true);
  729.     }
  730.     final void paintInternal(Graphics g, boolean paintIntersects) {
  731.         if (!isVisible()) {
  732.             return;
  733.         }
  734.         int oX = g.getClipX();
  735.         int oY = g.getClipY();
  736.         int oWidth = g.getClipWidth();
  737.         int oHeight = g.getClipHeight();
  738.         if (bounds.intersects(oX, oY, oWidth, oHeight)) {
  739.             g.clipRect(getX(), getY(), getWidth(), getHeight());
  740.             paintBackground(g);
  741.             if (isScrollable()) {
  742.                 int scrollX = getScrollX();
  743.                 int scrollY = getScrollY();
  744.                 g.translate(-scrollX, -scrollY);
  745.                 paint(g);
  746.                 g.translate(scrollX, scrollY);
  747.                 if (isScrollVisible) {
  748.                     paintScrollbars(g);
  749.                 }
  750.             } else {
  751.                 paint(g);
  752.             }
  753.             if (isBorderPainted()) {
  754.                 paintBorder(g);
  755.             }
  756.             //paint all the intersecting Components above the Component
  757.             if (paintIntersects && parent != null) {
  758.                 paintIntersectingComponentsAbove(g);
  759.             }
  760.             g.setClip(oX, oY, oWidth, oHeight);
  761.         }
  762.     }
  763.     private void paintIntersectingComponentsAbove(Graphics g) {
  764.         Container parent = getParent();
  765.         Component component = this;
  766.         int tx = g.getTranslateX();
  767.         int ty = g.getTranslateY();
  768.         g.translate(-tx, -ty);
  769.         while (parent != null) {
  770.             g.translate(parent.getAbsoluteX() + parent.getScrollX(),
  771.                     parent.getAbsoluteY() + parent.getScrollY());
  772.             parent.paintIntersecting(g, component, getAbsoluteX() + getScrollX(),
  773.                     getAbsoluteY() + getScrollY(),
  774.                     getWidth(), getHeight(), true);
  775.             g.translate(-parent.getAbsoluteX() - parent.getScrollX(),
  776.                     -parent.getAbsoluteY() - parent.getScrollY());
  777.             component = parent;
  778.             parent = parent.getParent();
  779.         }
  780.         g.translate(tx, ty);
  781.     }
  782.     /**
  783.      * Paints the UI for the scrollbars on the component, this will be invoked only
  784.      * for scrollable components. This method invokes the appropriate X/Y versions
  785.      * to do all the work.
  786.      * 
  787.      * @param g the component graphics
  788.      */
  789.     protected void paintScrollbars(Graphics g) {
  790.         if (isScrollableX()) {
  791.             paintScrollbarX(g);
  792.         }
  793.         if (isScrollableY()) {
  794.             paintScrollbarY(g);
  795.         }
  796.     }
  797.     /**
  798.      * Paints the UI for the scrollbar on the X axis, this method allows component
  799.      * subclasses to customize the look of a scrollbar
  800.      * 
  801.      * @param g the component graphics
  802.      */
  803.     protected void paintScrollbarX(Graphics g) {
  804.         float scrollW = getScrollDimension().getWidth();
  805.         float block = ((float) getWidth()) / scrollW;
  806.         float offset;
  807.         if(getScrollX() + getWidth() == scrollW) {
  808.             // normalize the offset to avoid rounding errors to the bottom of the screen
  809.             offset = 1 - block;
  810.         } else {
  811.             offset = (((float) getScrollX() + getWidth()) / scrollW) - block;
  812.         }
  813.         UIManager.getInstance().getLookAndFeel().drawHorizontalScroll(g, this, offset, block);
  814.     }
  815.     /**
  816.      * Paints the UI for the scrollbar on the Y axis, this method allows component
  817.      * subclasses to customize the look of a scrollbar
  818.      * 
  819.      * @param g the component graphics
  820.      */
  821.     protected void paintScrollbarY(Graphics g) {
  822.         float scrollH = getScrollDimension().getHeight();
  823.         float block = ((float) getHeight()) / scrollH;
  824.         float offset;
  825.         if(getScrollY() + getHeight() == scrollH) {
  826.             // normalize the offset to avoid rounding errors to the bottom of the screen
  827.             offset = 1 - block;
  828.         } else {
  829.             offset = (((float) getScrollY() + getHeight()) / scrollH) - block;
  830.         }
  831.         UIManager.getInstance().getLookAndFeel().drawVerticalScroll(g, this, offset, block);
  832.     }
  833.     /**
  834.      * Paints this component as a root by going to all the parent components and
  835.      * setting the absolute translation based on coordinates and scroll status.
  836.      * Restores translation when the painting is finished.
  837.      * 
  838.      * @param g the graphics to paint this Component on
  839.      */
  840.     final public void paintComponent(Graphics g) {
  841.         paintComponent(g, true);
  842.     }
  843.     /**
  844.      * Paints this component as a root by going to all the parent components and
  845.      * setting the absolute translation based on coordinates and scroll status.
  846.      * Restores translation when the painting is finished.
  847.      * 
  848.      * @param g the graphics to paint this Component on
  849.      * @param background if true paints all parents background
  850.      */
  851.     final public void paintComponent(Graphics g, boolean background) {
  852.         int clipX = g.getClipX();
  853.         int clipY = g.getClipX();
  854.         int clipW = g.getClipWidth();
  855.         int clipH = g.getClipHeight();
  856.         Container parent = getParent();
  857.         int translateX = 0;
  858.         int translateY = 0;
  859.         while (parent != null) {
  860.             translateX += parent.getX();
  861.             translateY += parent.getY();
  862.             //if (parent.isScrollable()) {
  863.             if (parent.isScrollableX()) {
  864.                 translateX -= parent.getScrollX();
  865.             }
  866.             if (parent.isScrollableY()) {
  867.                 translateY -= parent.getScrollY();
  868.             }
  869.             // since scrollability can translate everything... we should clip based on the
  870.             // current scroll
  871.             int parentX = parent.getAbsoluteX() + parent.getScrollX();
  872.             if (isRTL()) {
  873.                 parentX += parent.getSideGap();
  874.             }
  875.             g.clipRect(parentX, parent.getAbsoluteY() + parent.getScrollY(),
  876.                     parent.getWidth() - parent.getSideGap(), parent.getHeight() - parent.getBottomGap());
  877.             parent = parent.getParent();
  878.         }
  879.         
  880.         g.clipRect(translateX + getX(), translateY + getY(), getWidth(), getHeight());
  881.         if (background) {
  882.             paintBackgrounds(g);
  883.         }
  884.         g.translate(translateX, translateY);
  885.         paintInternal(g);
  886.         g.translate(-translateX, -translateY);
  887.         Form parentForm = getComponentForm();
  888.         if (parentForm != null) {
  889.             Painter glass = parentForm.getGlassPane();
  890.             if (glass != null) {
  891.                 int tx = g.getTranslateX();
  892.                 int ty = g.getTranslateY();
  893.                 g.translate(-tx, -ty);
  894.                 glass.paint(g, parentForm.getBounds());
  895.                 g.translate(tx, ty);
  896.             }
  897.         }
  898.         g.setClip(clipX, clipY, clipW, clipH);
  899.     }
  900.     private void drawPainters(com.sun.lwuit.Graphics g, Component par, Component c,
  901.             int x, int y, int w, int h) {
  902.         if (par == null) {
  903.             return;
  904.         } else {
  905.             if (par.getStyle().getBgTransparency() != ((byte) 0xFF)) {
  906.                 drawPainters(g, par.getParent(), par, x, y, w, h);
  907.             }
  908.         }
  909.         if (!par.isVisible()) {
  910.             return;
  911.         }
  912.         int transX = par.getAbsoluteX() + par.getScrollX();
  913.         int transY = par.getAbsoluteY() + par.getScrollY();
  914.         g.translate(transX, transY);
  915.         ((Container) par).paintIntersecting(g, c, x, y, w, h, false);
  916.         if (par.isBorderPainted()) {
  917.             Border b = par.getBorder();
  918.             if (b.isBackgroundPainter()) {
  919.                 g.translate(-par.getX(), -par.getY());
  920.                 b.paintBorderBackground(g, par);
  921.                 b.paint(g, par);
  922.                 g.translate(par.getX() - transX, par.getY() - transY);
  923.                 return;
  924.             }
  925.         }
  926.         Painter p = par.getStyle().getBgPainter();
  927.         if (p != null) {
  928.             Rectangle rect;
  929.             if (painterBounds == null || painterBounds.get() == null) {
  930.                 rect = new Rectangle(0, 0, par.getWidth(), par.getHeight());
  931.                 painterBounds = new WeakReference(rect);
  932.             } else {
  933.                 rect = (Rectangle) painterBounds.get();
  934.                 rect.getSize().setWidth(par.getWidth());
  935.                 rect.getSize().setHeight(par.getHeight());
  936.             }
  937.             p.paint(g, rect);
  938.         }
  939.         g.translate(-transX, -transY);
  940.     }
  941.     /**
  942.      * Normally returns getStyle().getBorder() but some subclasses might use this 
  943.      * to programmatically replace the border in runtime e.g. for a pressed border effect
  944.      * 
  945.      * @return the border that is drawn according to the current component state
  946.      */
  947.     protected Border getBorder() {
  948.         /*Border b = getStyle().getBorder();
  949.         if (hasFocus()) {
  950.         if (b != null) {
  951.         return b.getFocusedInstance();
  952.         }
  953.         return b;
  954.         } else {
  955.         return b;
  956.         }*/
  957.         return getStyle().getBorder();
  958.     }
  959.     /**
  960.      * Paints the background of the component, invoked with the clipping region
  961.      * and appropriate scroll translation.
  962.      * 
  963.      * @param g the component graphics
  964.      */
  965.     protected void paintBackground(Graphics g) {
  966.         if (isBorderPainted()) {
  967.             Border b = getBorder();
  968.             if (b != null && b.isBackgroundPainter()) {
  969.                 b.paintBorderBackground(g, this);
  970.                 return;
  971.             }
  972.         }
  973.         if (getStyle().getBgPainter() != null) {
  974.             getStyle().getBgPainter().paint(g, bounds);
  975.         }
  976.     }
  977.     /**
  978.      * This method paints the Component on the screen, it should be overriden
  979.      * by subclasses to perform custom drawing or invoke the UI API's to let
  980.      * the PLAF perform the rendering.
  981.      * 
  982.      * @param g the component graphics
  983.      */
  984.     public void paint(Graphics g) {
  985.     }
  986.     /**
  987.      * Indicates whether the component should/could scroll by default a component
  988.      * is not scrollable.
  989.      * 
  990.      * @return whether the component is scrollable
  991.      */
  992.     protected boolean isScrollable() {
  993.         return isScrollableX() || isScrollableY();
  994.     }
  995.     /**
  996.      * Indicates whether the component should/could scroll on the X axis
  997.      * 
  998.      * @return whether the component is scrollable on the X axis
  999.      */
  1000.     public boolean isScrollableX() {
  1001.         return false;
  1002.     }
  1003.     /**
  1004.      * Indicates whether the component should/could scroll on the Y axis
  1005.      * 
  1006.      * @return whether the component is scrollable on the X axis
  1007.      */
  1008.     public boolean isScrollableY() {
  1009.         return false;
  1010.     }
  1011.     /**
  1012.      * Indicates the X position of the scrolling, this number is relative to the
  1013.      * component position and so a position of 0 would indicate the x position
  1014.      * of the component.
  1015.      * 
  1016.      * @return the X position of the scrolling
  1017.      */
  1018.     public int getScrollX() {
  1019.         return scrollX;
  1020.     }
  1021.     /**
  1022.      * Indicates the Y position of the scrolling, this number is relative to the
  1023.      * component position and so a position of 0 would indicate the x position
  1024.      * of the component.
  1025.      * 
  1026.      * @return the Y position of the scrolling
  1027.      */
  1028.     public int getScrollY() {
  1029.         return scrollY;
  1030.     }
  1031.     /**
  1032.      * Indicates the X position of the scrolling, this number is relative to the
  1033.      * component position and so a position of 0 would indicate the x position
  1034.      * of the component.
  1035.      * 
  1036.      * @param scrollX the X position of the scrolling
  1037.      */
  1038.     protected void setScrollX(int scrollX) {
  1039.         // the setter must always update the value regardless...
  1040.         this.scrollX = scrollX;
  1041.         this.scrollX = Math.min(this.scrollX, getScrollDimension().getWidth() - getWidth());        
  1042.         this.scrollX = Math.max(this.scrollX, 0);
  1043.         if (isScrollableX()) {
  1044.             repaint();
  1045.         }
  1046.     }
  1047.     /**
  1048.      * Indicates the X position of the scrolling, this number is relative to the
  1049.      * component position and so a position of 0 would indicate the x position
  1050.      * of the component.
  1051.      * 
  1052.      * @param scrollY the Y position of the scrolling
  1053.      */
  1054.     protected void setScrollY(int scrollY) {
  1055.         // the setter must always update the value regardless... 
  1056.         this.scrollY = scrollY;
  1057.         this.scrollY = Math.min(this.scrollY, getScrollDimension().getHeight() - getHeight());
  1058.         this.scrollY = Math.max(this.scrollY, 0);
  1059.         if (isScrollableY()) {
  1060.             repaint();
  1061.         }
  1062.     }
  1063.     /**
  1064.      * Returns the gap to be left for the bottom scrollbar on the X axis. This
  1065.      * method is used by layout managers to determine the room they should
  1066.      * leave for the scrollbar
  1067.      * 
  1068.      * @return the gap to be left for the bottom scrollbar on the X axis
  1069.      */
  1070.     public int getBottomGap() {
  1071.         if (isScrollableX() && isScrollVisible()) {
  1072.             return UIManager.getInstance().getLookAndFeel().getHorizontalScrollHeight();
  1073.         }
  1074.         return 0;
  1075.     }
  1076.     /**
  1077.      * Returns the gap to be left for the side scrollbar on the Y axis. This
  1078.      * method is used by layout managers to determine the room they should
  1079.      * leave for the scrollbar. (note: side scrollbar rather than left scrollbar
  1080.      * is used for a future version that would support bidi).
  1081.      * 
  1082.      * @return the gap to be left for the side scrollbar on the Y axis
  1083.      */
  1084.     public int getSideGap() {
  1085.         if (isScrollableY() && isScrollVisible()) {
  1086.             return UIManager.getInstance().getLookAndFeel().getVerticalScrollWidth();
  1087.         }
  1088.         return 0;
  1089.     }
  1090.     /**
  1091.      * Returns true if the given absolute coordinate is contained in the Component
  1092.      * 
  1093.      * @param x the given absolute x coordinate
  1094.      * @param y the given absolute y coordinate
  1095.      * @return true if the given absolute coordinate is contained in the 
  1096.      * Component; otherwise false
  1097.      */
  1098.     public boolean contains(int x, int y) {
  1099.         int absX = getAbsoluteX() + getScrollX();
  1100.         int absY = getAbsoluteY() + getScrollY();
  1101.         return (x >= absX && x < absX + getWidth() && y >= absY && y < absY + getHeight());
  1102.     }
  1103.     /**
  1104.      * Calculates the preferred size based on component content. This method is
  1105.      * invoked lazily by getPreferred size.
  1106.      * 
  1107.      * @return the calculated preferred size based on component content
  1108.      */
  1109.     protected Dimension calcPreferredSize() {
  1110.         Dimension d = new Dimension(0, 0);
  1111.         return d;
  1112.     }
  1113.     private Dimension preferredSize() {
  1114.         if (!sizeRequestedByUser && (shouldCalcPreferredSize || preferredSize == null)) {
  1115.             shouldCalcPreferredSize = false;
  1116.             preferredSize = calcPreferredSize();
  1117.         }
  1118.         return preferredSize;
  1119.     }
  1120.     /**
  1121.      * Returns the component bounds which is sometimes more convenient than invoking
  1122.      * getX/Y/Width/Height. Bounds are relative to parent container.<br>
  1123.      * Changing values within the bounds can lead to unpredicted behavior.
  1124.      * 
  1125.      * @see #getX
  1126.      * @see #getY
  1127.      * @return the component bounds
  1128.      */
  1129.     protected Rectangle getBounds() {
  1130.         return bounds;
  1131.     }
  1132.     /**
  1133.      * Returns the component bounds for scrolling which might differ from the getBounds for large components
  1134.      * e.g. list.
  1135.      *
  1136.      * @see #getX
  1137.      * @see #getY
  1138.      * @return the component bounds
  1139.      */
  1140.     protected Rectangle getVisibleBounds() {
  1141.         return bounds;
  1142.     }
  1143.     /**
  1144.      * Returns true if this component can receive focus and is enabled
  1145.      * 
  1146.      * @return true if this component can receive focus; otherwise false
  1147.      */
  1148.     public boolean isFocusable() {
  1149.         return focusable && enabled && isVisible();
  1150.     }
  1151.     /**
  1152.      * A simple setter to determine if this Component can get focused
  1153.      * 
  1154.      * @param focusable indicate whether this component can get focused
  1155.      */
  1156.     public void setFocusable(boolean focusable) {
  1157.         this.focusable = focusable;
  1158.         Form p = getComponentForm();
  1159.         if (p != null) {
  1160.             p.clearFocusVectors();
  1161.         }
  1162.     }
  1163.     /**
  1164.      * Indicates the values within the component have changed and preferred 
  1165.      * size should be recalculated
  1166.      * 
  1167.      * @param shouldCalcPreferredSize indicate whether this component need to 
  1168.      * recalculate his preferred size
  1169.      */
  1170.     protected void setShouldCalcPreferredSize(boolean shouldCalcPreferredSize) {
  1171.         if (!shouldCalcScrollSize) {
  1172.             this.shouldCalcScrollSize = shouldCalcPreferredSize;
  1173.         }
  1174.         if (shouldCalcPreferredSize != this.shouldCalcPreferredSize) {
  1175.             this.shouldCalcPreferredSize = shouldCalcPreferredSize;
  1176.             this.shouldCalcScrollSize = shouldCalcPreferredSize;
  1177.             if (shouldCalcPreferredSize && getParent() != null) {
  1178.                 this.shouldCalcPreferredSize = shouldCalcPreferredSize;
  1179.                 getParent().setShouldCalcPreferredSize(shouldCalcPreferredSize);
  1180.             }
  1181.         }
  1182.     }
  1183.     /**
  1184.      * Indicates whether focus should be drawn around the component or whether 
  1185.      * it will handle its own focus painting
  1186.      * 
  1187.      * @return true if focus should be drawn around the component
  1188.      * ; otherwise false
  1189.      * @deprecated this method would be removed in a future version of the API, manipulate getSelectedStyle()
  1190.      * to achieve a similar look
  1191.      */
  1192.     public boolean isFocusPainted() {
  1193.         return focusPainted;
  1194.     }
  1195.     /**
  1196.      * Indicates whether focus should be drawn around the component or whether 
  1197.      * it will handle its own focus painting
  1198.      * 
  1199.      * @param focusPainted indicates whether focus should be drawn around the 
  1200.      * component
  1201.      */
  1202.     public void setFocusPainted(boolean focusPainted) {
  1203.         this.focusPainted = focusPainted;
  1204.     }
  1205.     /**
  1206.      * Prevents key events from being grabbed for focus traversal. E.g. a list component
  1207.      * might use the arrow keys for internal navigation so it will switch this flag to
  1208.      * true in order to prevent the focus manager from moving to the next component.
  1209.      * 
  1210.      * @return true if key events are being used for focus traversal
  1211.      * ; otherwise false
  1212.      */
  1213.     public boolean handlesInput() {
  1214.         return handlesInput;
  1215.     }
  1216.     /**
  1217.      * Prevents key events from being grabbed for focus traversal. E.g. a list component
  1218.      * might use the arrow keys for internal navigation so it will switch this flag to
  1219.      * true in order to prevent the focus manager from moving to the next component.
  1220.      * 
  1221.      * @param handlesInput indicates whether key events can be grabbed for 
  1222.      * focus traversal
  1223.      */
  1224.     public void setHandlesInput(boolean handlesInput) {
  1225.         this.handlesInput = handlesInput;
  1226.     }
  1227.     /**
  1228.      * Returns true if the component has focus
  1229.      * 
  1230.      * @return true if the component has focus; otherwise false
  1231.      * @see #setFocus
  1232.      */
  1233.     public boolean hasFocus() {
  1234.         return focused;
  1235.     }
  1236.     /**
  1237.      * This flag doesn't really give focus, its a state that determines
  1238.      * what colors from the Style should be used when painting the component.
  1239.      * Actual focus is determined by the parent form
  1240.      * 
  1241.      * @param focused sets the state that determines what colors from the 
  1242.      * Style should be used when painting a focused component
  1243.      * 
  1244.      * @see #requestFocus
  1245.      */
  1246.     public void setFocus(boolean focused) {
  1247.         this.focused = focused;
  1248.     }
  1249.     /**
  1250.      * Returns the Component Form or null if this Component
  1251.      * is not added yet to a form
  1252.      * 
  1253.      * @return the Component Form
  1254.      */
  1255.     public Form getComponentForm() {
  1256.         Form retVal = null;
  1257.         Component parent = getParent();
  1258.         if (parent != null) {
  1259.             retVal = parent.getComponentForm();
  1260.         }
  1261.         return retVal;
  1262.     }
  1263.     /**
  1264.      * Repaint the given component to the screen
  1265.      * 
  1266.      * @param cmp the given component on the screen
  1267.      */
  1268.     void repaint(Component cmp) {
  1269.         if (isCellRenderer() || cmp.getWidth() <= 0 || cmp.getHeight() <= 0) {
  1270.             return;
  1271.         }
  1272.         // null parent repaint can happen when a component is removed and modified which
  1273.         // is common for a popup
  1274.         Component parent = getParent();
  1275.         if (parent != null) {
  1276.             parent.repaint(cmp);
  1277.         }
  1278.     }
  1279.     /**
  1280.      * Repaint this Component, the repaint call causes a callback of the paint
  1281.      * method on the event dispatch thread.
  1282.      * 
  1283.      * @see Display
  1284.      */
  1285.     public void repaint() {
  1286.         if (dirtyRegion != null) {
  1287.             setDirtyRegion(null);
  1288.         }
  1289.         repaint(this);
  1290.     }
  1291.     /**
  1292.      * Repaints a specific region within the component
  1293.      * 
  1294.      * @param x boundry of the region to repaint
  1295.      * @param y boundry of the region to repaint
  1296.      * @param w boundry of the region to repaint
  1297.      * @param h boundry of the region to repaint
  1298.      */
  1299.     public void repaint(int x, int y, int w, int h) {
  1300.         Rectangle rect;
  1301.         synchronized (dirtyRegionLock) {
  1302.             if (dirtyRegion == null) {
  1303.                 rect = new Rectangle(x, y, w, h);
  1304.                 setDirtyRegion(rect);
  1305.             } else if (dirtyRegion.getX() != x || dirtyRegion.getY() != y ||
  1306.                     dirtyRegion.getSize().getWidth() != w || dirtyRegion.getSize().getHeight() != h) {
  1307.                 rect = new Rectangle(dirtyRegion);
  1308.                 Dimension size = rect.getSize();
  1309.                 int x1 = Math.min(rect.getX(), x);
  1310.                 int y1 = Math.min(rect.getY(), y);
  1311.                 int x2 = Math.max(x + w, rect.getX() + size.getWidth());
  1312.                 int y2 = Math.max(y + h, rect.getY() + size.getHeight());
  1313.                 rect.setX(x1);
  1314.                 rect.setY(y1);
  1315.                 size.setWidth(x2 - x1);
  1316.                 size.setHeight(y2 - y1);
  1317.                 setDirtyRegion(rect);
  1318.             }
  1319.         }
  1320.         repaint(this);
  1321.     }
  1322.     /**
  1323.      * If this Component is focused this method is invoked when the user presses
  1324.      * and holds the key
  1325.      * 
  1326.      * @param keyCode the key code value to indicate a physical key.
  1327.      */
  1328.     protected void longKeyPress(int keyCode) {
  1329.     }
  1330.     /**
  1331.      * If this Component is focused, the key pressed event
  1332.      * will call this method
  1333.      * 
  1334.      * @param keyCode the key code value to indicate a physical key.
  1335.      */
  1336.     public void keyPressed(int keyCode) {
  1337.     }
  1338.     /**
  1339.      * If this Component is focused, the key released event
  1340.      * will call this method
  1341.      * 
  1342.      * @param keyCode the key code value to indicate a physical key.
  1343.      */
  1344.     public void keyReleased(int keyCode) {
  1345.     }
  1346.     /**
  1347.      * If this Component is focused, the key repeat event
  1348.      * will call this method.
  1349.      * 
  1350.      * @param keyCode the key code value to indicate a physical key.
  1351.      */
  1352.     public void keyRepeated(int keyCode) {
  1353.         keyPressed(keyCode);
  1354.         keyReleased(keyCode);
  1355.     }
  1356.     /**
  1357.      * Allows defining the physics for the animation motion behavior directly 
  1358.      * by plugging in an alternative motion object
  1359.      * 
  1360.      * @param motion new motion object
  1361.      */
  1362.     private void setAnimationMotion(Motion motion) {
  1363.         animationMotion = motion;
  1364.     }
  1365.     /**
  1366.      * Allows defining the physics for the animation motion behavior directly 
  1367.      * by plugging in an alternative motion object
  1368.      * 
  1369.      * @return the component motion object
  1370.      */
  1371.     private Motion getAnimationMotion() {
  1372.         return animationMotion;
  1373.     }
  1374.     /**
  1375.      * Scroll animation speed in milliseconds allowing a developer to slow down or accelerate
  1376.      * the smooth animation mode
  1377.      * 
  1378.      * @return scroll animation speed in milliseconds
  1379.      */
  1380.     public int getScrollAnimationSpeed() {
  1381.         return animationSpeed;
  1382.     }
  1383.     /**
  1384.      * Scroll animation speed in milliseconds allowing a developer to slow down or accelerate
  1385.      * the smooth animation mode
  1386.      * 
  1387.      * @param animationSpeed scroll animation speed in milliseconds
  1388.      */
  1389.     public void setScrollAnimationSpeed(int animationSpeed) {
  1390.         this.animationSpeed = animationSpeed;
  1391.     }
  1392.     /**
  1393.      * Indicates that scrolling through the component should work as an animation
  1394.      * 
  1395.      * @return whether this component use smooth scrolling
  1396.      */
  1397.     public boolean isSmoothScrolling() {
  1398.         return smoothScrolling;
  1399.     }
  1400.     /**
  1401.      * Indicates that scrolling through the component should work as an animation
  1402.      * 
  1403.      * @param smoothScrolling indicates if a component uses smooth scrolling
  1404.      */
  1405.     public void setSmoothScrolling(boolean smoothScrolling) {
  1406.         this.smoothScrolling = smoothScrolling;
  1407.     }
  1408.     /**
  1409.      * Invoked for devices where the pointer can hover without actually clicking
  1410.      * the display. This is true for PC mouse pointer as well as some devices such
  1411.      * as the BB storm.
  1412.      * 
  1413.      * @param x the pointer x coordinate
  1414.      * @param y the pointer y coordinate
  1415.      */
  1416.     public void pointerHover(int[] x, int[] y) {
  1417.         draggedMotion = null;
  1418.         pointerDragged(x, y);
  1419.     }
  1420.     void clearDrag() {
  1421.         draggedMotion = null;
  1422.     }
  1423.     /**
  1424.      * Invoked for devices where the pointer can hover without actually clicking
  1425.      * the display. This is true for PC mouse pointer as well as some devices such
  1426.      * as the BB storm.
  1427.      *
  1428.      * @param x the pointer x coordinate
  1429.      * @param y the pointer y coordinate
  1430.      */
  1431.     public void pointerHoverReleased(int[] x, int[] y) {
  1432.         pointerReleaseImpl(x[0], y[0]);
  1433.     }
  1434.     /**
  1435.      * If this Component is focused, the pointer dragged event
  1436.      * will call this method
  1437.      * 
  1438.      * @param x the pointer x coordinate
  1439.      * @param y the pointer y coordinate
  1440.      */
  1441.     public void pointerDragged(int[] x, int[] y) {
  1442.         pointerDragged(x[0], y[0]);
  1443.     }
  1444.     /**
  1445.      * If this Component is focused, the pointer dragged event
  1446.      * will call this method
  1447.      * 
  1448.      * @param x the pointer x coordinate
  1449.      * @param y the pointer y coordinate
  1450.      */
  1451.     public void pointerDragged(int x, int y) {
  1452.         if (isScrollable() && isSmoothScrolling()) {
  1453.             int axisValue;
  1454.             if (isScrollableY()) {
  1455.                 axisValue = y;
  1456.             } else {
  1457.                 axisValue = x;
  1458.             }
  1459.             if (!dragActivated) {
  1460.                 dragActivated = true;
  1461.                 lastScrollY = y;
  1462.                 lastScrollX = x;
  1463.                 Form p = getComponentForm();
  1464.                 p.setDraggedComponent(this);
  1465.                 p.registerAnimatedInternal(this);
  1466.             }
  1467.             // we drag inversly to get a feel of grabbing a physical screen
  1468.             // and pulling it in the reverse direction of the drag
  1469.             if (isScrollableY()) {
  1470.                 int scroll = getScrollY() + (lastScrollY - y);
  1471.                 if (scroll >= 0 && scroll < getScrollDimension().getHeight() - getHeight()) {
  1472.                     setScrollY(scroll);
  1473.                 }
  1474.             }
  1475.             if (isScrollableX()) {
  1476.                 int scroll = getScrollX() + (lastScrollX - x);
  1477.                 if (scroll >= 0 && scroll < getScrollDimension().getWidth() - getWidth()) {
  1478.                     setScrollX(scroll);
  1479.                 }
  1480.             }
  1481.             lastScrollY = y;
  1482.             lastScrollX = x;
  1483.         } else {
  1484.             //try to find a scrollable element until you reach the Form
  1485.             Component parent = getParent();
  1486.             if (!(parent instanceof Form)) {
  1487.                 parent.pointerDragged(x, y);
  1488.             }
  1489.         }
  1490.     }
  1491.     private void initScrollMotion() {
  1492.         // the component might not be registered for animation if it started off 
  1493.         // as smaller than the screen and grew (e.g. by adding components to the container
  1494.         // once it is visible).
  1495.         Form f = getComponentForm();
  1496.         if (f != null) {
  1497.             f.registerAnimatedInternal(this);
  1498.         }
  1499.         Motion m = Motion.createLinearMotion(initialScrollY, destScrollY, getScrollAnimationSpeed());
  1500.         setAnimationMotion(m);
  1501.         m.start();
  1502.     }
  1503.     /**
  1504.      * If this Component is focused, the pointer pressed event
  1505.      * will call this method
  1506.      * 
  1507.      * @param x the pointer x coordinate
  1508.      * @param y the pointer y coordinate
  1509.      */
  1510.     public void pointerPressed(int[] x, int[] y) {
  1511.         draggedMotion = null;
  1512.         dragActivated = false;
  1513.         pointerPressed(x[0], y[0]);
  1514.     }
  1515.     /**
  1516.      * If this Component is focused, the pointer pressed event
  1517.      * will call this method
  1518.      * 
  1519.      * @param x the pointer x coordinate
  1520.      * @param y the pointer y coordinate
  1521.      */
  1522.     public void pointerPressed(int x, int y) {
  1523.         draggedMotion = null;
  1524.     }
  1525.     /**
  1526.      * If this Component is focused, the pointer released event
  1527.      * will call this method
  1528.      * 
  1529.      * @param x the pointer x coordinate
  1530.      * @param y the pointer y coordinate
  1531.      */
  1532.     public void pointerReleased(int[] x, int[] y) {
  1533.         pointerReleased(x[0], y[0]);
  1534.     }
  1535.     /**
  1536.      * If this Component is focused this method is invoked when the user presses
  1537.      * and holds the pointer on the Component
  1538.      * 
  1539.      */
  1540.     protected void longPointerPress(int x, int y) {
  1541.     }
  1542.     /**
  1543.      * If this Component is focused, the pointer released event
  1544.      * will call this method
  1545.      * 
  1546.      * @param x the pointer x coordinate
  1547.      * @param y the pointer y coordinate
  1548.      */
  1549.     public void pointerReleased(int x, int y) {
  1550.         pointerReleaseImpl(x, y);
  1551.     }
  1552.     private void pointerReleaseImpl(int x, int y) {
  1553.         if (dragActivated) {
  1554.             int scroll = scrollY;
  1555.             if(isScrollableX()){
  1556.                 scroll = scrollX;
  1557.             }
  1558.             draggedMotion = Motion.createFrictionMotion(scroll,
  1559.                     Display.getInstance().getDragSpeed(isScrollableY()),
  1560.                     0.0004f);
  1561.             draggedMotion.start();
  1562.             dragActivated = false;
  1563.         }
  1564.     }
  1565.     /**
  1566.      * Returns the Component Style allowing us to manipulate the look of the 
  1567.      * component
  1568.      * 
  1569.      * @return the component Style object
  1570.      */
  1571.     public Style getStyle() {
  1572.         if (unSelectedStyle == null) {
  1573.             initStyle();
  1574.         }
  1575.         if (hasFocus() && isFocusPainted()) {
  1576.             return getSelectedStyle();
  1577.         }
  1578.         return unSelectedStyle;
  1579.     }
  1580.     /**
  1581.      * Returns the Component Style for the unselected mode allowing us to manipulate
  1582.      * the look of the component
  1583.      *
  1584.      * @return the component Style object
  1585.      */
  1586.     public Style getUnselectedStyle() {
  1587.         if (unSelectedStyle == null) {
  1588.             initStyle();
  1589.         }
  1590.         return unSelectedStyle;
  1591.     }
  1592.     /**
  1593.      * Returns the Component Style for the selected state allowing us to manipulate
  1594.      * the look of the component when it owns focus
  1595.      *
  1596.      * @return the component Style object
  1597.      */
  1598.     public Style getSelectedStyle() {
  1599.         if (selectedStyle == null) {
  1600.             selectedStyle = UIManager.getInstance().getComponentSelectedStyle(getUIID());
  1601.             selectedStyle.addStyleListener(this);
  1602.             if (selectedStyle.getBgPainter() == null) {
  1603.                 selectedStyle.setBgPainter(new BGPainter());
  1604.             }
  1605.         }
  1606.         return selectedStyle;
  1607.     }
  1608.     /**
  1609.      * Changes the Component Style by replacing the Component Style with the given Style
  1610.      * 
  1611.      * @param style the component Style object 
  1612.      * @deprecated 
  1613.      */
  1614.     public void setStyle(Style style) {
  1615.         setUnSelectedStyle(style);
  1616.     }
  1617.     /**
  1618.      * Changes the Component Style by replacing the Component Style with the given Style
  1619.      *
  1620.      * @param style the component Style object
  1621.      * @deprecated use setUnselectedStyle (the case of the S character in this method is incorrect)
  1622.      */
  1623.     public void setUnSelectedStyle(Style style) {
  1624.         setUnselectedStyle(style);
  1625.     }
  1626.     /**
  1627.      * Changes the Component Style by replacing the Component Style with the given Style
  1628.      * 
  1629.      * @param style the component Style object
  1630.      */
  1631.     public void setUnselectedStyle(Style style) {
  1632.         if (this.unSelectedStyle != null) {
  1633.             this.unSelectedStyle.removeStyleListener(this);
  1634.         }
  1635.         this.unSelectedStyle = style;
  1636.         this.unSelectedStyle.addStyleListener(this);
  1637.         if (this.unSelectedStyle.getBgPainter() == null) {
  1638.             this.unSelectedStyle.setBgPainter(new BGPainter());
  1639.         }
  1640.         setShouldCalcPreferredSize(true);
  1641.         checkAnimation();
  1642.     }
  1643.     /**
  1644.      * Changes the Component selected Style by replacing the Component Style with the given Style
  1645.      *
  1646.      * @param style the component Style object
  1647.      */
  1648.     public void setSelectedStyle(Style style) {
  1649.         if (this.selectedStyle != null) {
  1650.             this.selectedStyle.removeStyleListener(this);
  1651.         }
  1652.         this.selectedStyle = style;
  1653.         this.selectedStyle.addStyleListener(this);
  1654.         if (this.selectedStyle.getBgPainter() == null) {
  1655.             this.selectedStyle.setBgPainter(new BGPainter());
  1656.         }
  1657.         setShouldCalcPreferredSize(true);
  1658.         checkAnimation();
  1659.     }
  1660.     /**
  1661.      * Changes the current component to the focused component, will work only
  1662.      * for a component that belongs to a parent form.
  1663.      */
  1664.     public void requestFocus() {
  1665.         Form rootForm = getComponentForm();
  1666.         if (rootForm != null) {
  1667.             rootForm.requestFocus(this);
  1668.         }
  1669.     }
  1670.     /**
  1671.      * Overriden to return a useful value for debugging purposes
  1672.      * 
  1673.      * @return a string representation of this component
  1674.      */
  1675.     public String toString() {
  1676.         String className = getClass().getName();
  1677.         className = className.substring(className.lastIndexOf('.') + 1);
  1678.         return className + "[" + paramString() + "]";
  1679.     }
  1680.     /**
  1681.      * Returns a string representing the state of this component. This 
  1682.      * method is intended to be used only for debugging purposes, and the 
  1683.      * content and format of the returned string may vary between 
  1684.      * implementations. The returned string may be empty but may not be 
  1685.      * <code>null</code>.
  1686.      * 
  1687.      * @return  a string representation of this component's state
  1688.      */
  1689.     protected String paramString() {
  1690.         return "x=" + getX() + " y=" + getY() + " width=" + getWidth() + " height=" + getHeight();
  1691.     }
  1692.     /**
  1693.      * Makes sure the component is up to date with the current style object
  1694.      */
  1695.     public void refreshTheme() {
  1696.         refreshTheme(getUIID());
  1697.     }
  1698.     /**
  1699.      * Makes sure the component is up to date with the given UIID
  1700.      * 
  1701.      * @param id The Style Id to update the Component with
  1702.      */
  1703.     protected void refreshTheme(String id) {
  1704.         Style unSelected = getUnselectedStyle();
  1705.         setUnSelectedStyle(mergeStyle(unSelected, UIManager.getInstance().getComponentStyle(id)));
  1706.         if (selectedStyle != null) {
  1707.             setSelectedStyle(mergeStyle(selectedStyle, UIManager.getInstance().getComponentSelectedStyle(id)));
  1708.         }
  1709.         checkAnimation();
  1710.         UIManager.getInstance().getLookAndFeel().bind(this);
  1711.     }
  1712.     Style mergeStyle(Style toMerge, Style newStyle) {
  1713.         if (toMerge.isModified()) {
  1714.             toMerge.merge(newStyle);
  1715.             return toMerge;
  1716.         } else {
  1717.             return newStyle;
  1718.         }
  1719.     }
  1720.     /**
  1721.      * Internal method indicating whether we are in the middle of a drag
  1722.      * 
  1723.      * @return true if we are in the middle of a drag; otherwise false
  1724.      */
  1725.     boolean isDragActivated() {
  1726.         return dragActivated;
  1727.     }
  1728.     void setDragActivated(boolean dragActivated) {
  1729.         this.dragActivated = dragActivated;
  1730.     }
  1731.     void checkAnimation() {
  1732.         Image bgImage = getStyle().getBgImage();
  1733.         if (bgImage != null && bgImage.isAnimation()) {
  1734.             Form parent = getComponentForm();
  1735.             if (parent != null) {
  1736.                 // animations are always running so the internal animation isn't
  1737.                 // good enough. We never want to stop this sort of animation
  1738.                 parent.registerAnimated(this);
  1739.             }
  1740.         }
  1741.     }
  1742.     void deregisterAnimatedInternal() {
  1743.         Form f = getComponentForm();
  1744.         if (f != null) {
  1745.             f.deregisterAnimatedInternal(this);
  1746.         }
  1747.     }
  1748.     
  1749.     /**
  1750.      * @inheritDoc
  1751.      */
  1752.     public boolean animate() {
  1753.         Image bgImage = getStyle().getBgImage();
  1754.         boolean animateBackground = bgImage != null && bgImage.isAnimation() && bgImage.animate();
  1755.         Motion m = getAnimationMotion();
  1756.         //preform regular scrolling
  1757.         if (m != null && destScrollY != -1 && destScrollY != getScrollY()) {
  1758.             // change the variable directly for efficiency both in removing redundant
  1759.             // repaints and scroll checks
  1760.             setScrollY(m.getValue());
  1761.             if (destScrollY == scrollY) {
  1762.                 destScrollY = -1;
  1763.                 deregisterAnimatedInternal();
  1764.             }
  1765.             return true;
  1766.         }
  1767.         //preform the dragging motion if exists
  1768.         if (draggedMotion != null && !draggedMotion.isFinished()) {
  1769.             // change the variable directly for efficiency both in removing redundant
  1770.             // repaints and scroll checks
  1771.             int dragVal = draggedMotion.getValue();
  1772.             if (isScrollableY()) {
  1773.                 if (dragVal >= 0 && dragVal <= (getScrollDimension().getHeight() - getHeight())) {
  1774.                     scrollY = dragVal;
  1775.                     return true;
  1776.                 }
  1777.             } else {
  1778.                 if (dragVal >= 0 && dragVal <= (getScrollDimension().getWidth() - getWidth())) {
  1779.                     scrollX = dragVal;
  1780.                     return true;
  1781.                 }
  1782.             }
  1783.         }
  1784.         if (animateBackground && bgImage instanceof StaticAnimation) {
  1785.             Rectangle dirty = ((StaticAnimation) bgImage).getDirtyRegion();
  1786.             if (dirty != null) {
  1787.                 dirty.setX(getAbsoluteX());
  1788.                 dirty.setY(getAbsoluteY() + dirty.getY());
  1789.             }
  1790.             setDirtyRegion(dirty);
  1791.         }
  1792.         return animateBackground;
  1793.     }
  1794.     /**
  1795.      * Makes sure the component is visible in the scroll if this container 
  1796.      * is scrollable
  1797.      * 
  1798.      * @param rect the rectangle that need to be visible
  1799.      * @param coordinateSpace the component according to whose coordinates 
  1800.      * rect is defined. Rect's x/y are relative to that component 
  1801.      * (they are not absolute).
  1802.      */
  1803.     protected void scrollRectToVisible(Rectangle rect, Component coordinateSpace) {
  1804.         scrollRectToVisible(rect.getX(), rect.getY(), 
  1805.                 rect.getSize().getWidth(), rect.getSize().getHeight(), coordinateSpace);
  1806.     }
  1807.     /**
  1808.      * Makes sure the component is visible in the scroll if this container 
  1809.      * is scrollable
  1810.      *
  1811.      * @param x 
  1812.      * @param y 
  1813.      * @param width 
  1814.      * @param height  
  1815.      * @param coordinateSpace the component according to whose coordinates 
  1816.      * rect is defined. Rect's x/y are relative to that component 
  1817.      * (they are not absolute).
  1818.      */
  1819.     protected void scrollRectToVisible(int x, int y, int width, int height, Component coordinateSpace) {
  1820.         if (isScrollable()) {
  1821.             int scrollPosition = getScrollY();
  1822.             Style s = getStyle();
  1823.             int w = getWidth() - s.getPadding(isRTL(), LEFT) - s.getPadding(isRTL(), RIGHT);
  1824.             int h = getHeight() - s.getPadding(false, TOP) - s.getPadding(false, BOTTOM);
  1825.             Rectangle view;
  1826.             if (isSmoothScrolling() && destScrollY > -1) {
  1827.                 view = new Rectangle(destScrollY, getScrollX(), w, h);
  1828.             } else {
  1829.                 view = new Rectangle(getScrollX(), getScrollY(), w, h);
  1830.             }
  1831.             int relativeX = x;
  1832.             int relativeY = y;
  1833.             // component needs to be in absolute coordinates...
  1834.             Container parent = null;
  1835.             if (coordinateSpace != null) {
  1836.                 parent = coordinateSpace.getParent();
  1837.             }
  1838.             if (parent == this) {
  1839.                 if (view.contains(x, y, width, height)) {
  1840.                     return;
  1841.                 }
  1842.             } else {
  1843.                 while (parent != this) {
  1844.                     // mostly a special case for list
  1845.                     if (parent == null) {
  1846.                         relativeX = x;
  1847.                         relativeY = y;
  1848.                         break;
  1849.                     }
  1850.                     relativeX += parent.getX();
  1851.                     relativeY += parent.getY();
  1852.                     parent = parent.getParent();
  1853.                 }
  1854.                 if (view.contains(relativeX, relativeY, width, height)) {
  1855.                     return;
  1856.                 }
  1857.             }
  1858.             if (isScrollableX()) {
  1859.                 if (getScrollX() > relativeX) {
  1860.                     setScrollX(relativeX);
  1861.                 }
  1862.                 int rightX = relativeX + width;
  1863.                 if (getScrollX() + w < rightX) {
  1864.                     setScrollX(getScrollX() + (rightX - (getScrollX() + w)));
  1865.                 } else {
  1866.                     if (getScrollX() > relativeX) {
  1867.                         setScrollX(relativeX);
  1868.                     }
  1869.                 }
  1870.             }
  1871.             if (isScrollableY()) {
  1872.                 if (getScrollY() > relativeY) {
  1873.                     scrollPosition = relativeY;
  1874.                 }
  1875.                 int bottomY = relativeY + height - 
  1876.                         s.getPadding(TOP) - s.getPadding(BOTTOM);
  1877.                 if (getScrollY() + h < bottomY) {
  1878.                     scrollPosition = getScrollY() + (bottomY - (getScrollY() + h));
  1879.                 } else {
  1880.                     if (getScrollY() > relativeY) {
  1881.                         scrollPosition = relativeY;
  1882.                     }
  1883.                 }
  1884.                 if (isSmoothScrolling()) {
  1885.                     initialScrollY = getScrollY();
  1886.                     destScrollY = scrollPosition;
  1887.                     initScrollMotion();
  1888.                 } else {
  1889.                     setScrollY(scrollPosition);
  1890.                 }
  1891.             }
  1892.             repaint();
  1893.         } else {
  1894.             //try to move parent scroll if you are not scrollable
  1895.             Container parent = getParent();
  1896.             if (parent != null) {
  1897.                 parent.scrollRectToVisible(getAbsoluteX() - parent.getAbsoluteX() + x,
  1898.                         getAbsoluteY() - parent.getAbsoluteY() + y, 
  1899.                         width, height, parent);
  1900.             }
  1901.         }
  1902.     }
  1903.     /**
  1904.      * Indicates whether a border should be painted
  1905.      * 
  1906.      * @param b true would cause the paintBorder method to be invoked false
  1907.      * allows us to hide the border of the component without deriving the class
  1908.      * @deprecated use getStyle().setBorder() to null to disable borders or install
  1909.      * a different border
  1910.      */
  1911.     public void setBorderPainted(boolean b) {
  1912.         if (!b) {
  1913.             getStyle().setBorder(null);
  1914.         } else {
  1915.             getStyle().setBorder(Border.getDefaultBorder());
  1916.         }
  1917.     }
  1918.     /**
  1919.      * Indicates whether a border should be painted
  1920.      *
  1921.      * @return if the border will be painted
  1922.      * @deprecated use getStyle().getBorder() != null 
  1923.      */
  1924.     public boolean isBorderPainted() {
  1925.         return getStyle().getBorder() != null;
  1926.     }
  1927.     /**
  1928.      * Draws the component border if such a border exists. The border unlike the content
  1929.      * of the component will not be affected by scrolling for a scrollable component.
  1930.      * 
  1931.      * @param g graphics context on which the border is painted
  1932.      */
  1933.     protected void paintBorder(Graphics g) {
  1934.         Border b = getBorder();
  1935.         if (b != null) {
  1936.             g.setColor(getStyle().getFgColor());
  1937.             b.paint(g, this);
  1938.         }
  1939.     }
  1940.     /**
  1941.      * Used as an optimization to mark that this component is currently being
  1942.      * used as a cell renderer
  1943.      * 
  1944.      * @param cellRenderer indicate whether this component is currently being
  1945.      * used as a cell renderer
  1946.      */
  1947.     public void setCellRenderer(boolean cellRenderer) {
  1948.         this.cellRenderer = cellRenderer;
  1949.     }
  1950.     /**
  1951.      * Used as an optimization to mark that this component is currently being
  1952.      * used as a cell renderer
  1953.      * 
  1954.      * @return rtue is this component is currently being used as a cell renderer
  1955.      */
  1956.     boolean isCellRenderer() {
  1957.         return cellRenderer;
  1958.     }
  1959.     /**
  1960.      * Indicate whether this component scroll is visible
  1961.      * 
  1962.      * @return true is this component scroll is visible; otherwise false
  1963.      */
  1964.     public boolean isScrollVisible() {
  1965.         return isScrollVisible;
  1966.     }
  1967.     /**
  1968.      * Set whether this component scroll is visible
  1969.      * 
  1970.      * @param isScrollVisible Indicate whether this component scroll is visible
  1971.      */
  1972.     public void setIsScrollVisible(boolean isScrollVisible) {
  1973.         this.isScrollVisible = isScrollVisible;
  1974.     }
  1975.     /**
  1976.      * Invoked internally to initialize and bind the component
  1977.      */
  1978.     void initComponentImpl() {
  1979.         if (!initialized) {
  1980.             initialized = true;
  1981.             getStyle();
  1982.             UIManager.getInstance().getLookAndFeel().bind(this);
  1983.             checkAnimation();
  1984.             if(isRTL() && isScrollableX()){
  1985.                 setScrollX(getScrollDimension().getWidth());
  1986.             }
  1987.             initComponent();
  1988.         }
  1989.     }
  1990.     /**
  1991.      * Cleansup the initialization flags in the hierachy, notice that paint calls might
  1992.      * still occur after deinitilization mostly to perform transitions etc.
  1993.      * <p>However interactivity, animation and event tracking code can and probably
  1994.      * should be removed by this method.
  1995.      */
  1996.     void deinitializeImpl() {
  1997.         if (isInitialized()) {
  1998.             setInitialized(false);
  1999.             setDirtyRegion(null);
  2000.             deinitialize();
  2001.         }
  2002.     }
  2003.     /**
  2004.      * This is a callback method to inform the Component when it's been laidout
  2005.      * on the parent Container
  2006.      */
  2007.     protected void laidOut() {
  2008.         if (isScrollableY() && getScrollY() > 0 && getScrollY() + getHeight() > 
  2009.                 getScrollDimension().getHeight()) {
  2010.             setScrollY(getScrollDimension().getHeight() - getHeight());
  2011.         }
  2012.         if (isScrollableX() && getScrollX() > 0 && getScrollX() + getWidth() > 
  2013.                 getScrollDimension().getWidth()) {
  2014.             setScrollX(getScrollDimension().getWidth() - getWidth());
  2015.         }
  2016.         if(!isScrollableY()){
  2017.             setScrollY(0);
  2018.         }
  2019.         if(!isScrollableX()){
  2020.             setScrollX(0);
  2021.         }
  2022.     }
  2023.     /**
  2024.      * Invoked to indicate that the component initialization is being reversed
  2025.      * since the component was detached from the container hierarchy. This allows
  2026.      * the component to deregister animators and cleanup after itself. This
  2027.      * method is the opposite of the initComponent() method.
  2028.      */
  2029.     protected void deinitialize() {
  2030.     }
  2031.     /**
  2032.      * Allows subclasses to bind functionality that relies on fully initialized and
  2033.      * "ready for action" component state
  2034.      */
  2035.     protected void initComponent() {
  2036.     }
  2037.     /**
  2038.      * Indicates if the component is in the initialized state, a component is initialized
  2039.      * when its initComponent() method was invoked. The initMethod is invoked before showing the
  2040.      * component to the user.
  2041.      * 
  2042.      * @return true if the component is in the initialized state
  2043.      */
  2044.     protected boolean isInitialized() {
  2045.         return initialized;
  2046.     }
  2047.     /**
  2048.      * Indicates if the component is in the initialized state, a component is initialized
  2049.      * when its initComponent() method was invoked. The initMethod is invoked before showing the
  2050.      * component to the user.
  2051.      * 
  2052.      * @param initialized Indicates if the component is in the initialized state
  2053.      */
  2054.     protected void setInitialized(boolean initialized) {
  2055.         this.initialized = initialized;
  2056.     }
  2057.     /**
  2058.      * @inheritDoc
  2059.      */
  2060.     public void styleChanged(String propertyName, Style source) {
  2061.         //changing the Font, Padding, Margin may casue the size of the Component to Change
  2062.         //therefore we turn on the shouldCalcPreferredSize flag
  2063.         if ((!shouldCalcPreferredSize &&
  2064.                 source == getStyle()) &&
  2065.                 (propertyName.equals(Style.FONT) ||
  2066.                 propertyName.equals(Style.MARGIN) ||
  2067.                 propertyName.equals(Style.PADDING))) {
  2068.             setShouldCalcPreferredSize(true);
  2069.             Container parent = getParent();
  2070.             if (parent != null && parent.getComponentForm() != null) {
  2071.                 parent.revalidate();
  2072.             }
  2073.         }
  2074.     }
  2075.     /**
  2076.      * Allows us to determine which component will receive focus next when traversing 
  2077.      * with the down key
  2078.      * 
  2079.      * @return the next focus component
  2080.      */
  2081.     public Component getNextFocusDown() {
  2082.         return nextFocusDown;
  2083.     }
  2084.     /**
  2085.      * Allows us to determine which component will receive focus next when traversing 
  2086.      * with the down key
  2087.      * 
  2088.      * @param nextFocusDown the next focus component
  2089.      */
  2090.     public void setNextFocusDown(Component nextFocusDown) {
  2091.         this.nextFocusDown = nextFocusDown;
  2092.     }
  2093.     /**
  2094.      * Allows us to determine which component will receive focus next when traversing 
  2095.      * with the up key. 
  2096.      * 
  2097.      * @return the nxt focus component
  2098.      */
  2099.     public Component getNextFocusUp() {
  2100.         return nextFocusUp;
  2101.     }
  2102.     /**
  2103.      * Allows us to determine which component will receive focus next when traversing 
  2104.      * with the up key, this method doesn't affect the general focus behavior.
  2105.      * 
  2106.      * @param nextFocusUp next focus component
  2107.      */
  2108.     public void setNextFocusUp(Component nextFocusUp) {
  2109.         this.nextFocusUp = nextFocusUp;
  2110.     }
  2111.     /**
  2112.      * Allows us to determine which component will receive focus next when traversing 
  2113.      * with the left key. 
  2114.      * 
  2115.      * @return the next focus component
  2116.      */
  2117.     public Component getNextFocusLeft() {
  2118.         return nextFocusLeft;
  2119.     }
  2120.     /**
  2121.      * Allows us to determine which component will receive focus next when traversing 
  2122.      * with the left key, this method doesn't affect the general focus behavior.
  2123.      * 
  2124.      * @param nextFocusLeft the next focus component
  2125.      */
  2126.     public void setNextFocusLeft(Component nextFocusLeft) {
  2127.         this.nextFocusLeft = nextFocusLeft;
  2128.     }
  2129.     /**
  2130.      * Allows us to determine which component will receive focus next when traversing 
  2131.      * with the right key
  2132.      * 
  2133.      * @return the next focus component
  2134.      */
  2135.     public Component getNextFocusRight() {
  2136.         return nextFocusRight;
  2137.     }
  2138.     /**
  2139.      * Allows us to determine which component will receive focus next when traversing 
  2140.      * with the right key
  2141.      * 
  2142.      * @param nextFocusRight the next focus component
  2143.      */
  2144.     public void setNextFocusRight(Component nextFocusRight) {
  2145.         this.nextFocusRight = nextFocusRight;
  2146.     }
  2147.     /**
  2148.      * Indicates whether component is enabled or disabled thus allowing us to prevent
  2149.      * a component from receiving input events and indicate so visually
  2150.      * 
  2151.      * @return true if enabled
  2152.      */
  2153.     public boolean isEnabled() {
  2154.         return enabled;
  2155.     }
  2156.     /**
  2157.      * Used to reduce coupling between the TextArea component and display/implementation
  2158.      * classes thus reduce the size of the hello world MIDlet
  2159.      * 
  2160.      * @param text text after editing is completed
  2161.      */
  2162.     void onEditComplete(String text) {
  2163.     }
  2164.     /**
  2165.      * Indicates whether component is enabled or disabled thus allowing us to prevent
  2166.      * a component from receiving input events and indicate so visually
  2167.      * 
  2168.      * @param enabled true to enable false to disable
  2169.      */
  2170.     public void setEnabled(boolean enabled) {
  2171.         this.enabled = enabled;
  2172.         Form f = getComponentForm();
  2173.         if (f != null) {
  2174.             f.clearFocusVectors();
  2175.             repaint();
  2176.         }
  2177.     }
  2178.     /**
  2179.      * Allows components to create a style of their own, this method binds the listener
  2180.      * to the style and installs a bg painter
  2181.      *
  2182.      * @param s style to initialize
  2183.      */
  2184.     protected void initCustomStyle(Style s) {
  2185.         s.addStyleListener(this);
  2186.         if (s.getBgPainter() == null) {
  2187.             s.setBgPainter(new BGPainter());
  2188.         }
  2189.     }
  2190.     /**
  2191.      * Allows components to create a style of their own, this method cleans up
  2192.      * state for the given style
  2193.      *
  2194.      * @param s style no longer used
  2195.      */
  2196.     protected void deinitializeCustomStyle(Style s) {
  2197.         s.removeStyleListener(this);
  2198.     }
  2199.     /**
  2200.      * Is the component a bidi RTL component
  2201.      *
  2202.      * @return true if the component is working in a right to left mode
  2203.      */
  2204.     public boolean isRTL() {
  2205.         return rtl;
  2206.     }
  2207.     /**
  2208.      * Is the component a bidi RTL component
  2209.      *
  2210.      * @param rtl true if the component should work in a right to left mode
  2211.      */
  2212.     public void setRTL(boolean rtl) {
  2213.         this.rtl = rtl;
  2214.     }
  2215.     /**
  2216.      * Indicates whether the component should "trigger" tactile touch when pressed by the user
  2217.      * in a touch screen UI.
  2218.      * @return the tactileTouch
  2219.      */
  2220.     public boolean isTactileTouch() {
  2221.         return tactileTouch;
  2222.     }
  2223.     /**
  2224.      * Indicates whether the component should "trigger" tactile touch when pressed by the user
  2225.      * in a touch screen UI.
  2226.      *
  2227.      * @param tactileTouch true to trigger vibration when the component is pressed
  2228.      */
  2229.     public void setTactileTouch(boolean tactileTouch) {
  2230.         this.tactileTouch = tactileTouch;
  2231.     }
  2232.     
  2233.     class BGPainter implements Painter {
  2234.         private Form parent;
  2235.         private Form previousTint;
  2236.         private boolean ignorCoordinates;
  2237.         private Painter painter;
  2238.         public BGPainter() {
  2239.         }
  2240.         public BGPainter(Form parent, Painter p) {
  2241.             this.painter = p;
  2242.             this.parent = parent;
  2243.         }
  2244.         public void setIgnorCoordinates(boolean ignorCoordinates) {
  2245.             this.ignorCoordinates = ignorCoordinates;
  2246.         }
  2247.         public void setPreviousForm(Form previous) {
  2248.             previousTint = previous;
  2249.         }
  2250.         public Form getPreviousForm() {
  2251.             return previousTint;
  2252.         }
  2253.         public void setParent(Form parent) {
  2254.             this.parent = parent;
  2255.         }
  2256.         private void drawGradientBackground(Style s, Graphics g, int x, int y, int width, int height) {
  2257.             switch (s.getBackgroundType()) {
  2258.                 case Style.BACKGROUND_GRADIENT_LINEAR_HORIZONTAL:
  2259.                     g.fillLinearGradient(s.getBackgroundGradientStartColor(), s.getBackgroundGradientEndColor(),
  2260.                             x, y, width, height, true);
  2261.                     return;
  2262.                 case Style.BACKGROUND_GRADIENT_LINEAR_VERTICAL:
  2263.                     g.fillLinearGradient(s.getBackgroundGradientStartColor(), s.getBackgroundGradientEndColor(),
  2264.                             x, y, width, height, false);
  2265.                     return;
  2266.                 case Style.BACKGROUND_GRADIENT_RADIAL:
  2267.                     g.fillRectRadialGradient(s.getBackgroundGradientStartColor(), s.getBackgroundGradientEndColor(),
  2268.                             x, y, width, height, s.getBackgroundGradientRelativeX(), s.getBackgroundGradientRelativeY(),
  2269.                             s.getBackgroundGradientRelativeSize());
  2270.                     return;
  2271.             }
  2272.             g.setColor(s.getBgColor());
  2273.             g.fillRect(x, y, width, height, s.getBgTransparency());
  2274.         }
  2275.         public void paint(Graphics g, Rectangle rect) {
  2276.             if (painter != null) {
  2277.                 if (previousTint != null) {
  2278.                     previousTint.paint(g);
  2279.                 }
  2280.             } else {
  2281.                 Style s = getStyle();
  2282.                 int x = rect.getX();
  2283.                 int y = rect.getY();
  2284.                 int width = rect.getSize().getWidth();
  2285.                 int height = rect.getSize().getHeight();
  2286.                 if (width <= 0 || height <= 0) {
  2287.                     return;
  2288.                 }
  2289.                 Image bgImage = s.getBgImage();
  2290.                 if (bgImage == null) {
  2291.                     if(s.getBackgroundType() >= Style.BACKGROUND_GRADIENT_LINEAR_VERTICAL) {
  2292.                         drawGradientBackground(s, g, x, y, width, height);
  2293.                         return;
  2294.                     }
  2295.                     g.setColor(s.getBgColor());
  2296.                     g.fillRect(x, y, width, height, s.getBgTransparency());
  2297.                 } else {
  2298.                     int iW = bgImage.getWidth();
  2299.                     int iH = bgImage.getHeight();
  2300.                     switch (s.getBackgroundType()) {
  2301.                         case Style.BACKGROUND_IMAGE_SCALED:
  2302.                             if (iW != width || iH != height) {
  2303.                                 bgImage = bgImage.scaled(width, height);
  2304.                                 s.setBgImage(bgImage, true);
  2305.                             }
  2306.                             g.drawImage(s.getBgImage(), x, y);
  2307.                             return;
  2308.                         case Style.BACKGROUND_IMAGE_TILE_BOTH:
  2309.                             for (int xPos = 0; xPos <= width; xPos += iW) {
  2310.                                 for (int yPos = 0; yPos <= height; yPos += iH) {
  2311.                                     g.drawImage(s.getBgImage(), x + xPos, y + yPos);
  2312.                                 }
  2313.                             }
  2314.                             return;
  2315.                         case Style.BACKGROUND_IMAGE_TILE_HORIZONTAL:
  2316.                             for (int xPos = 0; xPos <= width; xPos += iW) {
  2317.                                 g.drawImage(s.getBgImage(), x + xPos, y);
  2318.                             }
  2319.                             return;
  2320.                         case Style.BACKGROUND_IMAGE_TILE_VERTICAL:
  2321.                             for (int yPos = 0; yPos <= height; yPos += iH) {
  2322.                                 g.drawImage(s.getBgImage(), x, y + yPos);
  2323.                             }
  2324.                             return;
  2325.                         case Style.BACKGROUND_IMAGE_ALIGNED:
  2326.                             switch (s.getBackgroundAlignment()) {
  2327.                                 case Style.BACKGROUND_IMAGE_ALIGN_BOTTOM:
  2328.                                     g.drawImage(s.getBgImage(), x + width - iW, y + (height - iH));
  2329.                                     return;
  2330.                                 case Style.BACKGROUND_IMAGE_ALIGN_TOP:
  2331.                                     g.drawImage(s.getBgImage(), x + width - iW, y);
  2332.                                     return;
  2333.                                 case Style.BACKGROUND_IMAGE_ALIGN_LEFT:
  2334.                                     g.drawImage(s.getBgImage(), x, y + (height / 2 - iH / 2));
  2335.                                     return;
  2336.                                 case Style.BACKGROUND_IMAGE_ALIGN_RIGHT:
  2337.                                     g.drawImage(s.getBgImage(), x + width - iW, y + (height / 2 - iH / 2));
  2338.                                     return;
  2339.                                 case Style.BACKGROUND_IMAGE_ALIGN_CENTER:
  2340.                                     g.drawImage(s.getBgImage(), x + (width / 2 - iW / 2), y + (height / 2 - iH / 2));
  2341.                                     return;
  2342.                             }
  2343.                             return;
  2344.                     }
  2345.                 }
  2346.             }
  2347.         }        
  2348.     }
  2349. }