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

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.Component;
  27. import com.sun.lwuit.Graphics;
  28. import com.sun.lwuit.Image;
  29. import com.sun.lwuit.Painter;
  30. import com.sun.lwuit.RGBImage;
  31. import com.sun.lwuit.geom.Rectangle;
  32. import java.lang.ref.WeakReference;
  33. /**
  34.  * Base class that allows us to render a border for a component, a border is drawn before
  35.  * the component and is drawn within the padding region of the component. It is the
  36.  * responsibility of the component not to draw outside of the border line.
  37.  * <p>This class can be extended to provide additional border types and custom made
  38.  * border types.
  39.  * <p>A border can optionally paint the background of the component, this depends on
  40.  * the border type and is generally required for rounded borders that "know" the area
  41.  * that should be filled.
  42.  *
  43.  * @author Shai Almog
  44.  */
  45. public class Border {
  46.     private static Border defaultBorder = Border.createEtchedRaised(0x020202, 0xBBBBBB);
  47.     
  48.     private static final int TYPE_EMPTY = 0;
  49.     private static final int TYPE_LINE = 1;
  50.     private static final int TYPE_ROUNDED = 2;
  51.     private static final int TYPE_ROUNDED_PRESSED = 3;
  52.     private static final int TYPE_ETCHED_LOWERED = 4;
  53.     private static final int TYPE_ETCHED_RAISED = 5;
  54.     private static final int TYPE_BEVEL_RAISED = 6;
  55.     private static final int TYPE_BEVEL_LOWERED = 7;
  56.     private static final int TYPE_IMAGE = 8;
  57.     // variables are package protected for the benefit of the resource editor!
  58.     int type;
  59.     Image[] images;
  60.     
  61.     /**
  62.      * Indicates whether theme colors should be used or whether colors are specified
  63.      * in the border
  64.      */
  65.     boolean themeColors;
  66.     
  67.     int colorA;
  68.     int colorB;
  69.     int colorC;
  70.     int colorD;
  71.     int thickness;
  72.     int arcWidth;
  73.     int arcHeight;
  74.     boolean outline = true;
  75.     Border pressedBorder;
  76.     Border focusBorder;
  77.     
  78.     private static Border empty;
  79.     
  80.     /**
  81.      * Prevents usage of new operator, use the factory methods in the class or subclass
  82.      * to create new border types.
  83.      */
  84.     protected Border() {
  85.     }
  86.     /**
  87.      * Returns an empty border, this is mostly useful for overriding components that
  88.      * have a border by default
  89.      * 
  90.      * @return a border than draws nothing
  91.      * @deprecated use createEmpty instead
  92.      */
  93.     public static Border getEmpty() {
  94.         if(empty == null) {
  95.             empty = new Border();
  96.         }
  97.         return empty;
  98.     }
  99.     
  100.     /**
  101.      * Creates an empty border, this is useful where we don't want a border for a 
  102.      * component but want a focus border etc...
  103.      * 
  104.      * @return a border than draws nothing
  105.      */
  106.     public static Border createEmpty() {
  107.         return new Border();
  108.     }
  109.     
  110.     /**
  111.      * The given images are tiled appropriately across the matching side of the border and placed
  112.      * as expected in the four corners. The background image is optional and it will be tiled in
  113.      * the background if necessary.
  114.      * <p>By default this border does not override background unless a background image is specified
  115.      * 
  116.      * @param top the image of the top line
  117.      * @param bottom the image of the bottom line
  118.      * @param left the image of the left line
  119.      * @param right the image of the right line
  120.      * @param topLeft the image of the top left corner
  121.      * @param topRight the image of the top right corner
  122.      * @param bottomLeft the image of the bottom left corner
  123.      * @param bottomRight the image of the bottom right corner
  124.      * @param background the image of the background (optional)
  125.      * @return new border instance
  126.      */
  127.     public static Border createImageBorder(Image top, Image bottom, Image left, Image right, Image topLeft, Image topRight,
  128.         Image bottomLeft, Image bottomRight, Image background) {
  129.         Border b = new Border();
  130.         b.type = TYPE_IMAGE;
  131.         b.images = new Image[] {top, bottom, left, right, topLeft, topRight, bottomLeft, 
  132.                         bottomRight, background};
  133.         return b;
  134.     }
  135.     
  136.     /**
  137.      * The given images are tiled appropriately across the matching side of the border, rotated and placed
  138.      * as expected in the four corners. The background image is optional and it will be tiled in
  139.      * the background if necessary.
  140.      * <p>By default this border does not override background unless a background image is specified.
  141.      * <p>Notice that this version of the method is potentially much more efficient since images
  142.      * are rotated internally and this might save quite a bit of memory!
  143.      * <p><b>The top and topLeft images must be square!</b> The width and height of these images
  144.      * must be equal otherwise rotation won't work as you expect.
  145.      * 
  146.      * @param top the image of the top line
  147.      * @param topLeft the image of the top left corner
  148.      * @param background the image of the background (optional)
  149.      * @return new border instance
  150.      */
  151.     public static Border createImageBorder(Image top, Image topLeft, Image background) {
  152.         Border b = new Border();
  153.         b.type = TYPE_IMAGE;
  154.         b.images = new Image[] {top, top.rotate(180), top.rotate(270), top.rotate(90), topLeft, topLeft.rotate(90), 
  155.                 topLeft.rotate(270), topLeft.rotate(180), background};
  156.         return b;
  157.     }
  158.     /**
  159.      * Creates a line border that uses the color of the component foreground for drawing
  160.      * 
  161.      * @param thickness thickness of the boder in pixels
  162.      * @return new border instance
  163.      */
  164.     public static Border createLineBorder(int thickness) {
  165.         Border b = new Border();
  166.         b.type = TYPE_LINE;
  167.         b.themeColors = true;
  168.         b.thickness = thickness;
  169.         return b;
  170.     }
  171.     /**
  172.      * Creates a line border that uses the given color for the component
  173.      * 
  174.      * @param thickness thickness of the boder in pixels
  175.      * @param color the color for the border
  176.      * @return new border instance
  177.      */
  178.     public static Border createLineBorder(int thickness, int color) {
  179.         Border b = new Border();
  180.         b.type = TYPE_LINE;
  181.         b.themeColors = false;
  182.         b.thickness = thickness;
  183.         b.colorA = color;
  184.         return b;
  185.     }
  186.     
  187.     /**
  188.      * Creates a rounded corner border that uses the color of the component foreground for drawing.
  189.      * Due to technical issues (lack of shaped clipping) performance and memory overhead of round 
  190.      * borders can be low if used with either a bgImage or translucency! 
  191.      * <p>This border overrides any painter used on the component and would ignor such a painter.
  192.      * 
  193.      * @param arcWidth the horizontal diameter of the arc at the four corners.
  194.      * @param arcHeight the vertical diameter of the arc at the four corners.
  195.      * @return new border instance
  196.      */
  197.     public static Border createRoundBorder(int arcWidth, int arcHeight) {
  198.         Border b = new Border();
  199.         b.type = TYPE_ROUNDED;
  200.         b.themeColors = true;
  201.         b.arcHeight = arcHeight;
  202.         b.arcWidth = arcWidth;
  203.         return b;
  204.     }
  205.     /**
  206.      * Creates a rounded corner border that uses the color of the component foreground for drawing.
  207.      * Due to technical issues (lack of shaped clipping) performance and memory overhead of round
  208.      * borders can be low if used with either a bgImage or translucency!
  209.      * <p>This border overrides any painter used on the component and would ignor such a painter.
  210.      *
  211.      * @param arcWidth the horizontal diameter of the arc at the four corners.
  212.      * @param arcHeight the vertical diameter of the arc at the four corners.
  213.      * @param outline whether the round rect border outline should be drawn
  214.      * @return new border instance
  215.      */
  216.     public static Border createRoundBorder(int arcWidth, int arcHeight, boolean outline) {
  217.         Border b = createRoundBorder(arcWidth, arcHeight);
  218.         b.outline = outline;
  219.         return b;
  220.     }
  221.     /**
  222.      * Creates a rounded border that uses the given color for the component.
  223.      * Due to technical issues (lack of shaped clipping) performance and memory overhead of round 
  224.      * borders can be low if used with either a bgImage or translucency! 
  225.      * <p>This border overrides any painter used on the component and would ignor such a painter.
  226.      * 
  227.      * @param arcWidth the horizontal diameter of the arc at the four corners.
  228.      * @param arcHeight the vertical diameter of the arc at the four corners.
  229.      * @param color the color for the border
  230.      * @return new border instance
  231.      */
  232.     public static Border createRoundBorder(int arcWidth, int arcHeight, int color) {
  233.         Border b = new Border();
  234.         b.type = TYPE_ROUNDED;
  235.         b.themeColors = false;
  236.         b.colorA = color;
  237.         b.arcHeight = arcHeight;
  238.         b.arcWidth = arcWidth;
  239.         return b;
  240.     }
  241.     
  242.     /**
  243.      * Creates a rounded border that uses the given color for the component.
  244.      * Due to technical issues (lack of shaped clipping) performance and memory overhead of round
  245.      * borders can be low if used with either a bgImage or translucency!
  246.      * <p>This border overrides any painter used on the component and would ignor such a painter.
  247.      *
  248.      * @param arcWidth the horizontal diameter of the arc at the four corners.
  249.      * @param arcHeight the vertical diameter of the arc at the four corners.
  250.      * @param color the color for the border
  251.      * @param outline whether the round rect border outline should be drawn
  252.      * @return new border instance
  253.      */
  254.     public static Border createRoundBorder(int arcWidth, int arcHeight, int color, boolean outline) {
  255.         Border b = createRoundBorder(arcWidth, arcHeight, color);
  256.         b.outline = outline;
  257.         return b;
  258.     }
  259.     /**
  260.      * Creates a lowered etched border with default colors, highlight is derived
  261.      * from the component and shadow is a plain dark color
  262.      * 
  263.      * @return new border instance
  264.      */
  265.     public static Border createEtchedLowered() {
  266.         Border b = new Border();
  267.         b.type = TYPE_ETCHED_LOWERED;
  268.         b.themeColors = true;
  269.         return b;
  270.     }
  271.     /**
  272.      * Creates a raised etched border with the given colors
  273.      * 
  274.      * @param highlight color RGB value
  275.      * @param shadow color RGB value
  276.      * @return new border instance
  277.      */
  278.     public static Border createEtchedLowered(int highlight, int shadow) {
  279.         Border b = new Border();
  280.         b.type = TYPE_ETCHED_LOWERED;
  281.         b.themeColors = false;
  282.         b.colorA = shadow;
  283.         b.colorB = highlight;
  284.         return b;
  285.     }
  286.     
  287.     /**
  288.      * Creates a lowered etched border with default colors, highlight is derived
  289.      * from the component and shadow is a plain dark color
  290.      * 
  291.      * @return new border instance
  292.      */
  293.     public static Border createEtchedRaised() {
  294.         Border b = new Border();
  295.         b.type = TYPE_ETCHED_RAISED;
  296.         b.themeColors = true;
  297.         return b;
  298.     }
  299.     /**
  300.      * Creates a raised etched border with the given colors
  301.      * 
  302.      * @param highlight color RGB value
  303.      * @param shadow color RGB value
  304.      * @return new border instance
  305.      */
  306.     public static Border createEtchedRaised(int highlight, int shadow) {
  307.         Border b = new Border();
  308.         b.type = TYPE_ETCHED_RAISED;
  309.         b.themeColors = false;
  310.         b.colorA = highlight;
  311.         b.colorB = shadow;
  312.         return b;
  313.     }
  314.     /**
  315.      * Returns true if installing this border will override the painting of the component background
  316.      * 
  317.      * @return true if this border replaces the painter
  318.      */
  319.     public boolean isBackgroundPainter() {
  320.         return type == TYPE_ROUNDED || type == TYPE_ROUNDED_PRESSED || (type == TYPE_IMAGE);
  321.     }
  322.     /**
  323.      * Creates a lowered bevel border with default colors, highlight is derived
  324.      * from the component and shadow is a plain dark color
  325.      * 
  326.      * @return new border instance
  327.      */
  328.     public static Border createBevelLowered() {
  329.         Border b = new Border();
  330.         b.type = TYPE_BEVEL_LOWERED;
  331.         b.themeColors = true;
  332.         return b;
  333.     }
  334.     /**
  335.      * Creates a raised bevel border with the given colors
  336.      * 
  337.      * @param highlightOuter  RGB of the outer edge of the highlight area
  338.      * @param highlightInner  RGB of the inner edge of the highlight area
  339.      * @param shadowOuter     RGB of the outer edge of the shadow area
  340.      * @param shadowInner     RGB of the inner edge of the shadow area
  341.      * @return new border instance
  342.      */
  343.     public static Border createBevelLowered(int highlightOuter, int highlightInner,
  344.                         int shadowOuter, int shadowInner) {
  345.         Border b = new Border();
  346.         b.type = TYPE_BEVEL_LOWERED;
  347.         b.themeColors = false;
  348.         b.colorA = highlightOuter;
  349.         b.colorB = highlightInner;
  350.         b.colorC = shadowOuter;
  351.         b.colorD = shadowInner;
  352.         return b;
  353.     }
  354.     
  355.     /**
  356.      * Creates a lowered bevel border with default colors, highlight is derived
  357.      * from the component and shadow is a plain dark color
  358.      * 
  359.      * @return new border instance
  360.      */
  361.     public static Border createBevelRaised() {
  362.         Border b = new Border();
  363.         b.type = TYPE_BEVEL_RAISED;
  364.         b.themeColors = true;
  365.         return b;
  366.     }
  367.     /**
  368.      * Creates a raised bevel border with the given colors
  369.      * 
  370.      * @param highlightOuter  RGB of the outer edge of the highlight area
  371.      * @param highlightInner  RGB of the inner edge of the highlight area
  372.      * @param shadowOuter     RGB of the outer edge of the shadow area
  373.      * @param shadowInner     RGB of the inner edge of the shadow area
  374.      * @return new border instance
  375.      */
  376.     public static Border createBevelRaised(int highlightOuter, int highlightInner,
  377.                         int shadowOuter, int shadowInner) {
  378.         Border b = new Border();
  379.         b.type = TYPE_BEVEL_RAISED;
  380.         b.themeColors = false;
  381.         b.colorA = highlightOuter;
  382.         b.colorB = highlightInner;
  383.         b.colorC = shadowOuter;
  384.         b.colorD = shadowInner;
  385.         return b;
  386.     }
  387.         
  388.     /**
  389.      * Allows us to define a border that will act as the pressed version of this border
  390.      * 
  391.      * @param pressed a border that will be returned by the pressed version method
  392.      */
  393.     public void setPressedInstance(Border pressed) {
  394.         pressedBorder = pressed;
  395.     }
  396.     
  397.     /**
  398.      * Allows us to define a border that will act as the focused version of this border
  399.      * 
  400.      * @param focused a border that will be returned by the focused version method
  401.      * @deprecated use the getSelectedStyle() method in the component class
  402.      */
  403.     public void setFocusedInstance(Border focused) {
  404.         focusBorder = focused;
  405.     }
  406.     
  407.     /**
  408.      * Returns the focused version of the border if one is installed
  409.      * 
  410.      * @return a focused version of this border if one exists
  411.      * @deprecated use the getSelectedStyle() method in the component class
  412.      */
  413.     public Border getFocusedInstance() {
  414.         if(focusBorder != null) {
  415.             return focusBorder;
  416.         }
  417.         return this;
  418.     }
  419.     /**
  420.      * Returns the pressed version of the border if one is set by the user
  421.      * 
  422.      * @return the pressed instance of this border
  423.      */
  424.     public Border getPressedInstance() {
  425.         if(pressedBorder != null) {
  426.             return pressedBorder;
  427.         }
  428.         return this;
  429.     }
  430.     
  431.     /**
  432.      * When applied to buttons borders produce a version that reverses the effects 
  433.      * of the border providing a pressed feel
  434.      * 
  435.      * @return a border that will make the button feel pressed
  436.      */
  437.     public Border createPressedVersion() {
  438.         if(pressedBorder != null) {
  439.             return pressedBorder;
  440.         }
  441.         switch(type) {
  442.             case TYPE_LINE:
  443.                 return createLineBorder(thickness + 1, colorA);
  444.             case TYPE_ETCHED_LOWERED: {
  445.                 Border b = createEtchedRaised(colorA, colorB);
  446.                 b.themeColors = themeColors;
  447.                 return b;
  448.             }
  449.             case TYPE_ETCHED_RAISED: {
  450.                 Border b = createEtchedLowered(colorA, colorB);
  451.                 b.themeColors = themeColors;
  452.                 return b;
  453.             }
  454.             case TYPE_BEVEL_RAISED: {
  455.                 Border b = createBevelLowered(colorA, colorB, colorC, colorD);
  456.                 b.themeColors = themeColors;
  457.                 return b;
  458.             }
  459.             case TYPE_BEVEL_LOWERED: {
  460.                 Border b = createBevelRaised(colorA, colorB, colorC, colorD);
  461.                 b.themeColors = themeColors;
  462.                 return b;
  463.             }
  464.             case TYPE_ROUNDED: {
  465.                 Border b = createRoundBorder(arcWidth, arcHeight, colorA);
  466.                 b.themeColors = themeColors;
  467.                 b.type = TYPE_ROUNDED_PRESSED;
  468.                 return b;
  469.             }
  470.             case TYPE_ROUNDED_PRESSED: {
  471.                 Border b = createRoundBorder(arcWidth, arcHeight, colorA);
  472.                 b.themeColors = themeColors;
  473.                 return b;
  474.             }
  475.         }
  476.         return this;
  477.     }
  478.     
  479.     /**
  480.      * Has effect when the border demands responsibility for background painting
  481.      * normally the painter will perform this work but in this case the border might
  482.      * do it instead.
  483.      * 
  484.      * @param g graphics context to draw onto
  485.      * @param c component whose border should be drawn
  486.      */
  487.     public void paintBorderBackground(Graphics g, Component c) {
  488.         int originalColor = g.getColor();
  489.         int x = c.getX();
  490.         int y = c.getY();
  491.         int width = c.getWidth();
  492.         int height = c.getHeight();
  493.         switch(type) {
  494.             case TYPE_ROUNDED_PRESSED:
  495.                 x++;
  496.                 y++;
  497.                 width -= 2;
  498.                 height -= 2;
  499.             case TYPE_ROUNDED:
  500.                 width--;
  501.                 height--;
  502.                 // rounded is also responsible for drawing the background
  503.                 Style s = c.getStyle();
  504.                 if((s.getBgImage() != null && s.getBackgroundType() == Style.BACKGROUND_IMAGE_SCALED) ||
  505.                     s.getBackgroundType() > 1) {
  506.                     WeakReference w = (WeakReference)s.roundRectCache;
  507.                     Image i = null;
  508.                     if(w != null) {
  509.                         i = (Image)w.get();
  510.                     }
  511.                     if(i != null && i.getWidth() == width && i.getHeight() == height) {
  512.                         g.drawImage(i, x, y);
  513.                     } else {
  514.                         // we need to draw a background image!
  515.                         i = Image.createImage(width, height);
  516.                         Graphics imageG = i.getGraphics();
  517.                         imageG.setColor(0);
  518.                         imageG.fillRoundRect(0, 0, width, height, arcWidth, arcHeight);
  519.                         int[] rgb = i.getRGBCached();
  520.                         int transColor = rgb[0];
  521.                         int[] imageRGB;
  522.                         if(s.getBackgroundType() == Style.BACKGROUND_IMAGE_SCALED) {
  523.                             imageRGB = s.getBgImage().scaled(width, height).getRGBCached();
  524.                         } else {
  525.                             Image bgPaint = Image.createImage(width, height);
  526.                             Painter p = s.getBgPainter();
  527.                             // might occur during temporary conditions in the theme switching
  528.                             if(p == null) {
  529.                                 return;
  530.                             }
  531.                             p.paint(bgPaint.getGraphics(), new Rectangle(0, 0, width, height));
  532.                             imageRGB = bgPaint.getRGB();
  533.                         }
  534.                         for(int iter = 0 ; iter < rgb.length ; iter++) {
  535.                             if(rgb[iter] == transColor) {
  536.                                 imageRGB[iter] = 0;
  537.                             }
  538.                         }
  539.                         i = Image.createImage(imageRGB, width, height);
  540.                         s.roundRectCache = new WeakReference(i);
  541.                         g.drawImage(i, x, y);
  542.                     }
  543.                 } else {
  544.                     int foreground = g.getColor();
  545.                     g.setColor(s.getBgColor());
  546.                     // Its opaque much easier job!
  547.                     if(s.getBgTransparency() == ((byte)0xff)) {
  548.                         g.fillRoundRect(x, y , width, height, arcWidth, arcHeight);
  549.                     } else {
  550.                         if(g.isAlphaSupported()) {
  551.                             int alpha = g.getAlpha();
  552.                             g.setAlpha(s.getBgTransparency() & 0xff);
  553.                             g.fillRoundRect(x, y , width, height, arcWidth, arcHeight);
  554.                             g.setAlpha(alpha);
  555.                         } else {
  556.                             // if its transparent we don't need to do anything, if its
  557.                             // translucent... well....
  558.                             if(s.getBgTransparency() != 0) {
  559.                                 Image i = Image.createImage(width, height);
  560.                                 int[] imageRgb;
  561.                                 if(g.getColor() != 0xffffff) {
  562.                                     Graphics imageG = i.getGraphics();
  563.                                     imageG.setColor(g.getColor());
  564.                                     imageG.fillRoundRect(0, 0 , width, height, arcWidth, arcHeight);
  565.                                     imageRgb = i.getRGBCached();
  566.                                 } else {
  567.                                     // background color is white we need to remove a different color
  568.                                     // black is the only other "reliable" color on the device
  569.                                     Graphics imageG = i.getGraphics();
  570.                                     imageG.setColor(0);
  571.                                     imageG.fillRect(0, 0, width, height);
  572.                                     imageG.setColor(g.getColor());
  573.                                     imageG.fillRoundRect(0, 0 , width, height, arcWidth, arcHeight);
  574.                                     imageRgb = i.getRGBCached();
  575.                                 }
  576.                                 int removeColor = imageRgb[0];
  577.                                 int size = width * height;
  578.                                 int alphaInt = ((s.getBgTransparency() & 0xff) << 24) & 0xff000000;
  579.                                 for(int iter = 0 ; iter < size ; iter++) {
  580.                                     if(removeColor == imageRgb[iter]) {
  581.                                             imageRgb[iter] = 0;
  582.                                             continue;
  583.                                     }
  584.                                     if((imageRgb[iter] & 0xff000000) != 0) {
  585.                                         imageRgb[iter] = (imageRgb[iter] & 0xffffff) | alphaInt;
  586.                                     }   
  587.                                 }
  588.                                 g.drawImage(new RGBImage(imageRgb, width, height), x, y);
  589.                             } 
  590.                         }
  591.                     }
  592.                     
  593.                     g.setColor(foreground);
  594.                 }
  595.                 break;
  596.             case TYPE_IMAGE:
  597.                 int clipX = g.getClipX();
  598.                 int clipY = g.getClipY();
  599.                 int clipWidth = g.getClipWidth();
  600.                 int clipHeight = g.getClipHeight();
  601.                 Image topLeft = images[4]; 
  602.                 Image topRight = images[5];
  603.                 Image bottomLeft = images[6];
  604.                 Image center = images[8];
  605.                 x += topLeft.getWidth();
  606.                 y += topLeft.getHeight();
  607.                 height -= (topLeft.getHeight() + bottomLeft.getHeight());
  608.                 width -= (topLeft.getWidth() + topRight.getWidth());
  609.                 g.clipRect(x, y, width, height);
  610.                 if(center != null){
  611.                     int centerWidth = center.getWidth();
  612.                     int centerHeight = center.getHeight();
  613.                     for(int xCount = x ; xCount < x + width ; xCount += centerWidth) {
  614.                         for(int yCount = y ; yCount < y + height ; yCount += centerHeight) {
  615.                             g.drawImage(center, xCount, yCount);
  616.                         }
  617.                     }
  618.                 }
  619.                 Image top = images[0];  Image bottom = images[1];
  620.                 Image left = images[2]; Image right = images[3];
  621.                 Image bottomRight = images[7];
  622.                 
  623.                 g.setClip(clipX, clipY, clipWidth, clipHeight);
  624.                 
  625.                 x = c.getX();
  626.                 y = c.getY();
  627.                 width = c.getWidth();
  628.                 height = c.getHeight();
  629.                 
  630.                 g.drawImage(topLeft, x, y);
  631.                 g.drawImage(bottomLeft, x, y + height - bottomLeft.getHeight());
  632.                 g.drawImage(topRight, x + width - topRight.getWidth(), y);
  633.                 g.drawImage(bottomRight, x + width - bottomRight.getWidth(), y + height - bottomRight.getHeight());
  634.                 
  635.                 g.setClip(clipX, clipY, clipWidth, clipHeight);
  636.                 drawImageBorderLine(g, topLeft, topRight, top, x, y, width);
  637.                 g.setClip(clipX, clipY, clipWidth, clipHeight);
  638.                 drawImageBorderLine(g, bottomLeft, bottomRight, bottom, x, y + height - bottom.getHeight(), width);
  639.                 g.setClip(clipX, clipY, clipWidth, clipHeight);
  640.                 drawImageBorderColumn(g, topLeft, bottomLeft, left, x, y, height);
  641.                 g.setClip(clipX, clipY, clipWidth, clipHeight);
  642.                 drawImageBorderColumn(g, topRight, bottomRight, right, x + width - right.getWidth(), y, height);
  643.                                 
  644.                 g.setClip(clipX, clipY, clipWidth, clipHeight);
  645.                 break;
  646.         }
  647.         g.setColor(originalColor);
  648.     }
  649.     
  650.     /**
  651.      * Draws the border for the given component, this method is called before a call to
  652.      * background painting is made.
  653.      * 
  654.      * @param g graphics context to draw onto
  655.      * @param c component whose border should be drawn
  656.      */
  657.     public void paint(Graphics g, Component c) {
  658.         int originalColor = g.getColor();
  659.         int x = c.getX();
  660.         int y = c.getY();
  661.         int width = c.getWidth();
  662.         int height = c.getHeight();
  663.         if(!themeColors) {
  664.             g.setColor(colorA);
  665.         } 
  666.         switch(type) {
  667.             case TYPE_LINE:
  668.                 width--;
  669.                 height--;
  670.                 for(int iter = 0 ; iter < thickness ; iter++) {
  671.                     g.drawRect(x + iter, y + iter, width, height);
  672.                     width -= 2; height -= 2;
  673.                 }
  674.                 break;
  675.             case TYPE_ROUNDED_PRESSED:
  676.                 x++;
  677.                 y++;
  678.                 width -= 2;
  679.                 height -= 2;
  680.             case TYPE_ROUNDED:
  681.                 width--;
  682.                 height--;
  683.                 if(outline) {
  684.                     g.drawRoundRect(x, y , width, height, arcWidth, arcHeight);
  685.                 }
  686.                 break;
  687.             case TYPE_ETCHED_LOWERED:
  688.             case TYPE_ETCHED_RAISED:
  689.                 g.drawRect(x, y, width - 2, height - 2);
  690.                 if(themeColors) {
  691.                     if(type == TYPE_ETCHED_LOWERED) {
  692.                         g.lighterColor(40);
  693.                     } else {
  694.                         g.darkerColor(40);
  695.                     }
  696.                 } else {
  697.                     g.setColor(colorB);
  698.                 }
  699.                 g.drawLine(x + 1, y + height - 3, x + 1, y +1);
  700.                 g.drawLine(x + 1, y + 1, x + width - 3, y + 1);
  701.                 g.drawLine(x, y + height - 1, x + width - 1, y + height - 1);
  702.                 g.drawLine(x + width - 1, y + height - 1, x + width - 1, y);
  703.                 break;
  704.             case TYPE_BEVEL_RAISED:
  705.                 if(themeColors) {
  706.                     g.setColor(getBackgroundColor(c));
  707.                     g.lighterColor(50);
  708.                 } else {
  709.                     g.setColor(colorA);
  710.                 }
  711.                 g.drawLine(x, y, x, y + height - 2);
  712.                 g.drawLine(x + 1, y, x + width - 2, y);
  713.                 if(themeColors) {
  714.                     g.darkerColor(25);
  715.                 } else {
  716.                     g.setColor(colorB);
  717.                 }
  718.                 g.drawLine(x + 1, y + 1, x + 1, y + height - 3);
  719.                 g.drawLine(x + 2, y + 1, x + width - 3, y + 1);
  720.                 if(themeColors) {
  721.                     g.darkerColor(50);
  722.                 } else {
  723.                     g.setColor(colorC);
  724.                 }
  725.                 g.drawLine(x, y + height - 1, x + width - 1, y + height - 1);
  726.                 g.drawLine(x + width - 1, y, x + width - 1, y + height - 2);
  727.                 if(themeColors) {
  728.                     g.darkerColor(25);
  729.                 } else {
  730.                     g.setColor(colorD);
  731.                 }
  732.                 g.drawLine(x + 1, y + height - 2, x + width - 2, y + height - 2);
  733.                 g.drawLine(x + width - 2, y + 1, x + width - 2, y + height - 3);
  734.                 break;
  735.             case TYPE_BEVEL_LOWERED:
  736.                 if(themeColors) {
  737.                     g.setColor(getBackgroundColor(c));
  738.                     g.darkerColor(50);
  739.                 } else {
  740.                     g.setColor(colorD);
  741.                 }
  742.                 g.drawLine(x, y, x, y + height - 1);
  743.                 g.drawLine(x + 1, y, x + width - 1, y);
  744.                 if(themeColors) {
  745.                     g.lighterColor(25);
  746.                 } else {
  747.                     g.setColor(colorC);
  748.                 }
  749.                 g.drawLine(x + 1, y + 1, x + 1, y + height - 2);
  750.                 g.drawLine(x + 2, y + 1, x + width - 2, y + 1);
  751.                 if(themeColors) {
  752.                     g.lighterColor(50);
  753.                 } else {
  754.                     g.setColor(colorC);
  755.                 }
  756.                 g.drawLine(x + 1, y + height - 1, x + width - 1, y + height - 1);
  757.                 g.drawLine(x + width - 1, y + 1, x + width - 1, y + height - 2);
  758.                 if(themeColors) {
  759.                     g.lighterColor(25);
  760.                 } else {
  761.                     g.setColor(colorA);
  762.                 }
  763.                 g.drawLine(x + 2, y + height - 2, x + width - 2, y + height - 2);
  764.                 g.drawLine(x + width - 2, y + 2, x + width - 2, y + height - 3);
  765.                 break;
  766.             case TYPE_IMAGE:
  767.                 break;
  768.         }
  769.         g.setColor(originalColor);
  770.     }
  771.     private int getBackgroundColor(Component c) {
  772.         return c.getStyle().getBgColor();
  773.     }
  774.     
  775.     private void drawImageBorderLine(Graphics g, Image left, Image right, Image center, int x, int y, int width) {
  776.         int currentWidth = width - right.getWidth();
  777.         if(currentWidth > 0) {
  778.             x += left.getWidth();
  779.             int destX = x + currentWidth;
  780.             g.clipRect(x, y, currentWidth - left.getWidth(), center.getHeight());
  781.             int centerWidth = center.getWidth();
  782.             for(; x < destX ; x += centerWidth) {
  783.                 g.drawImage(center, x, y);
  784.             }
  785.         }
  786.     }
  787.     private void drawImageBorderColumn(Graphics g, Image top, Image bottom, Image center, int x, int y, int height) {
  788.         int currentHeight = height - bottom.getHeight();
  789.         if(currentHeight > 0) {
  790.             y += top.getHeight();
  791.             int destY = y + currentHeight;
  792.             g.clipRect(x, y, center.getWidth(), currentHeight - top.getHeight());
  793.             int centerHeight = center.getHeight();
  794.             for(; y < destY ; y += centerHeight) {
  795.                 g.drawImage(center, x, y);
  796.             }
  797.         }
  798.     }
  799.     
  800.     /**
  801.      * Sets the default border to the given value
  802.      * 
  803.      * @param border new border value
  804.      */
  805.     public static void setDefaultBorder(Border border) {
  806.         defaultBorder = border;
  807.     }
  808.     /**
  809.      * Gets the default border to the given value
  810.      * 
  811.      * @return the default border
  812.      */
  813.     public static Border getDefaultBorder() {
  814.         return defaultBorder;
  815.     }
  816. }