package org.j4me.ui;
import javax.microedition.lcdui.*;
import org.j4me.util.*;
/**
* Derive this class to set the application's theme. A theme controls
* the color scheme and background graphics used to skin the application.
* <p>
* Themes do not alter the shapes or functionality of components. To
* change the behavior of appearance of any component it is up to you to
* derive a new component type and implement the changes.
*/
public class Theme
{
// Colors.
// There are many online lists of colors. One is available at
// http://www.december.com/html/spec/colordec.html
/** Black */ public static final int BLACK = 0x00000000;
/** Brown */ public static final int BROWN = 0x00804000;
/** Blue */ public static final int BLUE = 0x000000FF;
/** Navy blue */ public static final int NAVY = 0x00000080;
/** Neon blue */ public static final int NEON_BLUE = 0x004DFFFF;
/** Light blue */ public static final int LIGHT_BLUE = 0x000080FF;
/** Red */ public static final int RED = 0x00FF0000;
/** Maroon */ public static final int MAROON = 0x00802020;
/** Light red */ public static final int LIGHT_RED = 0x00FF5050;
/** Magenta */ public static final int MAGENTA = 0x00FF28FF;
/** Orange */ public static final int ORANGE = 0x00FF8000;
/** Burnt orange */ public static final int BURNT_ORANGE = 0x00D07000;
/** Yellow */ public static final int YELLOW = 0x00FFFF00;
/** Green */ public static final int GREEN = 0x0066FF33;
/** Medium green */ public static final int MEDIUM_GREEN = 0x0000A700;
/** Light green */ public static final int LIGHT_GREEN = 0x0030C020;
/** Dark green */ public static final int DARK_GREEN = 0x001F432D;
/** Forest green*/ public static final int FOREST_GREEN = 0x0033773A;
/** Blue-green */ public static final int BLUE_GREEN = 0x00008080;
/** Cyan */ public static final int CYAN = 0x0033FFFF;
/** Silver */ public static final int SILVER = 0x00C0C0C0;
/** Gray */ public static final int GRAY = 0x00808080;
/** Light gray */ public static final int LIGHT_GRAY = 0x00C0C0C0;
/** Lavendar */ public static final int LAVENDAR = 0x00E6E6FA;
/** White */ public static final int WHITE = 0x00FFFFFF;
/**
* The percentage of the way down the title bar that the secondary color
* used in the gradient fill is at its max.
*/
private static final double TITLE_BAR_SECONDARY_COLOR_MAX = 0.60; // 60%
/**
* The percentage of the way down the menu bar that the secondary color
* used in the gradient fill is at its max.
*/
private static final double MENU_BAR_SECONDARY_COLOR_MAX = 0.10; // 10%
/**
* The percentage of the way across the scrollbar that the secondary color
* used in the gradient fill is at its max.
*/
private static final double SCROLLBAR_SECONDARY_COLOR_MAX = 0.80; // 80%
/**
* The width of the scrollbar in pixels.
*/
private static final int SCROLLBAR_WIDTH = 6;
/**
* The font used for writing text in the normal canvas area. It
* is the default font used by components.
*/
private final Font defaultFont;
/**
* The font used to write menu bar options.
*/
private final Font menuFont;
/**
* The font used in the title area.
*/
private final Font titleFont;
/**
* Creates a <code>Theme</code> object. After creating the theme it must
* be attached to the UI manager to use it through the <code>setTheme</code>
* method.
*/
public Theme ()
{
// Get the application's fonts.
Font base = Font.getDefaultFont();
int face = base.getFace();
int size = base.getSize();
defaultFont = Font.getFont( face, Font.STYLE_PLAIN, size );
menuFont = Font.getFont( face, Font.STYLE_PLAIN, size );
titleFont = Font.getFont( face, Font.STYLE_BOLD, size );
}
/**
* Gets the basic default font. This font is used for writing menu
* options, labels, and regular text throughout the UI.
*
* @return The font used for normal text within the UI.
* @see #getFontColor()
*/
public Font getFont ()
{
return defaultFont;
}
/**
* Returns the font used in the menu bar at the bottom of the canvas.
* <p>
* By default this font is the system font.
* Override this font to change the style of the title text.
*
* @return The font used for writing menu text.
*
* @see #getMenuFontColor()
* @see #paintMenuBar(Graphics, String, boolean, String, boolean, int, int)
*/
public Font getMenuFont ()
{
return menuFont;
}
/**
* Returns the font used for writing the title in the screen's title
* area.
* <p>
* By default this font is the system font in bold.
* Override this font to change the style of the title text.
*
* @return The font used for writing the title in the title area at
* the top of the screen.
* @see #getTitleFontColor()
* @see #paintTrackbar(Graphics, int, int, int, int)
*/
public Font getTitleFont ()
{
return titleFont;
}
/**
* The color of the text written with the font returned by <code>getFont</code>.
* Colors are defined as 0xAARRGGBB; the first-byte alpha-channel is ignored.
* <p>
* Override this method to change the text color.
*
* @return The color of text written with the font from <code>getFont</code>.
* @see #getFontColor()
*/
public int getFontColor ()
{
return NAVY;
}
/**
* The color of the text written with the font returned by <code>getMenuFont</code>.
* Colors are defined as 0xAARRGGBB; the first-byte alpha-channel is ignored.
* <p>
* Override this method to change the text color.
*
* @return The color of text written with the font from <code>getMenuFont</code>.
* @see #getMenuFont()
* @see #paintMenuBar(Graphics, String, boolean, String, boolean, int, int)
*/
public int getMenuFontColor ()
{
return WHITE;
}
/**
* The color of the menu text when the menu button is pressed. Normally it
* will be the color returned by <code>getMenuFontColor</code>.
* Colors are defined as 0xAARRGGBB; the first-byte alpha-channel is ignored.
* <p>
* Override this method to change the text color.
*
* @return The color of the menu text when its menu button is pressed.
* @see #getMenuFont()
* @see #getMenuFontColor()
* @see #paintMenuBar(Graphics, String, boolean, String, boolean, int, int)
*/
public int getMenuFontHighlightColor ()
{
return SILVER;
}
/**
* The color of the text written with the font returned by <code>getTitleFont</code>.
* Colors are defined as 0xAARRGGBB; the first-byte alpha-channel is ignored.
* <p>
* Override this method to change the text color.
*
* @return The color of text written with the font from <code>getTitleFont</code>.
* @see #getTitleFont()
* @see #paintTrackbar(Graphics, int, int, int, int)
*/
public int getTitleFontColor ()
{
return getMenuFontColor();
}
/**
* Returns the color used for borders in the canvas section of the
* UI. An example of a border is the outline around a text box.
* Colors are defined as 0xAARRGGBB; the first-byte alpha-channel
* is ignored.
* <p>
* Override this method to change it.
*
* @return The color of the borders in the UI.
*/
public int getBorderColor ()
{
return NAVY;
}
/**
* Returns the color used as the background for the canvas section
* of the screen. This is the area that is not the title bar
* at the top or menu bar at the bottom. Colors are defined as
* 0xAARRGGBB; the first-byte alpha-channel is ignored.
* <p>
* Override this method to change it.
*
* @return The color of the title border.
*/
public int getBackgroundColor ()
{
return WHITE;
}
/**
* Returns the main color used in painting components. For example
* a progress bar will use this color to show the completed progress.
* Colors are defined as 0xAARRGGBB; the first-byte alpha-channel
* is ignored.
* <p>
* Override this method to change it.
*
* @return The primary color used to paint components.
*/
public int getHighlightColor ()
{
return LIGHT_BLUE;
}
/**
* Returns the color of the border around the title bar.
* Colors are defined as 0xAARRGGBB; the first-byte alpha-channel is ignored.
* <p>
* By default this is the same color as the menu border. Override
* this method to change it.
*
* @return The color of the title border.
* @see #paintTrackbar(Graphics, int, int, int, int)
*/
public int getTitleBarBorderColor ()
{
return getMenuBarBorderColor();
}
/**
* Returns the primary color of the background of the title bar. A second
* color defined by <code>getTitleBarHighlightColor</code> is overlaid with
* a vertical gradient.
* <p>
* Colors are defined as 0xAARRGGBB; the first-byte alpha-channel is ignored.
* <p>
* By default this is the same color as the menu bar background. Override
* this method to change it.
*
* @return The primary color of the title bar background.
*
* @see #getTitleBarHighlightColor()
*/
public int getTitleBarBackgroundColor ()
{
return getMenuBarBackgroundColor();
}
/**
* Returns the highlight color applied as a vertical gradient to the title
* bar.
* <p>
* Colors are defined as 0xAARRGGBB; the first-byte alpha-channel is ignored.
* <p>
* By default this is the same color as the menu bar highlight. Override
* this method to change it.
*
* @return The highlight color of the title bar background.
*
* @see #getTitleBarBackgroundColor()
*/
public int getTitleBarHighlightColor ()
{
return getMenuBarHighlightColor();
}
/**
* Returns the color of the border around the menu bar.
* Colors are defined as 0xAARRGGBB; the first-byte alpha-channel is ignored.
* <p>
* Override this method to change it.
*
* @return The color of the border around the menu bar.
* @see #paintMenuBar(Graphics, String, boolean, String, boolean, int, int)
*/
public int getMenuBarBorderColor ()
{
return getFontColor();
}
/**
* Returns the primary color of the background of the menu bar. A second
* color defined by <code>getMenuBarHighlightColor</code> is overlaid with
* a vertical gradient.
* <p>
* Colors are defined as 0xAARRGGBB; the first-byte alpha-channel is ignored.
* <p>
* Override this method to change it.
*
* @return The color of the border around the menu bar.
*
* @see #getMenuBarHighlightColor()
*/
public int getMenuBarBackgroundColor ()
{
return NAVY;
}
/**
* Returns the highlight color applied as a vertical gradient to the menu
* bar.
* <p>
* Colors are defined as 0xAARRGGBB; the first-byte alpha-channel is ignored.
* <p>
* Override this method to change it.
*
* @return The highlight color of the menu bar background.
*
* @see #getMenuBarBackgroundColor()
*/
public int getMenuBarHighlightColor ()
{
return LIGHT_BLUE;
}
/**
* Gets the height of the title bar in pixels. This method is called
* whenever the title is set and the title bar is going to be painted.
*
* @return The height of the title bar in pixels.
* @see #paintTrackbar(Graphics, int, int, int, int)
*/
public int getTitleHeight ()
{
return getTitleFont().getHeight() + 2;
}
/**
* Paints the title bar of the canvas. This method is called only
* when the title has been set through <code>setTitle</code> and the canvas
* is not in full screen mode.
* <p>
* The supplied <code>Graphics</code> will be set with an appropriate clip
* and translated such that (0,0) is the top-left corner of the title
* bar.
* <p>
* Override this method to change the appearance of the title bar.
* For example background or logo images can be placed throughout the
* application by painting them here.
*
* @param g is the <code>Graphics</code> object to paint with.
* @param title is the text for the title bar as defined by the
* canvas class.
* @param width is the width of the title bar in pixels.
* @param height is the height of the title bar in pixels.
*/
public void paintTitleBar (Graphics g, String title, int width, int height)
{
// Fill the background of the title bar.
paintTitleBarBackground( g, 0, 0, width, height );
// Draw a line below the title bar to separate it from the canvas.
g.setColor( getTitleBarBorderColor() );
g.drawLine( 0, height - 1, width, height - 1 );
// Write the title text.
g.setFont( getTitleFont() );
g.setColor( getTitleFontColor() );
g.drawString( title, width / 2, 1, Graphics.HCENTER | Graphics.TOP );
}
/**
* Paints the background area of the title bar. The text will be
* added later by the calling <code>paintTitleBar</code> method.
*
* @param g is the <code>Graphics</code> object to paint with.
* @param x is the top-left X-coordinate pixel of the title bar.
* @param y is the top-left Y-coordinate pixel of the title bar.
* @param width is the width of the title bar in pixels.
* @param height is the height of the title bar in pixels.
*
* @see #paintTrackbar(Graphics, int, int, int, int)
*/
protected void paintTitleBarBackground (Graphics g, int x, int y, int width, int height)
{
// This code would paint the title bar a solid background.
// int background = getTitleBackgroundColor();
// g.setColor( background );
// g.fillRect( x, y, width, height );
// Paint a gradient background.
int primary = getTitleBarBackgroundColor();
int secondary = getTitleBarHighlightColor();
gradientFill( g, 0, 0, width, height, true, primary, secondary, TITLE_BAR_SECONDARY_COLOR_MAX );
}
/**
* Gets the height of the menu bar in pixels. This method is called
* whenever the menu is going to be painted.
*
* @return The height of the menu bar in pixels.
*
* @see #paintMenuBar(Graphics, String, boolean, String, boolean, int, int)
*/
public int getMenuHeight ()
{
return getMenuFont().getHeight() + 2;
}
/**
* Paints the menu bar at the bottom of the canvas. This method is
* not called if the canvas is in full screen mode.
* <p>
* The supplied <code>Graphics</code> will be set with an appropriate clip
* and translated such that (0,0) is the top-left corner of the title
* bar.
* <p>
* Override this method to change the appearance or functionality of
* the menu. Be careful not to write strings that are too long and
* will not fit on the menu bar.
*
* @param g is the <code>Graphics</code> object to paint with.
* @param left is the text to write on the left side of the menu bar.
* The left side is associated with dimissing input such as a
* "Cancel" button.
* @param highlightLeft is <code>true</code> if the menu text <code>left</code>
* should be highlighted to indicate the left menu button is currently
* pressed.
* @param right is the text to write on the right side of the menu bar.
* The right side is associated with accepting input such as an
* "OK" button.
* @param highlightRight is <code>true</code> if the menu text <code>right</code>
* should be highlighted to indicate the right menu button is currently
* pressed.
* @param width is the width of the menu bar in pixels.
* @param height is the height of the menu bar in pixels.
*/
public void paintMenuBar (Graphics g,
String left, boolean highlightLeft,
String right, boolean highlightRight,
int width, int height)
{
// Fill the menu bar background.
paintMenuBarBackground( g, 0, 0, width, height );
// Draw a line above the menu bar to separate it from the canvas.
g.setColor( getMenuBarBorderColor() );
g.drawLine( 0, 0, width, 0 );
// Write the menu items.
int normal = getMenuFontColor();
int highlighted = getMenuFontHighlightColor();
Font font = getMenuFont();
g.setFont( font );
int offset = font.charWidth( ' ' ) / 2;
g.setColor( highlightLeft ? highlighted : normal );
g.drawString( left, offset, height, Graphics.BOTTOM | Graphics.LEFT );
g.setColor( highlightRight ? highlighted : normal );
g.drawString( right, width - offset, height, Graphics.BOTTOM | Graphics.RIGHT );
}
/**
* Paints the background area of the menu bar. The text will be
* added later by the calling <code>paintMenuBar</code> method.
*
* @param g is the <code>Graphics</code> object to paint with.
* @param x is the top-left X-coordinate pixel of the menu bar.
* @param y is the top-left Y-coordinate pixel of the menu bar.
* @param width is the width of the menu bar in pixels.
* @param height is the height of the menu bar in pixels.
*
* @see #paintMenuBar(Graphics, String, boolean, String, boolean, int, int)
*/
protected void paintMenuBarBackground (Graphics g, int x, int y, int width, int height)
{
// This code would paint the menu bar a solid background.
// int background = getMenuBackgroundColor();
// g.setColor( background );
// g.fillRect( x, y, width, height );
// Paint a gradient background.
int primary = getMenuBarBackgroundColor();
int secondary = getMenuBarHighlightColor();
gradientFill( g, x, y, width, height, true, primary, secondary, MENU_BAR_SECONDARY_COLOR_MAX );
}
/**
* Gets the localized menu text for OK buttons that appear on
* forms. By default this is "OK".
*
* @return The text used for the OK button on forms.
*/
public String getMenuTextForOK ()
{
return "OK";
}
/**
* Gets the localized menu text for Cancel buttons that appear on
* forms. By default this is "Cancel".
*
* @return The text used for the Cancel button on forms.
*/
public String getMenuTextForCancel ()
{
return "Cancel";
}
/**
* Paints the background of the main section of the screen. This includes
* everything except for the title bar at the top and menu bar at the bottom.
* However, if this canvas is in full screen mode, then this method paints the entire
* screen.
* <p>
* After this method is called, the screen's <code>paintCanvas</code> method will be.
* <p>
* By default this method paints the entire background the color specified
* by <code>getBackgroundColor</code>. Override this implementation to provide
* a different background for the entire application, such as an image.
*
* @param g is the <code>Graphics</code> object to paint with.
*/
public void paintBackground (Graphics g)
{
int color = getBackgroundColor();
int x = g.getClipX();
int y = g.getClipY();
int w = g.getClipWidth();
int h = g.getClipHeight();
// Clear the canvas.
g.setColor( color );
g.fillRect( x, y, w, h );
}
/**
* Paints the vertical scrollbar. The scrollbar must go on the right
* side of the form and span from the top to the bottom. Its width
* is returned from this method and used to calculate the width of
* the remaining form area to draw components in.
*
* @param g is the <code>Graphics</code> object to paint with.
* @param x is the top-left X-coordinate pixel of the form area.
* @param y is the top-left Y-coordinate pixel of the form area.
* @param width is the width of the form area in pixels.
* @param height is the height of the form area in pixels.
* @param offset is the vertical scrolling position of the top pixel
* to show on the form area.
* @param formHeight is the total height of all the components on the
* form. This is bigger than <code>height</code>.
*/
public void paintVerticalScrollbar (Graphics g, int x, int y, int width, int height, int offset, int formHeight)
{
// Make the scrollbar as wide as the rounding diameter.
int scrollbarWidth = getVerticalScrollbarWidth();
int left = x + width - scrollbarWidth;
// Draw the scrollbar background.
paintScrollbarBackground( g, left, y, scrollbarWidth, height );
// Draw an edge to the scrollbar.
int border = getBorderColor();
g.setColor( border );
g.drawLine( left, y, left, y + height );
// Calculate the height of the trackbar.
int scrollableHeight = formHeight - height;
double trackbarPercentage = (double)height / (double)formHeight;
int trackbarHeight = (int)MathFunc.round( height * trackbarPercentage );
trackbarHeight = Math.max( trackbarHeight, 2 * scrollbarWidth );
// Calculate the range and location of the trackbar.
// The scrollbar doesn't actually go from 0% to 100%. The top
// is actually 1/2 the height of the trackbar from the top of
// the screen. The bottom is 1/2 the height from the bottom.
int rangeStart = trackbarHeight / 2;
int range = height - 2 * rangeStart;
double offsetPercentage = (double)offset / (double)scrollableHeight;
int center = y + rangeStart + (int)MathFunc.round( offsetPercentage * range );
// Draw the trackbar.
paintTrackbar( g, left, center - rangeStart, scrollbarWidth, trackbarHeight );
}
/**
* Paints the background area of the scrollbar. This does not include
* the trackbar (which will be painted later by <code>paintScrollbarTrackbar</code>).
*
* @param g is the <code>Graphics</code> object to paint with.
* @param x is the top-left X-coordinate pixel of the scrollbar.
* @param y is the top-left Y-coordinate pixel of the scrollbar.
* @param width is the width of the scrollbar in pixels.
* @param height is the height of the scrollbar in pixels.
*
* @see #paintVerticalScrollbar(Graphics, int, int, int, int, int, int)
* @see #paintTrackbar(Graphics, int, int, int, int)
*/
protected void paintScrollbarBackground (Graphics g, int x, int y, int width, int height)
{
// This code would paint the scrollbar a solid background.
// int background = getScrollbarBackgroundColor();
// g.setColor( background );
// g.fillRect( x, y, width, height );
// Paint a gradient background.
int primary = getScrollbarBackgroundColor();
int secondary = getScrollbarHighlightColor();
gradientFill( g, x, y, width, height, false, primary, secondary, SCROLLBAR_SECONDARY_COLOR_MAX );
}
/**
* Paints the trackbar on the scrollbar. The trackbar is the sliding bit
* found on the scrollbar that shows the user where the current screen
* is relative to the scrolling.
*
* @param g is the <code>Graphics</code> object to paint with.
* @param x is the top-left X-coordinate pixel of the trackbar.
* @param y is the top-left Y-coordinate pixel of the trackbar.
* @param width is the width of the trackbar in pixels.
* @param height is the height of the trackbar in pixels.
*
* @see #paintVerticalScrollbar(Graphics, int, int, int, int, int, int)
* @see #paintScrollbarBackground(Graphics, int, int, int, int)
*/
protected void paintTrackbar (Graphics g, int x, int y, int width, int height)
{
// This code would paint the scrollbar a solid background.
// int trackbar = getScrollbarTrackbarColor();
// g.setColor( trackbar );
// g.fillRect( x, y, width, height );
// Paint a gradient background.
int primary = getScrollbarTrackbarColor();
int secondary = getScrollbarBorderColor();
gradientFill( g, x, y, width, height, false, primary, secondary, 0.80 );
}
/**
* Returns the width of the vertical scrollbar.
*
* @return The number of pixels wide the scrollbar is.
*/
public int getVerticalScrollbarWidth ()
{
return SCROLLBAR_WIDTH;
}
/**
* Returns the color of the border around the scrollbar.
* Colors are defined as 0xAARRGGBB; the first-byte alpha-channel is ignored.
* <p>
* By default this is the same as the border color.
* Override this method to change it.
*
* @return The color of the border around the scrollbar.
* @see #paintVerticalScrollbar(Graphics, int, int, int, int, int, int)
*/
public int getScrollbarBorderColor ()
{
return getBorderColor();
}
/**
* Returns the color of the background of the scrollbar. This
* is the area without the trackbar on it.
* <p>
* By default this is the same as the scrollbar's border color.
* Override this method to change it.
*
* @return The color of the scrollbar background.
* @see #paintVerticalScrollbar(Graphics, int, int, int, int, int, int)
*/
public int getScrollbarBackgroundColor ()
{
return getMenuBarBackgroundColor();
}
/**
* Returns the highlight color applied as a horizontal gradient to the
* scrollbar.
* <p>
* Colors are defined as 0xAARRGGBB; the first-byte alpha-channel is ignored.
* <p>
* Override this method to change it.
*
* @return The highlight color of the scrollbar background.
*
* @see #getScrollbarBackgroundColor()
*/
public int getScrollbarHighlightColor ()
{
return getMenuFontHighlightColor();
}
/**
* Returns the color of the trackbar within the scrollbar. The
* trackbar is the block that moves up and down the scrollbar
* to visually inform the user of where in the scrolling they are.
* <p>
* By default this is the same as the menu bar's background color.
* Override this method to change it.
*
* @return The color of the scrollbar's trackbar.
* @see #paintVerticalScrollbar(Graphics, int, int, int, int, int, int)
*/
public int getScrollbarTrackbarColor ()
{
return getMenuBarHighlightColor();
}
/**
* Fills a rectangle with linear gradient. The gradient colors go
* from <code>primaryColor</code> to <code>secondaryColor</code> at
* <code>maxSecondary</code>. So if <code>maxSecondary == 0.70</code> then a line
* across the fill rectangle 70% of the way would be
* <code>secondaryColor</code>.
*
* @param g is the <code>Graphics</code> object for painting.
* @param x is the left edge of the rectangle.
* @param y is the top edge of the rectangle.
* @param width is the width of the rectangle.
* @param height is the height of the rectangle.
* @param fillVertically is <code>true</code> if the gradient goes from
* top-to-bottom or <code>false</code> for left-to-right.
* @param primaryColor is the main color.
* @param secondaryColor is the highlight color.
* @param maxSecondary is between 0.00 and 1.00 and says how far down
* the fill will <code>secondaryColor</code> peak.
*/
public static void gradientFill (
Graphics g,
int x, int y, int width, int height,
boolean fillVertically,
int primaryColor, int secondaryColor, double maxSecondary)
{
// Break the primary color into red, green, and blue.
int pr = (primaryColor & 0x00FF0000) >> 16;
int pg = (primaryColor & 0x0000FF00) >> 8;
int pb = (primaryColor & 0x000000FF);
// Break the secondary color into red, green, and blue.
int sr = (secondaryColor & 0x00FF0000) >> 16;
int sg = (secondaryColor & 0x0000FF00) >> 8;
int sb = (secondaryColor & 0x000000FF);
// Draw a horizonal line for each pixel from the top to the bottom.
int end = (fillVertically ? height : width);
for ( int i = 0; i < end; i++ )
{
// Calculate the color for this line.
double p = (double)i / (double)end;
double v = Math.abs( maxSecondary - p );
double v2 = 1.0 - v;
int red = (int)( pr * v + sr * v2 );
int green = (int)( pg * v + sg * v2 );
int blue = (int)( pb * v + sb * v2 );
g.setColor( red, green, blue );
// Draw the line.
if ( fillVertically )
{
g.drawLine( x, y + i, x + width, y + i );
}
else // horizontal
{
g.drawLine( x + i, y, x + i, y + height );
}
}
}
}