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

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.plaf;
  26. import com.sun.lwuit.geom.Dimension;
  27. import com.sun.lwuit.Graphics;
  28. import com.sun.lwuit.Image;
  29. import com.sun.lwuit.Button;
  30. import com.sun.lwuit.Component;
  31. import com.sun.lwuit.Display;
  32. import com.sun.lwuit.Label;
  33. import com.sun.lwuit.List;
  34. import com.sun.lwuit.TextArea;
  35. import com.sun.lwuit.list.ListCellRenderer;
  36. import com.sun.lwuit.list.ListModel;
  37. import com.sun.lwuit.Font;
  38. import com.sun.lwuit.TabbedPane;
  39. import com.sun.lwuit.events.FocusListener;
  40. import com.sun.lwuit.geom.Rectangle;
  41. /**
  42.  * Used to render the default look of LWUIT
  43.  *
  44.  * @author Chen Fishbein
  45.  */
  46. public class DefaultLookAndFeel extends LookAndFeel implements FocusListener {
  47.     private Image[] chkBoxImages = null;
  48.     private Image comboImage = null;
  49.     private Image[] rButtonImages = null;
  50.     private boolean tickWhenFocused = true;
  51.     /** Creates a new instance of DefaultLookAndFeel */
  52.     public DefaultLookAndFeel() {
  53.     }
  54.     /**
  55.      * @inheritDoc
  56.      */
  57.     public void bind(Component cmp) {
  58.         if (tickWhenFocused && cmp instanceof Label) {
  59.             ((Label) cmp).addFocusListener(this);
  60.         }
  61.     }
  62.     /**
  63.      * This method allows to set all Labels, Buttons, CheckBoxes, RadioButtons
  64.      * to start ticking when the text is too long. 
  65.      * @param tickWhenFocused
  66.      */
  67.     public void setTickWhenFocused(boolean tickWhenFocused) {
  68.         this.tickWhenFocused = tickWhenFocused;
  69.     }
  70.     /**
  71.      * Sets images for checkbox checked/unchecked modes
  72.      * 
  73.      * @param checked the image to draw in order to represent a checked checkbox
  74.      * @param unchecked the image to draw in order to represent an uncheck checkbox
  75.      */
  76.     public void setCheckBoxImages(Image checked, Image unchecked) {
  77.         if (checked == null || unchecked == null) {
  78.             chkBoxImages = null;
  79.         } else {
  80.             chkBoxImages = new Image[]{unchecked, checked};
  81.         }
  82.     }
  83.     /**
  84.      * Sets image for the combo box dropdown drawing
  85.      * 
  86.      * @param picker picker image
  87.      */
  88.     public void setComboBoxImage(Image picker) {
  89.         comboImage = picker;
  90.     }
  91.     /**
  92.      * Sets images for radio button selected/unselected modes
  93.      * 
  94.      * @param selected the image to draw in order to represent a selected radio button
  95.      * @param unselected the image to draw in order to represent an unselected radio button
  96.      */
  97.     public void setRadioButtonImages(Image selected, Image unselected) {
  98.         if (selected == null || unselected == null) {
  99.             rButtonImages = null;
  100.         } else {
  101.             rButtonImages = new Image[]{unselected, selected};
  102.         }
  103.     }
  104.     /**
  105.      * Returns the images used to represent the radio button (selected followed by unselected).
  106.      * 
  107.      * @return images representing the radio button or null for using the default drawing
  108.      */
  109.     public Image[] getRadioButtonImages() {
  110.         return rButtonImages;
  111.     }
  112.     /**
  113.      * Returns the images used to represent the checkbox (selected followed by unselected).
  114.      *
  115.      * @return images representing the check box or null for using the default drawing
  116.      */
  117.     public Image[] getCheckBoxImages() {
  118.         return chkBoxImages;
  119.     }
  120.     /**
  121.      * @inheritDoc
  122.      */
  123.     public void drawButton(Graphics g, Button b) {
  124.         drawComponent(g, b, b.getIconFromState(), null, 0);
  125.     }
  126.     /**
  127.      * @inheritDoc
  128.      */
  129.     public void drawCheckBox(Graphics g, Button cb) {
  130.         if (chkBoxImages != null) {
  131.             drawComponent(g, cb, cb.getIconFromState(), chkBoxImages[cb.isSelected() ? 1 : 0], 0);
  132.         } else {
  133.             Style style = cb.getStyle();
  134.             // checkbox square needs to be the height and width of the font height even
  135.             // when no text is in the check box this is a good indication of phone DPI
  136.             int height = cb.getStyle().getFont().getHeight();
  137.             drawComponent(g, cb, cb.getIconFromState(), null, height);
  138.             int gradientColor;
  139.             g.setColor(style.getFgColor());
  140.             gradientColor = style.getBgColor();
  141.             int width = height;
  142.             int rectWidth = scaleCoordinate(12f, 16, width);
  143.             int tX = cb.getX();
  144.             if (cb.isRTL()) {
  145.              tX = tX + cb.getWidth() - style.getPadding(cb.isRTL(), Component.LEFT) - rectWidth;
  146.             } else {
  147.              tX += style.getPadding(cb.isRTL(), Component.LEFT);
  148.             }
  149.             int tY = cb.getY() + style.getPadding(false, Component.TOP) + (cb.getHeight() - style.getPadding(false, Component.TOP) - style.getPadding(false, Component.BOTTOM)) / 2 - height / 2;
  150.             g.translate(tX, tY);
  151.             int x = scaleCoordinate(1.04f, 16, width);
  152.             int y = scaleCoordinate(4.0f, 16, height);
  153.             int rectHeight = scaleCoordinate(12f, 16, height);
  154.             // brighten or darken the color slightly
  155.             int destColor = findDestColor(gradientColor);
  156.             g.fillLinearGradient(gradientColor, destColor, x + 1, y + 1, rectWidth - 2, rectHeight - 1, false);
  157.             g.drawRoundRect(x, y, rectWidth, rectHeight, 5, 5);
  158.             if (cb.isSelected()) {
  159.                 int color = g.getColor();
  160.                 g.setColor(0x111111);
  161.                 g.translate(0, 1);
  162.                 fillCheckbox(g, width, height);
  163.                 g.setColor(color);
  164.                 g.translate(0, -1);
  165.                 fillCheckbox(g, width, height);
  166.             }
  167.             g.translate(-tX, -tY);
  168.         }
  169.     }
  170.     private static void fillCheckbox(Graphics g, int width, int height) {
  171.         int x1 = scaleCoordinate(2.0450495f, 16, width);
  172.         int y1 = scaleCoordinate(9.4227722f, 16, height);
  173.         int x2 = scaleCoordinate(5.8675725f, 16, width);
  174.         int y2 = scaleCoordinate(13.921746f, 16, height);
  175.         int x3 = scaleCoordinate(5.8675725f, 16, width);
  176.         int y3 = scaleCoordinate(11f, 16, height);
  177.         g.fillTriangle(x1, y1, x2, y2, x3, y3);
  178.         x1 = scaleCoordinate(14.38995f, 16, width);
  179.         y1 = scaleCoordinate(0, 16, height);
  180.         g.fillTriangle(x1, y1, x2, y2, x3, y3);
  181.     }
  182.     private static int round(float x) {
  183.         int rounded = (int) x;
  184.         if (x - rounded > 0.5f) {
  185.             return rounded + 1;
  186.         }
  187.         return rounded;
  188.     }
  189.     /**
  190.      * Takes a floating point coordinate on a virtual axis and rusterizes it to 
  191.      * a coordinate in the pixel surface. This is a very simple algorithm since
  192.      * anti-aliasing isn't supported.
  193.      * 
  194.      * @param coordinate a position in a theoretical plain
  195.      * @param plain the amount of space in the theoretical plain
  196.      * @param pixelSize the amount of pixels available on the screen
  197.      * @return the pixel which we should color
  198.      */
  199.     private static int scaleCoordinate(float coordinate, float plain, int pixelSize) {
  200.         return round(coordinate / plain * pixelSize);
  201.     }
  202.     /**
  203.      * @inheritDoc
  204.      */
  205.     public void drawLabel(Graphics g, Label l) {
  206.         drawComponent(g, l, l.getIcon(), null, 0);
  207.     }
  208.     /**
  209.      * @inheritDoc
  210.      */
  211.     public void drawRadioButton(Graphics g, Button rb) {
  212.         if (rButtonImages != null) {
  213.             drawComponent(g, rb, rb.getIconFromState(), rButtonImages[rb.isSelected() ? 1 : 0], 0);
  214.         } else {
  215.             Style style = rb.getStyle();
  216.             // radio button radius needs to be of the size of the font height even
  217.             // when no text is in the radio button this is a good indication of phone DPI
  218.             int height = rb.getStyle().getFont().getHeight();
  219.             drawComponent(g, rb, rb.getIconFromState(), null, height + rb.getGap());
  220.             g.setColor(style.getFgColor());
  221.             int x = rb.getX();
  222.             if (rb.isRTL()) {
  223.              x = x + rb.getWidth() - style.getPadding(rb.isRTL(), Component.LEFT) - height;
  224.             } else {
  225.              x += style.getPadding(rb.isRTL(), Component.LEFT);
  226.             }
  227.             int y = rb.getY();
  228.             // center the RadioButton
  229.             y += Math.max(0, rb.getHeight() / 2 - height / 2);
  230.             g.drawArc(x, y, height, height, 0, 360);
  231.             if (rb.isSelected()) {
  232.                 int color = g.getColor();
  233.                 int destColor = findDestColor(color);
  234.                 g.fillRadialGradient(color, destColor, x + 3, y + 3, height - 5, height - 5);
  235.             }
  236.         }
  237.     }
  238.     /**
  239.      * @inheritDoc
  240.      */
  241.     public void drawComboBox(Graphics g, List cb) {
  242.         int border = 2;
  243.         Style style = cb.getStyle();
  244.         int leftPadding = style.getPadding(cb.isRTL(), Component.LEFT);
  245.         int rightPadding = style.getPadding(cb.isRTL(), Component.RIGHT);
  246.         setFG(g, cb);
  247.         ListModel model = cb.getModel();
  248.         ListCellRenderer renderer = cb.getRenderer();
  249.         Object value = model.getItemAt(model.getSelectedIndex());
  250.         int comboImageWidth;
  251.         if (comboImage != null) {
  252.             comboImageWidth = comboImage.getWidth();
  253.         } else {
  254.             comboImageWidth = style.getFont().getHeight();
  255.         }
  256.         
  257.         int cellX = cb.getX() + style.getPadding(false, Component.TOP);
  258.         if(cb.isRTL()){
  259.             cellX += comboImageWidth;
  260.         }
  261.         
  262.         if (model.getSize() > 0) {
  263.             Component cmp = renderer.getListCellRendererComponent(cb, value, model.getSelectedIndex(), cb.hasFocus());
  264.             cmp.setX(cellX);
  265.             cmp.setY(cb.getY() + style.getPadding(false, Component.TOP));
  266.             cmp.setWidth(cb.getWidth() - comboImageWidth - 2 * rightPadding - leftPadding);
  267.             cmp.setHeight(cb.getHeight() - style.getPadding(false, Component.TOP) - style.getPadding(false, Component.BOTTOM));
  268.             cmp.paint(g);
  269.         }
  270.         g.setColor(style.getBgColor());
  271.         int y = cb.getY();
  272.         int height = cb.getHeight();
  273.         int width = comboImageWidth + border;
  274.         int x = cb.getX();
  275.         if (cb.isRTL()) {
  276.          x += leftPadding;
  277.         } else {
  278.          x += cb.getWidth() - comboImageWidth - rightPadding - border;
  279.         }
  280.         if (comboImage != null) {
  281.             g.drawImage(comboImage, x, y + height / 2 - comboImage.getHeight() / 2);
  282.         } else {
  283.             int color = g.getColor();
  284.             // brighten or darken the color slightly
  285.             int destColor = findDestColor(color);
  286.             g.fillLinearGradient(g.getColor(), destColor, x, y, width, height, false);
  287.             g.setColor(color);
  288.             g.drawRect(x, y, width, height - 1);
  289.             width--;
  290.             height--;
  291.             //g.drawRect(x, y, width, height);
  292.             g.translate(x + 1, y + 1);
  293.             g.setColor(0x111111);
  294.             int x1 = scaleCoordinate(2.5652081f, 16, width);
  295.             int y1 = scaleCoordinate(4.4753664f, 16, height);
  296.             int x2 = scaleCoordinate(8.2872691f, 16, width);
  297.             int y2 = scaleCoordinate(10f, 16, height);
  298.             int x3 = scaleCoordinate(13.516078f, 16, width);
  299.             int y3 = y1;
  300.             g.fillTriangle(x1, y1, x2, y2, x3, y3);
  301.             g.translate(-1, -1);
  302.             g.setColor(style.getFgColor());
  303.             g.fillTriangle(x1, y1, x2, y2, x3, y3);
  304.             //g.setColor(style.getFgColor());
  305.             //g.fillTriangle(x1 + 2, y1 + 2, x2, y2 - 2, x3 - 2, y3 + 2);
  306.             g.translate(-x, -y);
  307.         }
  308.     }
  309.     /**
  310.      * Finds a suitable destination color for gradient values
  311.      */
  312.     private int findDestColor(int color) {
  313.         // brighten or darken the color slightly
  314.         int sourceR = color >> 16 & 0xff;
  315.         int sourceG = color >> 8 & 0xff;
  316.         int sourceB = color & 0xff;
  317.         if (sourceR > 128 && sourceG > 128 && sourceB > 128) {
  318.             // darken
  319.             sourceR = Math.max(sourceR >> 1, 0);
  320.             sourceG = Math.max(sourceG >> 1, 0);
  321.             sourceB = Math.max(sourceB >> 1, 0);
  322.         } else {
  323.             // special case for black, since all channels are 0 it can't be brightened properly...
  324.             if(color == 0) {
  325.                 return 0x222222;
  326.             }
  327.             
  328.             // brighten
  329.             sourceR = Math.min(sourceR << 1, 0xff);
  330.             sourceG = Math.min(sourceG << 1, 0xff);
  331.             sourceB = Math.min(sourceB << 1, 0xff);
  332.         }
  333.         return ((sourceR << 16) & 0xff0000) | ((sourceG << 8) & 0xff00) | (sourceB & 0xff);
  334.     }
  335.     /**
  336.      * @inheritDoc
  337.      */
  338.     public void drawList(Graphics g, List l) {
  339.     }
  340.     /**
  341.      * @inheritDoc
  342.      */
  343.     public void drawTextArea(Graphics g, TextArea ta) {
  344.         setFG(g, ta);
  345.         int line = ta.getLines();
  346.         int oX = g.getClipX();
  347.         int oY = g.getClipY();
  348.         int oWidth = g.getClipWidth();
  349.         int oHeight = g.getClipHeight();
  350.         Font f = ta.getStyle().getFont();
  351.         int fontHeight = f.getHeight();
  352.         int align = ta.getAbsoluteAlignment();
  353.         int leftPadding = ta.getStyle().getPadding(ta.isRTL(), Component.LEFT);
  354.         int rightPadding = ta.getStyle().getPadding(ta.isRTL(), Component.RIGHT);
  355.         int topPadding = ta.getStyle().getPadding(false, Component.TOP);
  356.         boolean shouldBreak = false;
  357.         
  358.         for (int i = 0; i < line; i++) {
  359.             int x = ta.getX() + leftPadding;
  360.             int y = ta.getY() +  topPadding +
  361.                     (ta.getRowsGap() + fontHeight) * i;
  362.             if(Rectangle.intersects(x, y, ta.getWidth(), fontHeight, oX, oY, oWidth, oHeight)) {
  363.                 
  364.                 String rowText = (String) ta.getTextAt(i);
  365.                 //display ******** if it is a password field
  366.                 String displayText = "";
  367.                 if ((ta.getConstraint() & TextArea.PASSWORD) != 0) {
  368.                     for (int j = 0; j < rowText.length(); j++) {
  369.                         displayText += "*";
  370.                     }
  371.                 } else {
  372.                     displayText = rowText;
  373.                 }
  374.                 switch(align) {
  375.                     case Component.RIGHT:
  376.                  x = ta.getX() + ta.getWidth() - rightPadding - f.stringWidth(displayText);
  377.                         break;
  378.                     case Component.CENTER:
  379.                         x+= (ta.getWidth()-leftPadding-rightPadding-f.stringWidth(displayText))/2;
  380.                         break;
  381.                 }
  382.             
  383.                 g.drawString(displayText, x, y);
  384.                 shouldBreak = true;
  385.             }else{
  386.                 if(shouldBreak){
  387.                     break;
  388.                 }
  389.             }
  390.         }
  391.     }
  392.     /**
  393.      * @inheritDoc
  394.      */
  395.     public Dimension getButtonPreferredSize(Button b) {
  396.         return getPreferredSize(b, new Image[]{b.getIcon(), b.getRolloverIcon(), b.getPressedIcon()}, null);
  397.     }
  398.     /**
  399.      * @inheritDoc
  400.      */
  401.     public Dimension getCheckBoxPreferredSize(Button cb) {
  402.         if (chkBoxImages != null) {
  403.             return getPreferredSize(cb, new Image[]{cb.getIcon(), cb.getRolloverIcon(), cb.getPressedIcon()}, chkBoxImages[0]);
  404.         }
  405.         Dimension d = getPreferredSize(cb, new Image[]{cb.getIcon(), cb.getRolloverIcon(), cb.getPressedIcon()}, null);
  406.         // checkbox square needs to be the height and width of the font height even
  407.         // when no text is in the check box this is a good indication of phone DPI
  408.         int checkBoxSquareSize = cb.getStyle().getFont().getHeight();
  409.         // allow for checkboxes without a string within them
  410.         d.setHeight(Math.max(checkBoxSquareSize, d.getHeight()));
  411.         d.setWidth(d.getWidth() + checkBoxSquareSize + cb.getGap());
  412.         return d;
  413.     }
  414.     /**
  415.      * @inheritDoc
  416.      */
  417.     public Dimension getLabelPreferredSize(Label l) {
  418.         return getPreferredSize(l, new Image[]{l.getIcon()}, null);
  419.     }
  420.     /**
  421.      * @inheritDoc
  422.      */
  423.     private Dimension getPreferredSize(Label l, Image[] icons, Image stateImage) {
  424.         int prefW = 0;
  425.         int prefH = 0;
  426.         Style style = l.getStyle();
  427.         int gap = l.getGap();
  428.         for (int i = 0; i < icons.length; i++) {
  429.             Image icon = icons[i];
  430.             if (icon != null) {
  431.                 prefW = Math.max(prefW, icon.getWidth());
  432.                 prefH = Math.max(prefH, icon.getHeight());
  433.             }
  434.         }
  435.         String text = l.getText();
  436.         Font font = style.getFont();
  437.         if (font == null) {
  438.             System.out.println("Missing font for " + l);
  439.             font = Font.getDefaultFont();
  440.         }
  441.         if (text != null && text.length() > 0) {
  442.             //add the text size
  443.             switch (l.getTextPosition()) {
  444.                 case Label.LEFT:
  445.                 case Label.RIGHT:
  446.                     prefW += font.stringWidth(text);
  447.                     prefH = Math.max(prefH, font.getHeight());
  448.                     break;
  449.                 case Label.BOTTOM:
  450.                 case Label.TOP:
  451.                     prefW = Math.max(prefW, font.stringWidth(text));
  452.                     prefH += font.getHeight();
  453.                     break;
  454.             }
  455.         }
  456.         //add the state image(relevant for CheckBoxRadioButton)
  457.         if (stateImage != null) {
  458.             prefW += (stateImage.getWidth() + gap);
  459.             prefH = Math.max(prefH, stateImage.getHeight());
  460.         }
  461.         if (icons[0] != null && text != null && text.length() > 0) {
  462.             switch (l.getTextPosition()) {
  463.                 case Label.LEFT:
  464.                 case Label.RIGHT:
  465.                     prefW += gap;
  466.                     break;
  467.                 case Label.BOTTOM:
  468.                 case Label.TOP:
  469.                     prefH += gap;
  470.                     break;
  471.             }
  472.         }
  473.         if (prefH != 0) {
  474.             prefH += (style.getPadding(false, Component.TOP) + style.getPadding(false, Component.BOTTOM));
  475.         }
  476.         if (prefW != 0) {
  477.             prefW += (style.getPadding(l.isRTL(), Component.RIGHT) + style.getPadding(l.isRTL(), Component.LEFT));
  478.         }
  479.         return new Dimension(prefW, prefH);
  480.     }
  481.     /**
  482.      * @inheritDoc
  483.      */
  484.     public Dimension getListPreferredSize(List l) {
  485.         int width = 0;
  486.         int height = 0;
  487.         int selectedHeight;
  488.         int selectedWidth;
  489.         ListModel model = l.getModel();
  490.         int numOfcomponents = Math.max(model.getSize(), l.getMinElementHeight());
  491.         Object prototype = l.getRenderingPrototype();
  492.         Style unselectedEntryStyle = null;
  493.         Style selectedEntryStyle;
  494.         if(prototype != null) {
  495.             ListCellRenderer renderer = l.getRenderer();
  496.             Component cmp = renderer.getListCellRendererComponent(l, prototype, 0, false);
  497.             height = cmp.getPreferredH();
  498.             width = cmp.getPreferredW();
  499.             unselectedEntryStyle = cmp.getStyle();
  500.             cmp = renderer.getListCellRendererComponent(l, prototype, 0, true);
  501.             selectedEntryStyle = cmp.getStyle();
  502.             selectedHeight = Math.max(height, cmp.getPreferredH());
  503.             selectedWidth = Math.max(width, cmp.getPreferredW());
  504.         } else {
  505.             int hightCalcComponents = Math.min(5, numOfcomponents);
  506.             Object dummyProto = l.getRenderingPrototype();
  507.             if(model.getSize() > 0 && dummyProto == null) {
  508.                 dummyProto = model.getItemAt(0);
  509.             }
  510.             ListCellRenderer renderer = l.getRenderer();
  511.             for (int i = 0; i < hightCalcComponents; i++) {
  512.                 Object value;
  513.                 if(i < model.getSize()) {
  514.                     value = model.getItemAt(i);
  515.                 } else {
  516.                     value = dummyProto;
  517.                 }
  518.                 Component cmp = renderer.getListCellRendererComponent(l, value, i, false);
  519.                 unselectedEntryStyle = cmp.getStyle();
  520.                 height = Math.max(height, cmp.getPreferredH());
  521.                 width = Math.max(width, cmp.getPreferredW());
  522.             }
  523.             selectedEntryStyle = unselectedEntryStyle;
  524.             selectedHeight = height;
  525.             selectedWidth = width;
  526.             if (model.getSize() > 0) {
  527.                 Object value = model.getItemAt(0);
  528.                 Component cmp = renderer.getListCellRendererComponent(l, value, 0, true);
  529.                 selectedHeight = Math.max(height, cmp.getPreferredH());
  530.                 selectedWidth = Math.max(width, cmp.getPreferredW());
  531.                 selectedEntryStyle = cmp.getStyle();
  532.             }
  533.         }
  534.         if(unselectedEntryStyle != null) {
  535.             selectedWidth += selectedEntryStyle.getMargin(false, Component.LEFT) + selectedEntryStyle.getMargin(false, Component.RIGHT);
  536.             selectedHeight += selectedEntryStyle.getMargin(false, Component.TOP) + selectedEntryStyle.getMargin(false, Component.BOTTOM);
  537.             width += unselectedEntryStyle.getMargin(false, Component.LEFT) + unselectedEntryStyle.getMargin(false, Component.RIGHT);
  538.             height += unselectedEntryStyle.getMargin(false, Component.TOP) + unselectedEntryStyle.getMargin(false, Component.BOTTOM);
  539.         }
  540.         Style lStyle = l.getStyle();
  541.         int verticalPadding = lStyle.getPadding(false, Component.TOP) + lStyle.getPadding(false, Component.BOTTOM);
  542.         int horizontalPadding = lStyle.getPadding(false, Component.RIGHT) + lStyle.getPadding(false, Component.LEFT);
  543.         if (numOfcomponents == 0) {
  544.             return new Dimension(horizontalPadding, verticalPadding);
  545.         }
  546.         // If combobox without ever importing the ComboBox class dependency
  547.         if(l.getOrientation() > List.HORIZONTAL) {
  548.             int boxWidth = l.getStyle().getFont().getHeight() + 2;
  549.             return new Dimension(boxWidth + selectedWidth + horizontalPadding, selectedHeight + verticalPadding);
  550.         } else {
  551.             if (l.getOrientation() == List.VERTICAL) {
  552.                 return new Dimension(selectedWidth + horizontalPadding, selectedHeight + (height + l.getItemGap()) * (numOfcomponents - 1) + verticalPadding);
  553.             } else {
  554.                 return new Dimension(selectedWidth + (width + l.getItemGap()) * (numOfcomponents - 1) + horizontalPadding, selectedHeight + verticalPadding);
  555.             }
  556.         }
  557.     }
  558.     
  559.     /**
  560.      * @inheritDoc
  561.      */
  562.     public Dimension getRadioButtonPreferredSize(Button rb) {
  563.         if (rButtonImages != null) {
  564.             return getPreferredSize(rb, new Image[]{rb.getIcon(), rb.getRolloverIcon(), rb.getPressedIcon()}, rButtonImages[0]);
  565.         }
  566.         Dimension d = getPreferredSize(rb, new Image[]{rb.getIcon(), rb.getRolloverIcon(), rb.getPressedIcon()}, null);
  567.         // radio button radius needs to be of the size of the font height even
  568.         // when no text is in the radio button this is a good indication of phone DPI
  569.         int height = rb.getStyle().getFont().getHeight();
  570.         // allow for radio buttons without a string within them
  571.         d.setHeight(Math.max(height, d.getHeight()));
  572.         d.setWidth(d.getWidth() + height + rb.getGap());
  573.         return d;
  574.     }
  575.     /**
  576.      * @inheritDoc
  577.      */
  578.     public Dimension getTextAreaSize(TextArea ta, boolean pref) {
  579.         int prefW = 0;
  580.         int prefH = 0;
  581.         Font f = ta.getStyle().getFont();
  582.         //if this is a text field the preferred size should be the text width
  583.         if (ta.getRows() == 1) {
  584.             prefW = f.stringWidth(ta.getText());
  585.         } else {
  586.             prefW = f.charWidth(TextArea.getWidestChar()) * ta.getColumns();
  587.         }
  588.         int rows;
  589.         if(pref) {
  590.             rows = ta.getActualRows();
  591.         } else {
  592.             rows = ta.getLines();
  593.         }
  594.         prefH = (f.getHeight() + 2) * rows;
  595.         int columns = ta.getColumns();
  596.         String str = "";
  597.         for (int iter = 0; iter < columns; iter++) {
  598.             str += TextArea.getWidestChar();
  599.         }
  600.         if(columns > 0) {
  601.             prefW = Math.max(prefW, f.stringWidth(str));
  602.         }
  603.         prefH = Math.max(prefH, rows * f.getHeight());
  604.         return new Dimension(prefW + ta.getStyle().getPadding(false, Component.RIGHT) + ta.getStyle().getPadding(false, Component.LEFT), 
  605.                 prefH + ta.getStyle().getPadding(false, Component.TOP) + ta.getStyle().getPadding(false, Component.BOTTOM));
  606.     }
  607.     /**
  608.      * Reverses alignment in the case of bidi
  609.      */
  610.     private int reverseAlignForBidi(Component c, int align) {
  611.         if(c.isRTL()) {
  612.             switch(align) {
  613.                 case Component.RIGHT:
  614.                     return Component.LEFT;
  615.                 case Component.LEFT:
  616.                     return Component.RIGHT;
  617.             }
  618.         }
  619.         return align;
  620.     }
  621.     private void drawComponent(Graphics g, Label l, Image icon, Image stateIcon, int preserveSpaceForState) {
  622.         setFG(g, l);
  623.         int gap = l.getGap();
  624.         int stateIconSize = 0;
  625.         int stateIconYPosition = 0;
  626.         String text = l.getText();
  627.         Style style = l.getStyle();
  628.         int leftPadding = style.getPadding(l.isRTL(), Component.LEFT);
  629.         int rightPadding = style.getPadding(l.isRTL(), Component.RIGHT);
  630.         
  631.         Font font = style.getFont();
  632.         int fontHeight = 0;
  633.         if (text == null) {
  634.             text = "";
  635.         }
  636.         if(text.length() > 0){
  637.             fontHeight = font.getHeight();
  638.         }
  639.         
  640.         if (stateIcon != null) {
  641.             stateIconSize = stateIcon.getWidth(); //square image width == height
  642.             stateIconYPosition = l.getY() + l.getStyle().getPadding(false, Component.TOP) +
  643.                     (l.getHeight() - l.getStyle().getPadding(false, Component.TOP) -
  644.                     l.getStyle().getPadding(false, Component.BOTTOM)) / 2 - stateIconSize / 2;
  645.             preserveSpaceForState = stateIconSize + gap;
  646.             int tX = l.getX();
  647.             if (l.isRTL()) {
  648.              tX = tX + l.getWidth() - style.getPadding(l.isRTL(), Component.LEFT) - stateIcon.getWidth();
  649.             } else {
  650.              tX += style.getPadding(l.isRTL(), Component.LEFT);
  651.             }
  652.             g.drawImage(stateIcon, tX, stateIconYPosition);
  653.         }
  654.         //default for bottom left alignment
  655.         int x = l.getX() + l.getStyle().getPadding(l.isRTL(), Component.LEFT) + preserveSpaceForState;
  656.         int y = l.getY() + l.getStyle().getPadding(false, Component.TOP);
  657.         int align = reverseAlignForBidi(l, l.getAlignment());
  658.         int textPos= reverseAlignForBidi(l, l.getTextPosition());
  659.         //set initial x,y position according to the alignment and textPosition
  660.         if (align == Component.LEFT) {
  661.             switch (textPos) {
  662.                 case Label.LEFT:
  663.                 case Label.RIGHT:
  664.                     y = y + (l.getHeight() - (l.getStyle().getPadding(false, Component.TOP) + l.getStyle().getPadding(false, Component.BOTTOM) + Math.max(((icon != null) ? icon.getHeight() : 0), fontHeight))) / 2;
  665.                     break;
  666.                 case Label.BOTTOM:
  667.                 case Label.TOP:
  668.                     y = y + (l.getHeight() - (l.getStyle().getPadding(false, Component.TOP) + l.getStyle().getPadding(false, Component.BOTTOM) + ((icon != null) ? icon.getHeight() + gap : 0) + fontHeight)) / 2;
  669.                     break;
  670.             }
  671.         } else if (align == Component.CENTER) {
  672.             switch (textPos) {
  673.                 case Label.LEFT:
  674.                 case Label.RIGHT:
  675.                     x = x + (l.getWidth() - (preserveSpaceForState +
  676.                             leftPadding +
  677.                             rightPadding +
  678.                             ((icon != null) ? icon.getWidth() : 0) +
  679.                             font.stringWidth(text))) / 2;
  680.                     x = Math.max(x, l.getX() + leftPadding + preserveSpaceForState);
  681.                     y = y + (l.getHeight() - (style.getPadding(false, Component.TOP) +
  682.                             style.getPadding(false, Component.BOTTOM) +
  683.                             Math.max(((icon != null) ? icon.getHeight() : 0),
  684.                             fontHeight))) / 2;
  685.                     break;
  686.                 case Label.BOTTOM:
  687.                 case Label.TOP:
  688.                     x = x + (l.getWidth() - (preserveSpaceForState + leftPadding +
  689.                             rightPadding +
  690.                             Math.max(((icon != null) ? icon.getWidth() : 0),
  691.                             font.stringWidth(text)))) / 2;
  692.                     x = Math.max(x, l.getX() + leftPadding + preserveSpaceForState);
  693.                     y = y + (l.getHeight() - (style.getPadding(false, Component.TOP) +
  694.                             style.getPadding(false, Component.BOTTOM) +
  695.                             ((icon != null) ? icon.getHeight() + gap : 0) +
  696.                             fontHeight)) / 2;
  697.                     break;
  698.             }
  699.         } else if (align == Component.RIGHT) {
  700.             switch (textPos) {
  701.                 case Label.LEFT:
  702.                 case Label.RIGHT:
  703.                     x = l.getX() + l.getWidth() - rightPadding -
  704.                             ( ((icon != null) ? (icon.getWidth() + gap) : 0) +
  705.                             font.stringWidth(text));
  706.                     if(l.isRTL()) {
  707.                         x = Math.max(x - preserveSpaceForState, l.getX() + leftPadding);
  708.                     } else {
  709.                         x = Math.max(x, l.getX() + leftPadding + preserveSpaceForState);
  710.                     }
  711.                     y = y + (l.getHeight() - (style.getPadding(false, Component.TOP) +
  712.                             style.getPadding(false, Component.BOTTOM) +
  713.                             Math.max(((icon != null) ? icon.getHeight() : 0),
  714.                             fontHeight))) / 2;
  715.                     break;
  716.                 case Label.BOTTOM:
  717.                 case Label.TOP:
  718.                     x = l.getX() + l.getWidth() - rightPadding -
  719.                              (Math.max(((icon != null) ? (icon.getWidth()) : 0),
  720.                             font.stringWidth(text)));
  721.                     x = Math.max(x, l.getX() + leftPadding + preserveSpaceForState);
  722.                     y = y + (l.getHeight() - (style.getPadding(false, Component.TOP) +
  723.                             style.getPadding(false, Component.BOTTOM) +
  724.                             ((icon != null) ? icon.getHeight() + gap : 0) + fontHeight)) / 2;
  725.                     break;
  726.             }
  727.         }
  728.         int textSpaceW = l.getWidth() - style.getPadding(false, Label.RIGHT) - style.getPadding(false, Label.LEFT);
  729.         if (icon != null && (textPos == Label.RIGHT || textPos == Label.LEFT)) {
  730.             textSpaceW = textSpaceW - icon.getWidth();
  731.         }
  732.         if (stateIcon != null) {
  733.             textSpaceW = textSpaceW - stateIcon.getWidth();
  734.         } else {
  735.             textSpaceW = textSpaceW - preserveSpaceForState;
  736.         }
  737.         if (icon == null) { // no icon only string 
  738.             drawLabelString(g, l, text, x, y, textSpaceW, preserveSpaceForState);
  739.         } else {
  740.             //int strHeight = l.getStyle().getFont().getHeight();
  741.             int strWidth = l.getStyle().getFont().stringWidth(text);
  742.             int iconWidth = icon.getWidth();
  743.             int iconHeight = icon.getHeight();
  744.             int iconStringWGap;
  745.             int iconStringHGap;
  746.             switch (textPos) {
  747.                 case Label.LEFT:
  748.                     if (iconHeight > fontHeight) {
  749.                         iconStringHGap = (iconHeight - fontHeight) / 2;
  750.                         //drawLabelStringValign(g, l, text, x, y, iconStringHGap, iconHeight);
  751.                         strWidth = drawLabelStringValign(g, l, text, x, y, iconStringHGap, iconHeight, textSpaceW, fontHeight, preserveSpaceForState);
  752.                         g.drawImage(icon, x + strWidth + gap, y);
  753.                     } else {
  754.                         iconStringHGap = (fontHeight - iconHeight) / 2;
  755.                         //drawLabelString(g, l, text, x, y);
  756.                         strWidth = drawLabelString(g, l, text, x, y, textSpaceW, preserveSpaceForState);
  757.                         g.drawImage(icon, x + strWidth + gap, y + iconStringHGap);
  758.                     }
  759.                     break;
  760.                 case Label.RIGHT:
  761.                     if (iconHeight > fontHeight) {
  762.                         iconStringHGap = (iconHeight - fontHeight) / 2;
  763.                         g.drawImage(icon, x, y);
  764.                         //drawLabelStringValign(g, l, text, x+ iconWidth + gap, y, iconStringHGap, iconHeight);
  765.                         drawLabelStringValign(g, l, text, x + iconWidth + gap, y, iconStringHGap, iconHeight, textSpaceW, fontHeight, preserveSpaceForState);
  766.                     } else {
  767.                         iconStringHGap = (fontHeight - iconHeight) / 2;
  768.                         g.drawImage(icon, x, y + iconStringHGap);
  769.                         //drawLabelString(g, l, text, x + iconWidth + gap, y);
  770.                         drawLabelString(g, l, text, x + iconWidth + gap, y, textSpaceW, preserveSpaceForState);
  771.                     }
  772.                     break;
  773.                 case Label.BOTTOM:
  774.                     if (iconWidth > strWidth) { //center align the smaller
  775.                         iconStringWGap = (iconWidth - strWidth) / 2;
  776.                         g.drawImage(icon, x, y);
  777.                         //drawLabelString(g, l, text, x + iconStringWGap, y + iconHeight + gap);
  778.                         drawLabelString(g, l, text, x + iconStringWGap, y + iconHeight + gap, textSpaceW, preserveSpaceForState);
  779.                     } else {
  780.                         iconStringWGap = (Math.min(strWidth, textSpaceW) - iconWidth) / 2;
  781.                         g.drawImage(icon, x + iconStringWGap, y);
  782.                         
  783.                         //drawLabelString(g, l, text, x, y + iconHeight + gap);
  784.                         drawLabelString(g, l, text, x, y + iconHeight + gap, textSpaceW, preserveSpaceForState);
  785.                     }
  786.                     break;
  787.                 case Label.TOP:
  788.                     if (iconWidth > strWidth) { //center align the smaller
  789.                         iconStringWGap = (iconWidth - strWidth) / 2;
  790. //                        drawLabelString(g, l, text, x + iconStringWGap, y);
  791.                         drawLabelString(g, l, text, x + iconStringWGap, y, textSpaceW, preserveSpaceForState);
  792.                         g.drawImage(icon, x, y + fontHeight + gap);
  793.                     } else {
  794.                         iconStringWGap = (Math.min(strWidth, textSpaceW) - iconWidth) / 2;
  795. //                        drawLabelString(g, l, text, x, y);
  796.                         drawLabelString(g, l, text, x, y, textSpaceW, preserveSpaceForState);
  797.                         g.drawImage(icon, x + iconStringWGap, y + fontHeight + gap);
  798.                     }
  799.                     break;
  800.             }
  801.         }
  802.     }
  803.     /**
  804.      * Implements the drawString for the text component and adjust the valign
  805.      * assuming the icon is in one of the sides
  806.      */
  807.     private int drawLabelStringValign(Graphics g, Label l, String str, int x, int y,
  808.             int iconStringHGap, int iconHeight, int textSpaceW, int fontHeight, int preserveSpaceForState) {
  809.         switch (l.getVerticalAlignment()) {
  810.             case Component.TOP:
  811.                 return drawLabelString(g, l, str, x, y, textSpaceW, preserveSpaceForState);
  812.             case Component.CENTER:
  813.                 return drawLabelString(g, l, str, x, y + iconHeight / 2 - fontHeight / 2, textSpaceW, preserveSpaceForState);
  814.             default:
  815.                 return drawLabelString(g, l, str, x, y + iconStringHGap, textSpaceW, preserveSpaceForState);
  816.         }
  817.     }
  818.     /**
  819.      * Implements the drawString for the text component and adjust the valign
  820.      * assuming the icon is in one of the sides
  821.      */
  822.     private int drawLabelString(Graphics g, Label l, String text, int x, int y, int textSpaceW, int preserveSpaceForState) {
  823.         Style style = l.getStyle();
  824.         int cx = g.getClipX();
  825.         int cy = g.getClipY();
  826.         int cw = g.getClipWidth();
  827.         int ch = g.getClipHeight();
  828.         g.clipRect(x, cy, textSpaceW, ch);
  829.         if (l.isTickerRunning()) {
  830.             if (l.getShiftText() > 0) {
  831.                 if (l.getShiftText() > textSpaceW) {
  832.                     l.setShiftText(x - l.getX() - style.getFont().stringWidth(text));
  833.                 }
  834.             } else if (l.getShiftText() + style.getFont().stringWidth(text) < 0) {
  835.                 l.setShiftText(textSpaceW);
  836.             }
  837.         }
  838.         int drawnW = drawLabelText(g, l, text, x, y, textSpaceW);
  839.         g.setClip(cx, cy, cw, ch);
  840.         return drawnW;
  841.     }
  842.     /**
  843.      * Draws the text of a label
  844.      * 
  845.      * @param g graphics context
  846.      * @param l label component
  847.      * @param text the text for the label
  848.      * @param x position for the label
  849.      * @param y position for the label
  850.      * @param textSpaceW the width available for the component
  851.      * @return the space used by the drawing
  852.      */
  853.     protected int drawLabelText(Graphics g, Label l, String text, int x, int y, int textSpaceW) {
  854.         Font f = l.getStyle().getFont();
  855.         if ((!l.isTickerRunning()) || l.isRTL()) {
  856.             int txtW = f.stringWidth(text);
  857.             
  858.             //if there is no space to draw the text add ... at the end
  859.             if (txtW > textSpaceW && textSpaceW > 0) {
  860.              // Handling of adding 3 points and in fact all text positioning when the text is bigger than
  861.              // the allowed space is handled differently in RTL, this is due to the reverse algorithm
  862.              // effects - i.e. when the text includes both Hebrew/Arabic and English/numbers then simply
  863.              // trimming characters from the end of the text (as done with LTR) won't do.
  864.              // Instead we simple reposition the text, and draw the 3 points, this is quite simple, but
  865.              // the downside is that a part of a letter may be shown here as well.
  866.              if (l.isRTL()) {
  867.                  if ((!l.isTickerRunning()) && (l.isEndsWith3Points())) {
  868.              String points = "...";
  869.                  int pointsW = f.stringWidth(points);
  870.              g.drawString(points, l.getShiftText() + x, y);
  871.              g.clipRect(pointsW+l.getShiftText() + x, y, textSpaceW - pointsW, f.getHeight());
  872.                  }
  873.              x = x - txtW + textSpaceW;
  874.                 } else {
  875.                     if (l.isEndsWith3Points()) {
  876.                         String points = "...";
  877.                         int index = 1;
  878.                         String tmp = text.substring(0, index);
  879.                         int pointsW = f.stringWidth(points);
  880.                         while (f.stringWidth(tmp) + pointsW < textSpaceW) {
  881.                             index++;
  882.                             if (index >= text.length()) {
  883.                                 break;
  884.                             }
  885.                             tmp = text.substring(0, index);
  886.                         }
  887.                         tmp = text.substring(0, index - 1) + points;
  888.                         text = tmp;
  889.                     }
  890.                 }
  891.             }
  892.         }
  893.         g.drawString(text, l.getShiftText() + x, y);
  894.         return Math.min(f.stringWidth(text), textSpaceW);
  895.     }
  896.     /**
  897.      * @inheritDoc
  898.      */
  899.     public Dimension getComboBoxPreferredSize(List cb) {
  900.         return getListPreferredSize(cb);
  901.     }
  902.     /**
  903.      * @inheritDoc
  904.      */
  905.     public void drawTabbedPane(Graphics g, TabbedPane tp) {
  906.     }
  907.     /**
  908.      * @inheritDoc
  909.      */
  910.     public Component getTabbedPaneCell(final TabbedPane tp,
  911.             final String text, final Image icon, final boolean isSelected,
  912.             final boolean cellHasFocus, final Style cellStyle, final Style cellSelectedStyle,
  913.             final Style tabbedPaneStyle, final int cellOffsetX,
  914.             final int cellOffsetY, final Dimension cellsPreferredSize,
  915.             final Dimension contentPaneSize) {
  916.         Label cell = new Label(text) {
  917.             public void paint(Graphics g) {
  918.                 int tPBorder = tp.getTabbedPaneBorderWidth();
  919.                 int focusMarkWidth = tPBorder * 2;
  920.                 int tabP = tp.getTabPlacement();
  921.                 // Initialize forground colors before calling to super.paint()
  922.                 if (isSelected && cellHasFocus) {
  923.                     focusMarkWidth = tPBorder * 3;
  924.                     this.getStyle().setFgColor(cellSelectedStyle.getFgColor());
  925.                 } else {
  926.                     this.getStyle().setFgColor(cellStyle.getFgColor());
  927.                 }
  928.                 super.paint(g);
  929.                 if (!isSelected) {
  930.                     g.setColor(0);
  931.                     g.fillRect(getX(), getY(), getWidth(), getHeight(), (byte) 0x2f);
  932.                 }
  933.                 // coloring back the focus mark line
  934.                 g.setColor(getStyle().getFgColor());
  935.                 if (tabP == TabbedPane.TOP || tabP == TabbedPane.BOTTOM) {
  936.                     if (tabP == TabbedPane.TOP) {
  937.                         if (isSelected) {
  938.                             g.fillRect(getX(), getY() + tPBorder, getWidth(), focusMarkWidth);// north
  939.                         }
  940.                         g.setColor(tabbedPaneStyle.getFgColor());
  941.                         g.fillRect(getX(), getY(), getWidth(), tPBorder);//north line
  942.                         g.fillRect(getX(), getY(), tPBorder, getHeight());// west line
  943.                     } else {
  944.                         if (isSelected) {
  945.                             g.fillRect(getX(), getY() + getHeight() - focusMarkWidth, getWidth(), focusMarkWidth);// south
  946.                         }
  947.                         g.setColor(tabbedPaneStyle.getFgColor());
  948.                         g.fillRect(getX(), getY() + getHeight() - tPBorder, getWidth(), tPBorder);//south line
  949.                         g.fillRect(getX(), getY(), tPBorder, getHeight());// west line
  950.                     }
  951.                     int x = getX() - cellOffsetX + getWidth();
  952.                     if (x == contentPaneSize.getWidth()) {
  953.                         g.fillRect(x + cellOffsetX - tPBorder, getY(), tPBorder, getHeight());// east line
  954.                     }
  955.                     if (cellsPreferredSize.getWidth() < contentPaneSize.getWidth() && (getX() + getWidth() == cellsPreferredSize.getWidth())) {
  956.                         g.fillRect(getX() + getWidth() - tPBorder, getY(), tPBorder, getHeight());
  957.                     }
  958.                 } else { // LEFT or RIGHT
  959.                     if (isSelected) {
  960.                         g.fillRect(getX(), getY() + tPBorder, getWidth(), focusMarkWidth);// north
  961.                     }
  962.                     g.setColor(tabbedPaneStyle.getFgColor());
  963.                     g.fillRect(getX(), getY(), getWidth(), tPBorder);
  964.                     int y = getY() - cellOffsetY + getHeight();
  965.                     if (y == contentPaneSize.getHeight()) {
  966.                         g.fillRect(getX(), y + cellOffsetY - tPBorder, getWidth(), tPBorder);
  967.                     }
  968.                     if (cellsPreferredSize.getHeight() < contentPaneSize.getHeight() && (getY() + getHeight() == cellsPreferredSize.getHeight())) {
  969.                         g.fillRect(getX(), getY() + getHeight() - tPBorder, getWidth(), tPBorder);//south line
  970.                     }
  971.                     if (!tp.isRTL() && tabP == TabbedPane.LEFT || 
  972.                             tp.isRTL() && tabP == TabbedPane.RIGHT) {
  973.                         g.fillRect(getX(), getY(), tPBorder, getHeight());// west border
  974.                     } else {
  975.                         g.fillRect(getX() + getWidth() - tPBorder, getY(), tPBorder, getHeight());// east border
  976.                     }
  977.                 }
  978.             }
  979.         };
  980.         cell.setUIID("Tab");
  981.         cell.setCellRenderer(true);
  982.         cell.getStyle().setBorder(null);
  983.         cell.getStyle().setMargin(0, 0, 0, 0);
  984.         cell.setIcon(icon);
  985.         updateCellLook(tp, (Component) cell, isSelected);
  986.         if (isSelected) {
  987.             cellStyle.setBgColor(cellStyle.getBgColor());
  988.         }
  989.         cell.setAlignment(Label.CENTER);
  990.         return cell;
  991.     }
  992.     private void updateCellLook(TabbedPane tp, Component c, boolean selected) {
  993.         c.getStyle().setFgColor(tp.getStyle().getFgColor());
  994.         c.getStyle().setBgTransparency(tp.getStyle().getBgTransparency());
  995.         c.getStyle().setFont(tp.getStyle().getFont());
  996.     }
  997.     /**
  998.      * @inheritDoc
  999.      */
  1000.     public void drawTabbedPaneContentPane(final TabbedPane tp,
  1001.             final Graphics g, final Rectangle rect,
  1002.             final Dimension cellsPreferredSize, final int numOfTabs,
  1003.             final int selectedTabIndex, final Dimension tabsSize,
  1004.             final int cellOffsetX, final int cellOffsetY) {
  1005.         int tPBorder = tp.getTabbedPaneBorderWidth();
  1006.         if(tPBorder < 1) {
  1007.             return;
  1008.         }
  1009.         int x = rect.getX();
  1010.         int y = rect.getY();
  1011.         int w = rect.getSize().getWidth();
  1012.         int h = rect.getSize().getHeight();
  1013.         int listPreferredW = cellsPreferredSize.getWidth();
  1014.         int listPreferredH = cellsPreferredSize.getHeight();
  1015.         int maxTabWidth = tabsSize.getWidth();
  1016.         int maxTabHeight = tabsSize.getHeight();
  1017.         g.setColor(tp.getStyle().getBgColor());
  1018.         g.fillRect(x, y, w, h, tp.getStyle().getBgTransparency());
  1019.         // paint borders for TOP tab placement
  1020.         g.setColor(tp.getStyle().getFgColor());
  1021.         int tabP = tp.getTabPlacement();
  1022.         if (tabP == TabbedPane.TOP || tabP == TabbedPane.BOTTOM) {
  1023.             g.fillRect(x, y, tPBorder, h);// west border
  1024.             g.fillRect(x + w - tPBorder, y, tPBorder, h);// east border
  1025.             int relativeY = y;
  1026.             if (tabP == TabbedPane.BOTTOM) {
  1027.                 relativeY = y + h - tPBorder;
  1028.                 g.fillRect(x, y, w, tPBorder);// north border
  1029.             } else {
  1030.                 g.fillRect(x, y + h - tPBorder, w, tPBorder);// south border
  1031.             }
  1032.             
  1033.             if(tp.isRTL()){
  1034.                 if (listPreferredW < w) {
  1035.                     g.fillRect(x, relativeY, w - listPreferredW, tPBorder);
  1036.                 }
  1037.                 for (int i = 0; i < numOfTabs; i++) {
  1038.                     if (i != selectedTabIndex) {
  1039.                         g.fillRect((x - cellOffsetX + w - (maxTabWidth * (i+1))), relativeY, maxTabWidth + tPBorder, tPBorder);
  1040.                     }
  1041.                 }
  1042.             } else {
  1043.                 if (listPreferredW < w) {
  1044.                     g.fillRect(listPreferredW - tPBorder, relativeY, w - listPreferredW, tPBorder);
  1045.                 }
  1046.                 for (int i = 0; i < numOfTabs; i++) {
  1047.                     if (i != selectedTabIndex) {
  1048.                         g.fillRect((x - cellOffsetX + (maxTabWidth * i)), relativeY, maxTabWidth + tPBorder, tPBorder);
  1049.                     }
  1050.                 }
  1051.             }
  1052.         } else {//if (tabP == LEFT || tabP == RIGHT) {
  1053.             g.fillRect(x, y, w, tPBorder);// north border
  1054.             g.fillRect(x, y + h - tPBorder, w, tPBorder);// south border
  1055.             int relativeX = x;
  1056.             if (!tp.isRTL() && tabP == TabbedPane.RIGHT ||
  1057.                     tp.isRTL() && tabP == TabbedPane.LEFT) {
  1058.                 g.fillRect(x, y, tPBorder, h);// west border
  1059.                 relativeX = x + w - tPBorder;
  1060.             } else {
  1061.                 g.fillRect(x + w - tPBorder, y, tPBorder, h);// east border
  1062.             }
  1063.             if (listPreferredH < h) {
  1064.                 g.fillRect(relativeX, y + listPreferredH - tPBorder, tPBorder, h - listPreferredH + tPBorder);
  1065.             }
  1066.             for (int i = 0; i < numOfTabs; i++) {
  1067.                 if (i != selectedTabIndex) {
  1068.                     g.fillRect(relativeX, (y - cellOffsetY + (maxTabHeight * i)), tPBorder, maxTabHeight + tPBorder);
  1069.                 }
  1070.             }
  1071.         }
  1072.     }
  1073.     /**
  1074.      * Similar to getText() but works properly with password fields
  1075.      */
  1076.     protected String getTextFieldString(TextArea ta) {
  1077.         String text = (String) ta.getText();
  1078.         String displayText = "";
  1079.         if ((ta.getConstraint() & TextArea.PASSWORD) != 0) {
  1080.             // show the last character in a password field
  1081.             if (ta.isPendingCommit()) {
  1082.                 if (text.length() > 0) {
  1083.                     for (int j = 0; j < text.length() - 1; j++) {
  1084.                         displayText += "*";
  1085.                     }
  1086.                     displayText += text.charAt(text.length() - 1);
  1087.                 }
  1088.             } else {
  1089.                 for (int j = 0; j < text.length(); j++) {
  1090.                     displayText += "*";
  1091.                 }
  1092.             }
  1093.         } else {
  1094.             displayText = text;
  1095.         }
  1096.         return displayText;
  1097.     }
  1098.     
  1099.     /**
  1100.      * @inheritDoc
  1101.      */
  1102.     public void drawTextField(Graphics g, TextArea ta) {
  1103.         setFG(g, ta);
  1104.         // display ******** if it is a password field
  1105.         String displayText = getTextFieldString(ta);
  1106.         Style style = ta.getStyle();
  1107.         int x = 0;
  1108.         int cursorCharPosition = ta.getCursorPosition();        
  1109.         Font f = ta.getStyle().getFont();
  1110.         int cursorX = 0;
  1111.         int xPos = 0;
  1112.         
  1113.         int align = ta.getAbsoluteAlignment();
  1114.         int displayX = 0;
  1115.         String inputMode = ta.getInputMode();
  1116.         int inputModeWidth = f.stringWidth(inputMode);
  1117.         // QWERTY devices don't quite have an input mode hide it also when we have a VK
  1118.         if(ta.isQwertyInput() || Display.getInstance().isVirtualKeyboardShowing()) {
  1119.             inputMode = "";
  1120.             inputModeWidth = 0;
  1121.         }
  1122.         // there is currently no support for CENTER aligned text fields
  1123.         if (align == Component.LEFT) {
  1124.             if (cursorCharPosition > 0) {
  1125.                 xPos = f.stringWidth(displayText.substring(0, cursorCharPosition));
  1126.                 cursorX = ta.getX() + style.getPadding(ta.isRTL(), Component.LEFT) + xPos;
  1127.                 // no point in showing the input mode when there is only one input mode...
  1128.                 if(inputModeWidth > 0 && ta.getInputModeOrder() != null && ta.getInputModeOrder().length == 1) {
  1129.                     inputModeWidth = 0;
  1130.                 }
  1131.                 if(ta.isEnableInputScroll()) {
  1132.                     if (ta.getWidth() > (f.getHeight() * 2) && cursorX >= ta.getWidth()-inputModeWidth - style.getPadding(ta.isRTL(), Component.LEFT)) {
  1133.                         while (x + xPos >= ta.getWidth() - inputModeWidth - style.getPadding(ta.isRTL(), Component.LEFT) * 2) {
  1134.                             x--;
  1135.                         }
  1136.                     }
  1137.                 }
  1138.             }
  1139.             displayX = ta.getX() + x + style.getPadding(ta.isRTL(), Component.LEFT);
  1140.         } else {
  1141.      x = 0;
  1142.      cursorX = getTextFieldCursorX(ta);
  1143.      int baseX = ta.getX() + style.getPadding(false, Component.LEFT) + inputModeWidth;
  1144.      int endX = ta.getX() + ta.getWidth() - style.getPadding(false, Component.RIGHT);
  1145.      if(cursorX<baseX) {
  1146.      x = baseX - cursorX;
  1147.      } else {
  1148.                 if (cursorX > endX) {
  1149.          x = endX - cursorX;
  1150.          }
  1151.             }
  1152.      displayX = ta.getX() + ta.getWidth() - style.getPadding(false, Component.RIGHT) - f.stringWidth(displayText)+x;
  1153.         }
  1154.         g.drawString(displayText, displayX, ta.getY() + style.getPadding(false, Component.TOP));
  1155.         // no point in showing the input mode when there is only one input mode...
  1156.         if(inputModeWidth > 0 && ta.getInputModeOrder() != null && ta.getInputModeOrder().length > 1) {
  1157.             
  1158.             if (ta.handlesInput() && ta.getWidth() / 2 > inputModeWidth) {
  1159.             
  1160.                 int drawXPos = ta.getX() + style.getPadding(ta.isRTL(), Component.LEFT);
  1161.                 if((!ta.isRTL() && ta.getAlignment() == Component.LEFT) ||
  1162.                     (ta.isRTL() && ta.getAlignment() == Component.RIGHT)) {
  1163.                     drawXPos = drawXPos + ta.getWidth() - inputModeWidth - style.getPadding(false, Component.RIGHT) - style.getPadding(false, Component.LEFT);
  1164.                 } 
  1165.                 g.setColor(style.getFgColor());
  1166.                 g.fillRect(drawXPos, ta.getY() + style.getPadding(false, Component.TOP), inputModeWidth,
  1167.                         ta.getHeight(), (byte) 140);
  1168.                 g.setColor(style.getBgColor());
  1169.                 g.drawString(inputMode, drawXPos, ta.getY() + style.getPadding(false, Component.TOP));
  1170.             }
  1171.         }
  1172.     }
  1173.     /**
  1174.      * Returns true if the given character is an RTL character or a space
  1175.      * character
  1176.      *
  1177.      * @param c character to test
  1178.      * @return true if bidi is active and this is a
  1179.      */
  1180. private boolean isRTLOrWhitespace(char c) {
  1181.         return (Display.getInstance().isRTL(c)) || c == ' ';
  1182.     }
  1183.     /**
  1184.      * Calculates the position of the text field cursor within the string
  1185.      */
  1186.     private int getTextFieldCursorX(TextArea ta) {
  1187.         Style style = ta.getStyle();
  1188.         Font f = style.getFont();
  1189.         // display ******** if it is a password field
  1190.         String displayText = getTextFieldString(ta);
  1191.         String inputMode = ta.getInputMode();
  1192.         int inputModeWidth = f.stringWidth(inputMode);
  1193.         // QWERTY devices don't quite have an input mode hide it also when we have a VK
  1194.         if(ta.isQwertyInput() || Display.getInstance().isVirtualKeyboardShowing()) {
  1195.             inputMode = "";
  1196.             inputModeWidth = 0;
  1197.         }
  1198.         int xPos = 0;
  1199.         int cursorCharPosition = ta.getCursorPosition();
  1200.         int cursorX=0;
  1201.         int x = 0;
  1202.         if (ta.getAbsoluteAlignment() == Component.RIGHT) {
  1203.          if (Display.getInstance().isBidiAlgorithm()) {
  1204.                 //char[] dest = displayText.toCharArray();
  1205.                 cursorCharPosition = Display.getInstance().getCharLocation(displayText, cursorCharPosition-1);
  1206.                 if (cursorCharPosition==-1) {
  1207.                     xPos = f.stringWidth(displayText);
  1208.                 } else {
  1209.                     displayText = Display.getInstance().convertBidiLogicalToVisual(displayText);
  1210.                     if (!isRTLOrWhitespace((displayText.charAt(cursorCharPosition)))) {
  1211.                         cursorCharPosition++;
  1212.                     }
  1213.                     xPos = f.stringWidth(displayText.substring(0, cursorCharPosition));
  1214.                 } 
  1215.          }
  1216.          int displayX = ta.getX() + ta.getWidth() - style.getPadding(ta.isRTL(), Component.LEFT) - f.stringWidth(displayText);
  1217.          cursorX = displayX + xPos;
  1218.          x=0;
  1219.         } else {
  1220.             if (cursorCharPosition > 0) {
  1221.                 xPos = f.stringWidth(displayText.substring(0, cursorCharPosition));
  1222.             }
  1223.             cursorX = ta.getX() + style.getPadding(ta.isRTL(), Component.LEFT) + xPos;
  1224.             if (ta.getWidth() > (f.getHeight() * 2) && cursorX >= ta.getWidth() - inputModeWidth  -style.getPadding(ta.isRTL(), Component.LEFT)) {
  1225.                 while (x + xPos >= ta.getWidth() - inputModeWidth - style.getPadding(false, Component.LEFT) - style.getPadding(false, Component.RIGHT)) {
  1226.                     x--;
  1227.                 }
  1228.             }
  1229.         }
  1230.         return cursorX+x;
  1231.     }
  1232.     /**
  1233.      * @inheritDoc
  1234.      */
  1235.     public Dimension getTextFieldPreferredSize(TextArea ta) {
  1236.         return getTextAreaSize(ta, true);
  1237.     }
  1238.     /**
  1239.      * @inheritDoc
  1240.      */
  1241.      public void drawTextFieldCursor(Graphics g, TextArea ta) {
  1242.          Style style = ta.getStyle();
  1243.          Font f = style.getFont();
  1244.      int cursorY = ta.getY() + style.getPadding(false, Component.TOP);
  1245.      int cursorX = getTextFieldCursorX(ta);
  1246.         int align=ta.getAbsoluteAlignment();
  1247. int x=0;
  1248.         if (align==Component.RIGHT) {
  1249.             String inputMode = ta.getInputMode();
  1250.             int inputModeWidth = f.stringWidth(inputMode);
  1251.      int baseX=ta.getX()+style.getPadding(false, Component.LEFT)+inputModeWidth;
  1252.      if (cursorX<baseX) {
  1253.      x=baseX-cursorX;
  1254.      }
  1255.         }
  1256.         int oldColor = g.getColor();
  1257.         g.setColor(style.getFgColor());
  1258.         g.drawLine(cursorX + x, cursorY, cursorX + x, cursorY + f.getHeight());
  1259.         g.setColor(oldColor);
  1260.     }
  1261.     /**
  1262.      * @inheritDoc
  1263.      */
  1264.     public void focusGained(Component cmp) {
  1265.         if(cmp instanceof Label) {
  1266.             Label l = (Label) cmp;
  1267.             if (l.shouldTickerStart()) {
  1268.                 ((Label) cmp).startTicker(getTickerSpeed(), true);
  1269.             }
  1270.         }
  1271.     }
  1272.     /**
  1273.      * @inheritDoc
  1274.      */
  1275.     public void focusLost(Component cmp) {
  1276.         if(cmp instanceof Label) {
  1277.             Label l = (Label) cmp;
  1278.             if (l.isTickerRunning()) {
  1279.                 l.stopTicker();
  1280.             }
  1281.         }
  1282.     }
  1283. }