/* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores * CA 94065 USA or visit www.oracle.com if you need additional information or * have any questions. */ package com.codename1.ui.plaf; import com.codename1.io.Log; import com.codename1.ui.geom.Dimension; import com.codename1.ui.*; import com.codename1.ui.animations.BubbleTransition; import com.codename1.ui.animations.CommonTransitions; import com.codename1.ui.animations.Transition; import com.codename1.ui.list.*; /** * Allows a UI developer to completely customize the look of the application by * overriding drawing/sizing methods appropriately. * * @author Chen Fishbein * @deprecated this class is still crucial for some features in Codename One. The deprecation is here to indicate * our desire to reduce usage/reliance on this class. */ public abstract class LookAndFeel { private Component verticalScroll; private Component horizontalScroll; private Component verticalScrollThumb; private Component horizontalScrollThumb; /** * Right-To-Left. Default false. */ private boolean rtl; private long tickerSpeed = 50; /** * Tint color is set when a form is partially covered be it by a menu or by a * dialog. A look and feel can override this default value. */ private int defaultFormTintColor = 0x77000000; /** * This color is used to paint disable mode. */ private int disableColor = 0xcccccc; /** * This member allows us to define a default animation that will draw the transition for * entering a form */ private Transition defaultFormTransitionIn; /** * This member allows us to define a default animation that will draw the transition for * exiting a form */ private Transition defaultFormTransitionOut; /** * This member allows us to define a default animation that will draw the transition for * entering a menu */ private Transition defaultMenuTransitionIn; /** * This member allows us to define a default animation that will draw the transition for * exiting a menu */ private Transition defaultMenuTransitionOut; /** * This member allows us to define a default animation that will draw the transition for * entering a dialog */ private Transition defaultDialogTransitionIn; /** * This member allows us to define a default animation that will draw the transition for * exiting a form */ private Transition defaultDialogTransitionOut; /** * Indicates whether lists and containers should have smooth scrolling by default */ private boolean defaultSmoothScrolling = true; /** * Indicates whether lists and containers should scroll only via focus and thus "jump" when * moving to a larger component as was the case in older versions of Codename One. */ private boolean focusScrolling; /** * Indicates the default speed for smooth scrolling */ private int defaultSmoothScrollingSpeed = 150; private boolean scrollVisible; private boolean fadeScrollEdge; private boolean fadeScrollBar; private int fadeScrollBarSpeed = 5; private int fadeScrollEdgeLength = 15; private Image fadeScrollTop; private Image fadeScrollBottom; private Image fadeScrollRight; private Image fadeScrollLeft; private int fadeScrollEdgeStartAlpha = 0x999999; private int fadeScrollEdgeEndAlpha = 0; private int textFieldCursorColor; private boolean backgroundImageDetermineSize; /** * Indicates whether softbuttons should be reversed from their default orientation */ private boolean reverseSoftButtons; /** * This renderer is assigned to all Forms Menu's by default. */ private ListCellRenderer menuRenderer; private Image[] menuIcons = new Image[3]; /** * Allows defining a tactile touch device that vibrates when the user presses a component * that should respond with tactile feedback on a touch device (e.g. vibrate). * Setting this to 0 disables tactile feedback completely */ private int tactileTouchDuration = 0; /** * Indicates whether labels should end with 3 points by default */ private boolean defaultEndsWith3Points = true; /** * Indicates whether tensile drag should be active by default */ private boolean defaultTensileDrag = true; /** * Indicates whether tensile highlight should be active by default */ private boolean defaultTensileHighlight = false; /** * The MenuBar class */ private Class menuBar = MenuBar.class;; private boolean defaultSnapToGrid; private boolean defaultAlwaysTensile; private Image tensileHighlightTopImage; private Image tensileHighlightBottomImage; private Image tensileGlowTopImage; private Image tensileGlowBottomImage; private UIManager manager; public LookAndFeel(UIManager manager){ this.manager = manager; } /** * Every component binds itself to the look and feel thus allowing the look * and feel to customize the component. Binding occurs at the end of the * constructor when the component is in a valid state and ready to be used. * Notice that a component might be bound twice or more and it is the * responsibility of the LookAndFeel to protect against that. * * @param cmp component instance that may be customized by the look and feel */ public void bind(Component cmp) { } /** * Invoked when a look and feel is removed, allows a look and feel to release * resources related to binding components. * * @see #bind(Component) */ public void uninstall() { } /** * Invoked for drawing a button widget * * @param g graphics context * @param b component to draw * @deprecated this method is no longer used by the implementation, we shifted code away to improve performance */ public abstract void drawButton(Graphics g, Button b); /** * Invoked for drawing a checkbox widget * * @param g graphics context * @param cb component to draw */ public abstract void drawCheckBox(Graphics g, Button cb); /** * Invoked for drawing a combo box widget * * @param g graphics context * @param cb component to draw */ public abstract void drawComboBox(Graphics g, List cb); /** * Invoked for drawing a label widget * * @param g graphics context * @param l component to draw * @deprecated this method is no longer used by the implementation, we shifted code away to improve performance */ public abstract void drawLabel(Graphics g, Label l); /** * Invoked for drawing a list widget * * @param g graphics context * @param l component to draw */ public abstract void drawList(Graphics g, List l); /** * Invoked for drawing the radio button widget * * @param g graphics context * @param rb component to draw */ public abstract void drawRadioButton(Graphics g, Button rb); /** * Draw the given text area * * @param g graphics context * @param ta component to draw */ public abstract void drawTextArea(Graphics g, TextArea ta); /** * Draws the text field without its cursor which is drawn in a separate method * input mode indication can also be drawn using this method. * * @param g graphics context * @param ta component to draw */ public abstract void drawTextField(Graphics g, TextArea ta); /** * Draws the cursor of the text field, blinking is handled simply by avoiding * a call to this method. * * @param g graphics context * @param ta component to draw */ public abstract void drawTextFieldCursor(Graphics g, TextArea ta); /** * Calculate the preferred size of the component * * @param b component whose size should be calculated * @return the preferred size for the button */ public abstract Dimension getButtonPreferredSize(Button b); /** * Calculate the preferred size of the component * * @param cb component whose size should be calculated * @return the preferred size for the component */ public abstract Dimension getCheckBoxPreferredSize(Button cb); /** * Calculate the preferred size of the component * * @param l component whose size should be calculated * @return the preferred size for the component */ public abstract Dimension getLabelPreferredSize(Label l); /** * Calculate the preferred size of the component * * @param l component whose size should be calculated * @return the preferred size for the component */ public abstract Dimension getListPreferredSize(List l); /** * Calculate the preferred size of the component * * @param rb component whose size should be calculated * @return the preferred size for the component */ public abstract Dimension getRadioButtonPreferredSize(Button rb); //public abstract Dimension getSpinnerPreferredSize(Spinner sp); /** * Calculate the preferred size of the component * * @param ta component whose size should be calculated * @param pref indicates whether preferred or scroll size should be returned * @return the preferred size for the component */ public abstract Dimension getTextAreaSize(TextArea ta, boolean pref); /** * Calculate the preferred size of the component * * @param ta component whose size should be calculated * @return the preferred size for the component */ public abstract Dimension getTextFieldPreferredSize(TextArea ta); /** * Calculate the preferred size of the component * * @param box component whose size should be calculated * @return the preferred size for the component */ public abstract Dimension getComboBoxPreferredSize(List box); /** * Draws a vertical scroll bar in the given component * * @param g graphics context * @param c component to draw on * @param offsetRatio ratio of the scroll bar from 0 to 1 * @param blockSizeRatio block size for the scroll from 0 to 1 */ public void drawVerticalScroll(Graphics g, Component c, float offsetRatio, float blockSizeRatio) { if(verticalScroll == null) { initScroll(); } int borderW = 0; if(c.getStyle().getBorder() != null){ borderW = c.getStyle().getBorder().getThickness(); } int x = c.getX(); if(!c.isRTL()) { x += c.getWidth() - getVerticalScrollWidth() - borderW; }else{ x += borderW; } int y = c.getY(); int height = c.getHeight(); int width = getVerticalScrollWidth(); drawScroll(g, c, offsetRatio, blockSizeRatio, true, x, y, width, height, verticalScroll, verticalScrollThumb); if(fadeScrollEdge) { if(offsetRatio > 0) { if(fadeScrollTop == null || Display.getInstance().getDisplayWidth() != fadeScrollTop.getWidth()) { fadeScrollTop = generateFadeImage(fadeScrollEdgeStartAlpha, fadeScrollEdgeEndAlpha, c.getStyle().getBgColor(), false, Display.getInstance().getDisplayWidth(),fadeScrollEdgeLength); } g.drawImage(fadeScrollTop, c.getX(), c.getY()); } if(offsetRatio < 1 - blockSizeRatio) { // special case since when scrolling with the physical keys we leave // the margin out of the equasion int l = c.getScrollY() + c.getHeight() + c.getStyle().getVerticalMargins() + c.getStyle().getVerticalPadding(); int totalScroll = c.getScrollDimension().getHeight(); if(l >= totalScroll) { return; } if(fadeScrollBottom == null || Display.getInstance().getDisplayWidth() != fadeScrollBottom.getWidth()) { fadeScrollBottom = generateFadeImage(fadeScrollEdgeEndAlpha, fadeScrollEdgeStartAlpha, c.getStyle().getBgColor(), false, Display.getInstance().getDisplayWidth(), fadeScrollEdgeLength); } g.drawImage(fadeScrollBottom, c.getX(), c.getY() + c.getHeight() - fadeScrollBottom.getHeight()); } } } private Image generateFadeImage(int startColor, int endColor, int bgColor, boolean horizontal, int width, int height) { Image mute = Image.createImage(width, height); mute.getGraphics().fillLinearGradient(startColor, endColor, 0, 0, width, height, horizontal); Object mask = mute.createMask(); mute = Image.createImage(width, height); Graphics gr = mute.getGraphics(); gr.setColor(bgColor); gr.fillRect(0, 0, width, height); return mute.applyMask(mask); } /** * Draws a horizontal scroll bar in the given component * * @param g graphics context * @param c component to draw on * @param offsetRatio ratio of the scroll bar from 0 to 1 * @param blockSizeRatio block size for the scroll from 0 to 1 */ public void drawHorizontalScroll(Graphics g, Component c, float offsetRatio, float blockSizeRatio) { if(horizontalScroll == null) { initScroll(); } int borderH = 0; if(c.getStyle().getBorder() != null){ borderH = c.getStyle().getBorder().getThickness(); } int x = c.getX(); int y = c.getY() + c.getHeight() - getHorizontalScrollHeight() - borderH; int width = c.getWidth(); int height = getHorizontalScrollHeight(); drawScroll(g, c, offsetRatio, blockSizeRatio, false, x, y, width, height, horizontalScroll, horizontalScrollThumb); if(fadeScrollEdge) { if(offsetRatio > 0) { if(fadeScrollLeft == null || Display.getInstance().getDisplayHeight() != fadeScrollLeft.getHeight()) { fadeScrollLeft = generateFadeImage(fadeScrollEdgeStartAlpha, fadeScrollEdgeEndAlpha, c.getStyle().getBgColor(), true, fadeScrollEdgeLength, Display.getInstance().getDisplayHeight()); } g.drawImage(fadeScrollLeft, c.getX(), c.getY()); } if(offsetRatio < 1 - blockSizeRatio) { // special case since when scrolling with the physical keys we leave // the margin out of the equasion int l = c.getScrollX() + c.getWidth() + c.getStyle().getHorizontalMargins() + c.getStyle().getHorizontalPadding(); int totalScroll = c.getScrollDimension().getWidth(); if(l >= totalScroll) { return; } if(fadeScrollRight == null || Display.getInstance().getDisplayHeight() != fadeScrollRight.getHeight()) { fadeScrollRight = generateFadeImage(fadeScrollEdgeEndAlpha, fadeScrollEdgeStartAlpha, c.getStyle().getBgColor(), true, fadeScrollEdgeLength, Display.getInstance().getDisplayHeight()); } g.drawImage(fadeScrollRight, c.getX() + c.getWidth() - fadeScrollRight.getWidth(), c.getY()); } } } private void drawScroll(Graphics g, Component c, float offsetRatio, float blockSizeRatio, boolean isVertical, int x, int y, int width, int height, Component scroll, Component scrollThumb) { Style scrollStyle = scroll.getUnselectedStyle(); Style scrollThumbStyle = scrollThumb.getUnselectedStyle(); int alpha = scrollStyle.getBgTransparency() & 0xff; int thumbAlpha = scrollThumbStyle.getBgTransparency() & 0xff; int originalAlpha = g.getAlpha(); if(fadeScrollBar) { if(scrollStyle.getBgTransparency() != 0) { scrollStyle.setBgTransparency(c.getScrollOpacity(), true); } scrollThumbStyle.setBgTransparency(c.getScrollOpacity(), true); g.setAlpha(c.getScrollOpacity()); } // take margin into consideration when positioning the scroll int marginLeft = scrollStyle.getMarginLeft(c.isRTL()); int marginTop = scrollStyle.getMarginTop(); x += marginLeft; width -= (marginLeft + scrollStyle.getMarginRight(c.isRTL())); y += marginTop; height -= (marginTop + scrollStyle.getMarginBottom()); scroll.setX(x); scroll.setY(y); scroll.setWidth(width); scroll.setHeight(height); int cx = g.getClipX(); int cy = g.getClipY(); int cw = g.getClipWidth(); int ch = g.getClipHeight(); scroll.paintComponent(g); marginLeft = scrollThumbStyle.getMarginLeft(c.isRTL()); marginTop = scrollThumbStyle.getMarginTop(); x += marginLeft; width -= (marginLeft + scrollThumbStyle.getMarginRight(c.isRTL())); y += marginTop; height -= (marginTop + scrollThumbStyle.getMarginBottom()); int offset, blockSize; if (isVertical) { blockSize = (int) (c.getHeight() * blockSizeRatio) + 2; offset = (int) ((c.getHeight()) * offsetRatio); } else { blockSize = (int) (c.getWidth() * blockSizeRatio) + 2; offset = (int) ((c.getWidth()) * offsetRatio); } if (isVertical) { scrollThumb.setX(x); scrollThumb.setY(y + offset); scrollThumb.setWidth(width); scrollThumb.setHeight(blockSize); } else { scrollThumb.setX(x + offset); scrollThumb.setY(y); scrollThumb.setWidth(blockSize); scrollThumb.setHeight(height); } g.setClip(cx, cy, cw, ch); scrollThumb.paintComponent(g); g.setClip(cx, cy, cw, ch); if(fadeScrollBar) { scrollStyle.setBgTransparency(alpha, true); scrollThumbStyle.setBgTransparency(thumbAlpha, true); g.setAlpha(originalAlpha); } } /** * Sets the foreground color and font for a generic component, reuse-able by most component * drawing code * * @param g graphics context * @param c component from which fg styles should be set */ public void setFG(Graphics g, Component c) { Style s = c.getStyle(); g.setFont(s.getFont()); g.setColor(s.getFgColor()); } /** * Returns the default width of a vertical scroll bar * * @return default width of a vertical scroll bar */ public int getVerticalScrollWidth() { if(verticalScroll == null) { initScroll(); } Style scrollStyle = verticalScroll.getStyle(); // bidi doesn't matter for width calculations return scrollStyle.getMarginLeftNoRTL() + scrollStyle.getMarginRightNoRTL() + scrollStyle.getPaddingLeftNoRTL() + scrollStyle.getPaddingRightNoRTL(); } /** * Returns the default height of a horizontal scroll bar * * @return default height of a horizontal scroll bar */ public int getHorizontalScrollHeight() { if(horizontalScroll == null) { initScroll(); } Style scrollStyle = horizontalScroll.getStyle(); // bidi doesn't matter for height calculations return scrollStyle.getMarginTop() + scrollStyle.getMarginBottom() + scrollStyle.getPaddingTop() + scrollStyle.getPaddingBottom(); } /** * Draws generic component border */ void drawBorder(Graphics g, Component c, int color, int borderWidth) { drawBorder(g, c, color, color, borderWidth); } /** * Draws generic component border */ void drawBorder(Graphics g, Component c, int topAndRightColor, int bottomAndLeftColor, int borderWidth) { g.setColor(topAndRightColor); //Text Component upper border color g.fillRect(c.getX(), c.getY(), c.getWidth(), borderWidth); g.fillRect(c.getX(), c.getY(), borderWidth, c.getHeight()); g.setColor(bottomAndLeftColor); //Text Component lower border color g.fillRect(c.getX(), c.getY() + c.getHeight() - borderWidth, c.getWidth(), borderWidth); g.fillRect(c.getX() + c.getWidth() - borderWidth, c.getY(), borderWidth, c.getHeight()); } /** * Allows us to define a default animation that will draw the transition for * entering a form * * @return default transition */ public Transition getDefaultFormTransitionIn() { return defaultFormTransitionIn; } /** * Allows us to define a default animation that will draw the transition for * entering a form * * @param defaultFormTransitionIn the default transition */ public void setDefaultFormTransitionIn(Transition defaultFormTransitionIn) { this.defaultFormTransitionIn = defaultFormTransitionIn; } /** * Allows us to define a default animation that will draw the transition for * exiting a form * * @return default transition */ public Transition getDefaultFormTransitionOut() { return defaultFormTransitionOut; } /** * Allows us to define a default animation that will draw the transition for * exiting a form * * @param defaultFormTransitionOut the default transition */ public void setDefaultFormTransitionOut(Transition defaultFormTransitionOut) { this.defaultFormTransitionOut = defaultFormTransitionOut; } /** * Allows us to define a default animation that will draw the transition for * entering a Menu * * @return default transition */ public Transition getDefaultMenuTransitionIn() { return defaultMenuTransitionIn; } /** * Allows us to define a default animation that will draw the transition for * entering a Menu * * @param defaultMenuTransitionIn the default transition */ public void setDefaultMenuTransitionIn(Transition defaultMenuTransitionIn) { this.defaultMenuTransitionIn = defaultMenuTransitionIn; } /** * Allows us to define a default animation that will draw the transition for * exiting a Menu * * @return default transition */ public Transition getDefaultMenuTransitionOut() { return defaultMenuTransitionOut; } /** * Allows us to define a default animation that will draw the transition for * exiting a Menu * * @param defaultMenuTransitionOut the default transition */ public void setDefaultMenuTransitionOut(Transition defaultMenuTransitionOut) { this.defaultMenuTransitionOut = defaultMenuTransitionOut; } /** * Allows us to define a default animation that will draw the transition for * entering a dialog * * @return default transition */ public Transition getDefaultDialogTransitionIn() { return defaultDialogTransitionIn; } /** * Allows us to define a default animation that will draw the transition for * entering a dialog * * @param defaultDialogTransitionIn the default transition */ public void setDefaultDialogTransitionIn(Transition defaultDialogTransitionIn) { this.defaultDialogTransitionIn = defaultDialogTransitionIn; } /** * Allows us to define a default animation that will draw the transition for * exiting a dialog * * @return default transition */ public Transition getDefaultDialogTransitionOut() { return defaultDialogTransitionOut; } /** * Allows us to define a default animation that will draw the transition for * exiting a dialog * * @param defaultDialogTransitionOut the default transition */ public void setDefaultDialogTransitionOut(Transition defaultDialogTransitionOut) { this.defaultDialogTransitionOut = defaultDialogTransitionOut; } /** * Tint color is set when a form is partially covered be it by a menu or by a * dialog. A look and feel can override this default value. * * @return default tint color */ public int getDefaultFormTintColor() { return defaultFormTintColor; } /** * Tint color is set when a form is partially covered be it by a menu or by a * dialog. A look and feel can override this default value. * * @param defaultFormTintColor the default tint color */ public void setDefaultFormTintColor(int defaultFormTintColor) { this.defaultFormTintColor = defaultFormTintColor; } /** * This color is used to paint disable mode text color. * @return the color value */ public int getDisableColor() { return disableColor; } /** * Simple setter to disable color * * @param disableColor the disable color value */ public void setDisableColor(int disableColor) { this.disableColor = disableColor; } /** * Indicates whether lists and containers should have smooth scrolling by default * * @return true if smooth scrolling should be on by default */ public boolean isDefaultSmoothScrolling() { return defaultSmoothScrolling; } /** * Indicates whether lists and containers should have smooth scrolling by default * * @param defaultSmoothScrolling true if smooth scrolling should be on by default */ public void setDefaultSmoothScrolling(boolean defaultSmoothScrolling) { this.defaultSmoothScrolling = defaultSmoothScrolling; } /** * Indicates the default speed for smooth scrolling * * @return speed for smooth scrollin */ public int getDefaultSmoothScrollingSpeed() { return defaultSmoothScrollingSpeed; } /** * Indicates the default speed for smooth scrolling * * @param defaultSmoothScrollingSpeed speed for smooth scrollin */ public void setDefaultSmoothScrollingSpeed(int defaultSmoothScrollingSpeed) { this.defaultSmoothScrollingSpeed = defaultSmoothScrollingSpeed; } /** * Indicates whether softbuttons should be reversed from their default orientation * * @return true if softbuttons should be reversed */ public boolean isReverseSoftButtons() { return reverseSoftButtons; } /** * Indicates whether softbuttons should be reversed from their default orientation * * @param reverseSoftButtons true if softbuttons should be reversed */ public void setReverseSoftButtons(boolean reverseSoftButtons) { this.reverseSoftButtons = reverseSoftButtons; } /** * This method returns the MenuBar class. * * @return the MenuBar class. */ public Class getMenuBarClass(){ return menuBar; } /** * Simple setter for the MenuBar Class * * @param menuBar */ public void setMenuBarClass(Class menuBar) { this.menuBar = menuBar; } /** * Returns the Menu default renderer * * @return default renderer for the menu */ public ListCellRenderer getMenuRenderer() { return menuRenderer; } /** * Sets the Menu default renderer * * @param menuRenderer default renderer for the menu */ public void setMenuRenderer(ListCellRenderer menuRenderer) { this.menuRenderer = menuRenderer; } /** * Sets globally the Menu icons * * @param select select icon * @param cancel cancel icon * @param menu menu icon */ public void setMenuIcons(Image select, Image cancel, Image menu) { menuIcons[0] = select; menuIcons[1] = cancel; menuIcons[2] = menu; } /** * Simple getter for the menu icons * * @return an Image array at size of 3, where the first is the select image * the second is the cancel image and the last is the menu image. */ public Image[] getMenuIcons() { return menuIcons; } /** * Gets the ticker speed * * @return ticker speed in milliseconds */ public long getTickerSpeed() { return tickerSpeed; } /** * Sets the ticker speed * * @param tickerSpeed the speed in milliseconds */ public void setTickerSpeed(long tickerSpeed) { this.tickerSpeed = tickerSpeed; } private void initScroll() { verticalScroll = new Label(); verticalScroll.setUIID("Scroll"); horizontalScroll = new Label(); horizontalScroll.setUIID("HorizontalScroll"); verticalScrollThumb = new Label();; verticalScrollThumb.setUIID("ScrollThumb"); horizontalScrollThumb = new Label(); horizontalScrollThumb.setUIID("HorizontalScrollThumb"); } /** * This method is a callback to the LookAndFeel when a theme is being * changed in the UIManager * @param completeClear indicates that the theme is set and not added */ public void refreshTheme(boolean completeClear) { fadeScrollTop = null; fadeScrollBottom = null; fadeScrollRight = null; fadeScrollLeft = null; initScroll(); if(menuRenderer != null) { if(menuRenderer instanceof Component) { ((Component)menuRenderer).refreshTheme(); } } Toolbar.setGlobalToolbar(manager.isThemeConstant("globalToobarBool", Toolbar.isGlobalToolbar())); boolean isTouch = Display.getInstance().isTouchScreenDevice(); scrollVisible = manager.isThemeConstant("scrollVisibleBool", true); fadeScrollEdge = manager.isThemeConstant("fadeScrollEdgeBool", false); fadeScrollEdgeLength = manager.getThemeConstant("fadeScrollEdgeInt", fadeScrollEdgeLength); fadeScrollBar = manager.isThemeConstant("fadeScrollBarBool", false); try { tickerSpeed = Long.parseLong(manager.getThemeConstant("tickerSpeedInt", "" + tickerSpeed)); if(tickerSpeed < 1) { Label.setDefaultTickerEnabled(false); } else { Label.setDefaultTickerEnabled(true); } } catch(NumberFormatException err) { Log.e(err); } defaultFormTintColor = (int)Long.parseLong(manager.getThemeConstant("tintColor", Integer.toHexString(defaultFormTintColor)), 16); disableColor = Integer.parseInt(manager.getThemeConstant("disabledColor", Integer.toHexString(disableColor)), 16); Dialog.setDefaultDialogPosition(manager.getThemeConstant("dialogPosition", Dialog.getDefaultDialogPosition())); Dialog.setCommandsAsButtons(manager.isThemeConstant("dialogButtonCommandsBool", Dialog.isCommandsAsButtons())); Dialog.setDefaultBlurBackgroundRadius(manager.getThemeConstant("dialogBlurRadiusInt", (int)Dialog.getDefaultBlurBackgroundRadius())); List.setDefaultIgnoreFocusComponentWhenUnfocused(manager.isThemeConstant("ignorListFocusBool", List.isDefaultIgnoreFocusComponentWhenUnfocused())); if(isTouch) { Display.getInstance().setPureTouch(manager.isThemeConstant("pureTouchBool", Display.getInstance().isPureTouch())); } int defaultTransitionSpeed = Integer.parseInt(manager.getThemeConstant("transitionSpeedInt", "220")); String slideDir = manager.getThemeConstant("slideDirection", "horizontal"); String dialogSlideDir = manager.getThemeConstant("dlgSlideDirection", "vertical"); String menuSlideDir = manager.getThemeConstant("menuSlideDirection", dialogSlideDir); boolean outdir = manager.isThemeConstant("slideOutDirBool", false); boolean indir = manager.isThemeConstant("slideInDirBool", true); boolean dialogOutdir = manager.isThemeConstant("dlgSlideOutDirBool", false); boolean dialogIndir = manager.isThemeConstant("dlgSlideInDirBool", true); boolean menuOutdir = manager.isThemeConstant("menuSlideOutDirBool", false); boolean menuIndir = manager.isThemeConstant("menuSlideInDirBool", true); defaultFormTransitionIn = getTransitionConstant(defaultFormTransitionIn, "formTransitionIn", slideDir, defaultTransitionSpeed, indir); defaultFormTransitionOut = getTransitionConstant(defaultFormTransitionOut, "formTransitionOut", slideDir, defaultTransitionSpeed, outdir); defaultMenuTransitionIn = getTransitionConstant(defaultMenuTransitionIn, "menuTransitionIn", menuSlideDir, defaultTransitionSpeed, menuIndir); defaultMenuTransitionOut = getTransitionConstant(defaultMenuTransitionOut, "menuTransitionOut", menuSlideDir, defaultTransitionSpeed, menuOutdir); defaultDialogTransitionIn = getTransitionConstant(defaultDialogTransitionIn, "dialogTransitionIn", dialogSlideDir, defaultTransitionSpeed, dialogIndir); defaultDialogTransitionOut = getTransitionConstant(defaultDialogTransitionOut, "dialogTransitionOut", dialogSlideDir, defaultTransitionSpeed, dialogOutdir); initCommandBehaviorConstant(manager.getThemeConstant("commandBehavior", null), completeClear); reverseSoftButtons = manager.isThemeConstant("reverseSoftButtonsBool", reverseSoftButtons); textFieldCursorColor = manager.getThemeConstant("textFieldCursorColorInt", 0); TextArea.setDefaultValign(manager.getThemeConstant("textCmpVAlignInt", TextArea.getDefaultValign())); defaultSnapToGrid = manager.isThemeConstant("snapGridBool", false); defaultAlwaysTensile = manager.isThemeConstant("alwaysTensileBool", false); defaultTensileDrag = manager.isThemeConstant("tensileDragBool", true); defaultEndsWith3Points = manager.isThemeConstant("endsWith3PointsBool", false); defaultTensileHighlight = manager.isThemeConstant("tensileHighlightBool", false); tensileHighlightBottomImage = null; tensileHighlightTopImage = null; if(defaultTensileHighlight) { tensileHighlightBottomImage = manager.getThemeImageConstant("tensileHighlightBottomImage"); tensileHighlightTopImage = manager.getThemeImageConstant("tensileHighlightTopImage"); tensileGlowBottomImage = manager.getThemeImageConstant("tensileGlowBottomImage"); tensileGlowTopImage = manager.getThemeImageConstant("tensileGlowTopImage"); if(tensileHighlightBottomImage != null && tensileHighlightTopImage != null) { defaultTensileDrag = true; defaultAlwaysTensile = false; } else { defaultTensileHighlight = false; } } backgroundImageDetermineSize = manager.isThemeConstant("bgImageSizeBool", false); } private void initCommandBehaviorConstant(String c, boolean complete) { if(c != null) { if(c.equalsIgnoreCase("SoftKey")) { Display.getInstance().setCommandBehavior(Display.COMMAND_BEHAVIOR_SOFTKEY); return; } if(c.equalsIgnoreCase("Touch")) { Display.getInstance().setCommandBehavior(Display.COMMAND_BEHAVIOR_TOUCH_MENU); return; } if(c.equalsIgnoreCase("Bar")) { Display.getInstance().setCommandBehavior(Display.COMMAND_BEHAVIOR_BUTTON_BAR); return; } if(c.equalsIgnoreCase("Title")) { Display.getInstance().setCommandBehavior(Display.COMMAND_BEHAVIOR_BUTTON_BAR_TITLE_BACK); return; } if(c.equalsIgnoreCase("Right")) { Display.getInstance().setCommandBehavior(Display.COMMAND_BEHAVIOR_BUTTON_BAR_TITLE_RIGHT); return; } if(c.equalsIgnoreCase("Native")) { Display.getInstance().setCommandBehavior(Display.COMMAND_BEHAVIOR_NATIVE); return; } if(c.equalsIgnoreCase("ICS")) { Display.getInstance().setCommandBehavior(Display.COMMAND_BEHAVIOR_ICS); return; } if(c.equalsIgnoreCase("SIDE")) { Display.getInstance().setCommandBehavior(Display.COMMAND_BEHAVIOR_SIDE_NAVIGATION); setMenuBarClass(SideMenuBar.class); return; } } else { if(complete) { Display.getInstance().setCommandBehavior(Display.COMMAND_BEHAVIOR_DEFAULT); } } } private Transition getTransitionConstant(Transition t, String constant, String slideDir, int speed, boolean forward) { Image img = manager.getThemeImageConstant(constant + "Image"); if(img != null) { return CommonTransitions.createTimeline(img); } String val = manager.getThemeConstant(constant, null); if(val == null) { return t; } if(val.equalsIgnoreCase("empty")) { return CommonTransitions.createEmpty(); } if(val.equalsIgnoreCase("slide")) { if(slideDir.equalsIgnoreCase("horizontal")) { return CommonTransitions.createSlide(CommonTransitions.SLIDE_HORIZONTAL, forward, speed); } else { return CommonTransitions.createSlide(CommonTransitions.SLIDE_VERTICAL, forward, speed); } } if(val.equalsIgnoreCase("cover")) { if(slideDir.equalsIgnoreCase("horizontal")) { return CommonTransitions.createCover(CommonTransitions.SLIDE_HORIZONTAL, forward, speed); } else { return CommonTransitions.createCover(CommonTransitions.SLIDE_VERTICAL, forward, speed); } } if(val.equalsIgnoreCase("uncover")) { if(slideDir.equalsIgnoreCase("horizontal")) { return CommonTransitions.createUncover(CommonTransitions.SLIDE_HORIZONTAL, forward, speed); } else { return CommonTransitions.createUncover(CommonTransitions.SLIDE_VERTICAL, forward, speed); } } if(val.equalsIgnoreCase("fslide")) { if(slideDir.equalsIgnoreCase("horizontal")) { return CommonTransitions.createFastSlide(CommonTransitions.SLIDE_HORIZONTAL, forward, speed); } else { return CommonTransitions.createFastSlide(CommonTransitions.SLIDE_VERTICAL, forward, speed); } } if(val.equalsIgnoreCase("fade")) { return CommonTransitions.createFade(speed); } if(val.equalsIgnoreCase("slidefade")) { return CommonTransitions.createSlideFadeTitle(forward, speed); } if(val.equalsIgnoreCase("pulse")) { return CommonTransitions.createDialogPulsate(); } if(val.equalsIgnoreCase("bubble")) { BubbleTransition transition = new BubbleTransition(speed); transition.setRoundBubble(false); return transition; } return t; } /** * Indicates whether the menu UI should target a touch based device or a * standard cell phone * * @return true for touch menus * @deprecated use Display.getCommandBehavior() == Display.COMMAND_BEHAVIOR_TOUCH_MENU */ public boolean isTouchMenus() { int t = Display.getInstance().getCommandBehavior(); return t == Display.COMMAND_BEHAVIOR_TOUCH_MENU || (t == Display.COMMAND_BEHAVIOR_DEFAULT && Display.getInstance().isTouchScreenDevice()); } /** * Indicates whether the menu UI should target a touch based device or a * standard cell phone * * @param touchMenus true to enable touch menus false to disable * @deprecated use Display.setCommandBehavior(Display.COMMAND_BEHAVIOR_TOUCH_MENU) */ public void setTouchMenus(boolean touchMenus) { if(touchMenus) { Display.getInstance().setCommandBehavior(Display.COMMAND_BEHAVIOR_TOUCH_MENU); } else { Display.getInstance().setCommandBehavior(Display.COMMAND_BEHAVIOR_SOFTKEY); } } /** * Sets this LookAndFeel to operate in right-to-left mode. * * @param rtl - true if right-to-left, false if left-to-right */ public void setRTL(boolean rtl) { if(UIManager.localeAccessible) { this.rtl = rtl; if(rtl) { Display.getInstance().setBidiAlgorithm(true); } } } /** * Use this to check if the LookAndFeel is in RTL mode * * @return true if the LookAndFeel is in right-to-left mode, false otherwise */ public boolean isRTL() { return rtl; } /** * Allows defining a tactile touch device that vibrates when the user presses a component * that should respond with tactile feedback on a touch device (e.g. vibrate). * Setting this to 0 disables tactile feedback completely * @return the tactileTouchDuration */ public int getTactileTouchDuration() { return tactileTouchDuration; } /** * Allows defining a tactile touch device that vibrates when the user presses a component * that should respond with tactile feedback on a touch device (e.g. vibrate). * Setting this to 0 disables tactile feedback completely * * @param tactileTouchDuration the duration of vibration */ public void setTactileTouchDuration(int tactileTouchDuration) { this.tactileTouchDuration = tactileTouchDuration; } /** * Indicates whether labels should end with 3 points by default * * @return whether labels should end with 3 points by default */ public boolean isDefaultEndsWith3Points() { return defaultEndsWith3Points; } /** * Indicates whether labels should end with 3 points by default * * @param defaultEndsWith3Points True to indicates that labels should end with 3 points by default */ public void setDefaultEndsWith3Points(boolean defaultEndsWith3Points) { this.defaultEndsWith3Points = defaultEndsWith3Points; } /** * Indicates whether tensile drag should be active by default * * @return whether tensile drag should be active by default */ public boolean isDefaultTensileDrag() { return defaultTensileDrag; } /** * Indicates whether tensile drag should be active by default * * @param defaultTensileDrag true if tensile drag should be active by default */ public void setDefaultTensileDrag(boolean defaultTensileDrag) { this.defaultTensileDrag = defaultTensileDrag; } /** * Indicates whether lists and containers should scroll only via focus and thus "jump" when * moving to a larger component as was the case in older versions of Codename One. * * @return true if focus scrolling is enabled */ public boolean isFocusScrolling() { return focusScrolling; } /** * Indicates whether lists and containers should scroll only via focus and thus "jump" when * moving to a larger component as was the case in older versions of Codename One. * * @param focusScrolling true to enable focus scrolling */ public void setFocusScrolling(boolean focusScrolling) { this.focusScrolling = focusScrolling; } /** * Indicates whether the edge of a scrollable area should fade out * * @return the fadeScrollEdge */ public boolean isFadeScrollEdge() { return fadeScrollEdge; } /** * Indicates whether the edge of a scrollable area should fade out * * @param fadeScrollEdge the fadeScrollEdge to set */ public void setFadeScrollEdge(boolean fadeScrollEdge) { this.fadeScrollEdge = fadeScrollEdge; } /** * Indicates whether the scrollbar should fade when unused * * @return the fadeScrollBar */ public boolean isFadeScrollBar() { return fadeScrollBar; } /** * Indicates whether the scrollbar should fade when unused * * @param fadeScrollBar the fadeScrollBar to set */ public void setFadeScrollBar(boolean fadeScrollBar) { this.fadeScrollBar = fadeScrollBar; } /** * Indicates the width/height of the fading edge to indicate scrolling * * @return the fadeScrollEdgeLength */ public int getFadeScrollEdgeLength() { return fadeScrollEdgeLength; } /** * Indicates the width/height of the fading edge to indicate scrolling * * @param fadeScrollEdgeLength the fadeScrollEdgeLength to set */ public void setFadeScrollEdgeLength(int fadeScrollEdgeLength) { this.fadeScrollEdgeLength = fadeScrollEdgeLength; } /** * The color of the text field cursor * @return the textFieldCursorColor */ public int getTextFieldCursorColor() { return textFieldCursorColor; } /** * The color of the text field cursor * @param textFieldCursorColor the textFieldCursorColor to set */ public void setTextFieldCursorColor(int textFieldCursorColor) { this.textFieldCursorColor = textFieldCursorColor; } /** * Indicates whether scrolling this component should jump to a specific location * in a grid * @return the defaultSnapToGrid */ public boolean isDefaultSnapToGrid() { return defaultSnapToGrid; } /** * Indicates whether scrolling this component should jump to a specific location * in a grid * @param defaultSnapToGrid the defaultSnapToGrid to set */ public void setDefaultSnapToGrid(boolean defaultSnapToGrid) { this.defaultSnapToGrid = defaultSnapToGrid; } /** * Enable the tensile drag to work even when a component doesn't have a scroll showable (scrollable flag still needs to be set to true) * @return the defaultAlwaysTensile */ public boolean isDefaultAlwaysTensile() { return defaultAlwaysTensile; } /** * Enable the tensile drag to work even when a component doesn't have a scroll showable (scrollable flag still needs to be set to true) * @param defaultAlwaysTensile the defaultAlwaysTensile to set */ public void setDefaultAlwaysTensile(boolean defaultAlwaysTensile) { this.defaultAlwaysTensile = defaultAlwaysTensile; } /** * Indicates whether tensile highlight should be active by default * @return the defaultTensileHighlight */ public boolean isDefaultTensileHighlight() { return defaultTensileHighlight; } /** * Paints the tensile hightlight image * * @param g graphics destination for the tensile highlight image * @param top destination of the tensile highlight image * @param opacity the opacity of the image */ public void paintTensileHighlight(Component t, Graphics g, boolean top, int opacity) { if(opacity > 0 && tensileHighlightTopImage != null && tensileHighlightBottomImage != null) { int absX = t.getAbsoluteX(); int absY = t.getAbsoluteY(); if(tensileGlowTopImage != null) { int a = g.getAlpha(); float aspect = ((float)tensileGlowTopImage.getWidth()) / ((float)Display.getInstance().getDisplayWidth()); int newHeight = (int)(((float)tensileGlowTopImage.getHeight()) * aspect); if(top) { // this is a pull to refresh operation if(t.isAlwaysTensile()) { return; } g.drawImage(tensileHighlightTopImage, absX, absY, t.getWidth(), tensileHighlightTopImage.getHeight()); g.setAlpha(opacity / 3); g.drawImage(tensileGlowTopImage, absX, absY, t.getWidth(), newHeight); g.setAlpha(a); } else { g.drawImage(tensileHighlightBottomImage, absX, absY + t.getScrollY() + (t.getHeight() - tensileHighlightBottomImage.getHeight()), t.getWidth(), tensileHighlightBottomImage.getHeight()); g.setAlpha(opacity / 3); g.drawImage(tensileGlowBottomImage, absX, absY + t.getScrollY() +(t.getHeight() - newHeight), t.getWidth(), newHeight); g.setAlpha(a); } } else { int a = g.getAlpha(); g.setAlpha(opacity); if(top) { // this is a pull to refresh operation if(t.isAlwaysTensile()) { g.setAlpha(a); return; } g.drawImage(tensileHighlightTopImage, absX, absY, Display.getInstance().getDisplayWidth(), tensileHighlightTopImage.getHeight()); } else { g.drawImage(tensileHighlightBottomImage, absX, absY + t.getScrollY() + t.getHeight() - tensileHighlightBottomImage.getHeight(), Display.getInstance().getDisplayWidth(), tensileHighlightBottomImage.getHeight()); } g.setAlpha(a); } } } UIManager getUIManager(){ return manager; } /** * @return the fadeScrollBarSpeed */ public int getFadeScrollBarSpeed() { return fadeScrollBarSpeed; } /** * @return scrollVisible */ public boolean isScrollVisible() { return scrollVisible; } /** * @param fadeScrollBarSpeed the fadeScrollBarSpeed to set */ public void setFadeScrollBarSpeed(int fadeScrollBarSpeed) { this.fadeScrollBarSpeed = fadeScrollBarSpeed; } /** * Indicates if the bg image of a style should determine the minimum preferred size according to the theme * @return the backgroundImageDetermineSize */ public boolean isBackgroundImageDetermineSize() { return backgroundImageDetermineSize; } /** * Indicates if the bg image of a style should determine the minimum preferred size according to the theme * @param backgroundImageDetermineSize the backgroundImageDetermineSize to set */ public void setBackgroundImageDetermineSize(boolean backgroundImageDetermineSize) { this.backgroundImageDetermineSize = backgroundImageDetermineSize; } /** * Paints the pull to refresh * @param g graphics context * @param cmp the Component which we draw the pull to refresh beneath it * @param taskExecuted an indication if the refresh task is currently running */ public abstract void drawPullToRefresh(Graphics g, Component cmp, boolean taskExecuted); /** * Returns the required height of the pull to refresh feature */ public abstract int getPullToRefreshHeight(); }