/* * 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.charts.util.ColorUtil; import com.codename1.io.Log; import com.codename1.ui.*; import static com.codename1.ui.ComponentSelector.$; import com.codename1.ui.events.ActionEvent; import com.codename1.ui.events.ActionListener; import com.codename1.ui.plaf.StyleParser.BorderInfo; import com.codename1.ui.plaf.StyleParser.FontInfo; import com.codename1.ui.plaf.StyleParser.ImageInfo; import com.codename1.ui.plaf.StyleParser.MarginInfo; import com.codename1.ui.plaf.StyleParser.PaddingInfo; import com.codename1.ui.plaf.StyleParser.StyleInfo; import com.codename1.ui.util.EventDispatcher; import com.codename1.ui.util.Resources; import com.codename1.util.StringUtil; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Arrays; import java.util.Enumeration; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; import java.util.Vector; /** * Central point singleton managing the look of the application, this class allows us to * customize the styles (themes) as well as the look instance. * * @author Chen Fishbein */ public class UIManager { private LookAndFeel current; private HashMap<String, Style> styles = new HashMap<String, Style>(); private HashMap<String, Style> selectedStyles = new HashMap<String, Style>(); private HashMap<String, Object> themeProps; private HashMap<String, Object> themeConstants = new HashMap<String, Object>(); static UIManager instance; private Style defaultStyle = new Style(); private Style defaultSelectedStyle = new Style(); /** * This member is used by the resource editor */ static boolean accessible = true; /** * This member is used by the resource editor */ static boolean localeAccessible = true; /** * Useful for caching theme images so they are not loaded twice in case * an image reference is used it two places in the theme (e.g. same background * to title and menu bar). */ private HashMap<String, Image> imageCache = new HashMap<String, Image>(); /** * The resource bundle allows us to implicitly localize the UI on the fly, once its * installed all internal application strings query the resource bundle and extract * their values from this table if applicable. */ private Hashtable resourceBundle; private Map<String, String> bundle; private boolean wasThemeInstalled; /** * This EventDispatcher holds all listeners who would like to register to * Theme refreshed event */ private EventDispatcher themelisteners; UIManager() { // Lazy initialization of instance for js port compatibility. We will // do a double-lazy initialization to try to best prevent regressions // from other projects that may be out of sync. E.g. the Designer project // uses the "instance" property directly. This should guarantee that // instance will be set if (instance == null) { instance = this; } current = new DefaultLookAndFeel(this); resetThemeProps(null); } /** * Indicates if a theme was previously installed since the last reset * @return true if setThemeProps was invoked */ public boolean wasThemeInstalled() { return wasThemeInstalled; } /** * Singleton instance method * * @return Instance of the ui manager */ public static UIManager getInstance() { if (instance == null) { instance = new UIManager(); } return instance; } /** * This factory method allows creating a new UIManager instance, this is usefull where an application * has some screens with different context * @return a new UIManager instance */ public static UIManager createInstance() { return new UIManager(); } /** * Returns the currently installed look and feel * * @return the currently installed look and feel */ public LookAndFeel getLookAndFeel() { return current; } /** * Sets the currently installed look and feel * * @param plaf the look and feel for the application */ public void setLookAndFeel(LookAndFeel plaf) { current.uninstall(); current = plaf; } /** * Allows a developer to programmatically install a style into the UI manager * * @param id the component id matching the given style * @param style the style object to install */ public void setComponentStyle(String id, Style style) { if (id == null || id.length() == 0) { //if no id return the default style id = ""; } else { id = id + "."; } styles.put(id, style); } /** * Allows a developer to programmatically install a style into the UI manager * * @param id the component id matching the given style * @param style the style object to install * @param type press, dis or other custom type */ public void setComponentStyle(String id, Style style, String type) { if(type != null && type.length() > 0) { if (id == null || id.length() == 0) { //if no id return the default style id = type + "#"; } else { id = id + "." + type + "#"; } } else { if (id == null || id.length() == 0) { //if no id return the default style id = ""; } else { id = id + "."; } } styles.put(id, style); } /** * Allows a developer to programmatically install a style into the UI manager * * @param id the component id matching the given style * @param style the style object to install */ public void setComponentSelectedStyle(String id, Style style) { if (id == null || id.length() == 0) { //if no id return the default style id = ""; } else { id = id + "."; } selectedStyles.put(id, style); } /** * Returns the style of the component with the given id or a <b>new instance</b> of the default * style. * This method will always return a new style instance to prevent modification of the global * style object. * * @param id the component id whose style we want * @return the appropriate style (this method never returns null) */ public Style getComponentStyle(String id) { return getComponentStyleImpl(id, false, ""); } /** * Returns the style of the component with the given baseStyle or a <b>new instance</b> of the default * style, but overrides styles based on the directives in the styleStrings. * * This method will always return a new style instance to prevent modification of the global * style object. * * @param theme Theme file used to retrieve images that are referenced by the styleString * @param baseStyle The component ID that serves as the base style for this style. These base styles are * overridden by the styles provided in styleString. * @param id the component id into which the resulting style is to be cached. * @param styleString Array of style strings to override the styles in {@literal baseStyle}. Style string syntax is * is {@literal key1:value1; key2:value2; key3:value3; etc...}. While this is similar to CSS, it is not CSS. The keys * and values * correspond to properties of {@link Style} and their associated values. * @return the appropriate style (this method never returns null) */ public Style parseComponentStyle(Resources theme, String baseStyle, String id, String... styleString) { return parseStyle(theme, id, "", baseStyle, false, styleString); } /** * Returns the selected style of the component with the given id or a <b>new instance</b> of the default * style. * This method will always return a new style instance to prevent modification of the global * style object. * * @param id the component id whose selected style we want * @return the appropriate style (this method never returns null) */ public Style getComponentSelectedStyle(String id) { return getComponentStyleImpl(id, true, "sel#"); } /** * Returns the selected style of the component with the given baseStyle or a <b>new instance</b> of the default * style, but overrides styles based on the directives in the styleStrings. * * This method will always return a new style instance to prevent modification of the global * style object. * * @param theme Theme file used to retrieve images that are referenced by the styleString * @param baseStyle The component ID that serves as the base style for this style. These base styles are * overridden by the styles provided in styleString. * @param id the component id into which the resulting style is to be cached. * @param styleString Array of style strings to override the styles in {@literal baseStyle}. Style string syntax is * is {@literal key1:value1; key2:value2; key3:value3; etc...}. While this is similar to CSS, it is not CSS. The keys * and values * correspond to properties of {@link Style} and their associated values. * @return the appropriate style (this method never returns null) */ public Style parseComponentSelectedStyle(Resources theme, String baseStyle, String id, String... styleString) { return parseStyle(theme, id, "sel#", baseStyle, true, styleString); } /** * Returns a custom style for the component with the given id, this method always returns a * new instance. Custom styles allow us to install application specific or component specific * style attributes such as pressed, disabled, hover etc. * * @param id the component id whose custom style we want * @param type the style type * @return the appropriate style (this method never returns null) */ public Style getComponentCustomStyle(String id, String type) { return getComponentStyleImpl(id, false, type + "#"); } /** * Returns the selected style of the component with the given baseStyle or a <b>new instance</b> of the default * style, but overrides styles based on the directives in the styleStrings. * * This method will always return a new style instance to prevent modification of the global * style object. * * @param theme Theme file used to retrieve images that are referenced by the styleString * @param baseStyle The component ID that serves as the base style for this style. These base styles are * overridden by the styles provided in styleString. * @param id the component id into which the resulting style is to be cached. * @param type the style type * @param styleString Array of style strings to override the styles in {@literal baseStyle}. Style string syntax is * is {@literal key1:value1; key2:value2; key3:value3; etc...}. While this is similar to CSS, it is not CSS. The keys * and values * correspond to properties of {@link Style} and their associated values. * @return the appropriate style (this method never returns null) */ public Style parseComponentCustomStyle(Resources theme, String baseStyle, String id, String type, String... styleString) { return parseStyle(theme, id, type+"#", baseStyle, false, styleString); } private Style getComponentStyleImpl(String id, boolean selected, String prefix) { try { Style style = null; if (id == null || id.length() == 0) { //if no id return the default style id = ""; } else { id = id + "."; } if (selected) { style = (Style) selectedStyles.get(id); if (style == null) { style = createStyle(id, prefix, true); selectedStyles.put(id, style); } } else { if (prefix.length() == 0) { style = (Style) styles.get(id); if (style == null) { style = createStyle(id, prefix, false); styles.put(id, style); } } else { return createStyle(id, prefix, false); } } return new Style(style); } catch(Throwable err) { // fail gracefully for an illegal style, this is useful for the resource editor Log.p("Error creating style " + id + " selected: " + selected + " prefix: " + prefix); Log.e(err); return new Style(defaultStyle); } } /** * @return the name of the current theme for theme switching UI's */ public String getThemeName() { if (themeProps != null) { return (String) themeProps.get("name"); } return null; } // for internal use by the resource editor HashMap<String, Object> getThemeProps() { return themeProps; } /** * Initializes the theme properties with the current "defaults" * * @param installedTheme the theme to be installed or null, this is used * to check if style inheritance is used in which case we must NOT init * style defaults for that particular component */ private void resetThemeProps(Hashtable installedTheme) { themeProps = new HashMap<String, Object>(); wasThemeInstalled = false; if(current == null) { current = new DefaultLookAndFeel(this); } String disabledColor = Integer.toHexString(getLookAndFeel().getDisableColor()); Integer centerAlign = new Integer(Component.CENTER); Integer rightAlign = new Integer(Component.RIGHT); Integer leftAlign = new Integer(Component.LEFT); // global settings themeProps.put("sel#transparency", "255"); themeProps.put("dis#fgColor", disabledColor); Boolean darkModeBoolean = (Boolean)themeProps.get("@darkModeBool"); boolean darkMode = darkModeBoolean != null && darkModeBoolean .booleanValue() && CN.isDarkMode() != null && CN.isDarkMode().booleanValue(); Font thinFont = Font.getDefaultFont(); Font lightFont = thinFont; Font italic = Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_ITALIC, Font.SIZE_MEDIUM); Font bold = Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_MEDIUM); if(Font.isNativeFontSchemeSupported()) { int size = Display.getInstance().convertToPixels(2.5f); thinFont = Font.createTrueTypeFont("native:MainThin", "native:MainThin").derive(size, Font.STYLE_PLAIN); lightFont = Font.createTrueTypeFont("native:MainLight", "native:MainLight").derive(size, Font.STYLE_PLAIN); italic = Font.createTrueTypeFont("native:ItalicLight", "native:ItalicLight").derive(size, Font.STYLE_ITALIC); bold = Font.createTrueTypeFont(Font.NATIVE_MAIN_BOLD, Font.NATIVE_MAIN_BOLD).derive(size, Font.STYLE_BOLD); } // component specific settings if (installedTheme == null || !installedTheme.containsKey("ToolbarSearch.derive")) { themeProps.put("ToolbarSearch.derive", "Toolbar"); } themeProps.put("ToolbarLandscape.derive", "Toolbar"); themeProps.put("TitleCommandLandscape.derive", "TitleCommand"); themeProps.put("BackCommandLandscape.derive", "BackCommand"); themeProps.put("TitleLandscape.derive", "Title"); themeProps.put("StatusBarLandscape.derive", "StatusBar"); String foreground = "0"; String background = "ffffff"; if(darkMode) { foreground = "ffffff"; background = "0"; } if (installedTheme == null || !installedTheme.containsKey("TextFieldSearch.derive")) { themeProps.put("TextFieldSearch.derive", "Title"); themeProps.put("TextFieldSearch.align", leftAlign); themeProps.put("TextFieldSearch.sel#align", leftAlign); themeProps.put("TextFieldSearch.press#align", leftAlign); themeProps.put("TextFieldSearch.dis#align", leftAlign); themeProps.put("TextFieldSearch.sel#derive", "TextFieldSearch"); themeProps.put("TextFieldSearch.press#derive", "TextFieldSearch"); themeProps.put("TextFieldSearch.dis#derive", "TextFieldSearch"); } if (installedTheme == null || !installedTheme.containsKey("TextHintSearch.derive")) { themeProps.put("TextHintSearch.derive", "TextHint"); themeProps.put("TextHintSearch.transparency", "0"); } if (installedTheme == null || !installedTheme.containsKey("AccordionItem.derive")) { themeProps.put("AccordionItem.margin", "0,0,0,0"); themeProps.put("AccordionItem.padding", "1,1,1,1"); themeProps.put("AccordionItem.border", Border.createLineBorder(1)); } if (installedTheme == null || !installedTheme.containsKey("AccordionHeader.derive")) { themeProps.put("AccordionHeader.margin", "0,0,0,0"); themeProps.put("AccordionHeader.sel#margin", "0,0,0,0"); themeProps.put("AccordionHeader.press#margin", "0,0,0,0"); themeProps.put("AccordionHeader.padding", "0,0,0,0"); themeProps.put("AccordionHeader.sel#padding", "0,0,0,0"); themeProps.put("AccordionHeader.press#padding", "0,0,0,0"); } if (installedTheme == null || !installedTheme.containsKey("SignatureButton.derive")) { themeProps.put("SignatureButton.align", centerAlign); themeProps.put("SignatureButton.sel#derive", "SignatureButton"); themeProps.put("SignatureButton.press#derive", "SignatureButton"); themeProps.put("SignatureButton.dis#derive", "SignatureButton"); } if (installedTheme == null || !installedTheme.containsKey("ToastBar.derive")) { themeProps.put("ToastBar.margin", "0,0,0,0"); if(darkMode) { themeProps.put("ToastBar.bgColor", "dddddd"); } else { themeProps.put("ToastBar.bgColor", "0"); } themeProps.put("ToastBar.transparency", "200"); themeProps.put("ToastBar.bgType", new Byte(Style.BACKGROUND_NONE)); themeProps.put("ToastBar.border", Border.createEmpty()); themeProps.put("ToastBar.sel#derive", "ToastBar"); themeProps.put("ToastBar.press#derive", "ToastBar"); themeProps.put("ToastBar.dis#derive", "ToastBar"); } if (installedTheme == null || !installedTheme.containsKey("ToastBarMessage.derive")) { themeProps.put("ToastBarMessage.font", lightFont); themeProps.put("ToastBarMessage.transparency", "0"); themeProps.put("ToastBarMessage.fgColor", "FFFFFF"); themeProps.put("ToastBarMessage.bgType", new Byte(Style.BACKGROUND_NONE)); themeProps.put("ToastBarMessage.border", Border.createEmpty()); themeProps.put("ToastBarMessage.sel#derive", "ToastBarMessage"); themeProps.put("ToastBarMessage.press#derive", "ToastBarMessage"); themeProps.put("ToastBarMessage.dis#derive", "ToastBarMessage"); } if (installedTheme == null || !installedTheme.containsKey("Sheet.derive")) { themeProps.put("Sheet.padding", "0,0,0,0"); themeProps.put("Sheet.margin", "0,0,0,0"); themeProps.put("Sheet.bgType", new Byte(Style.BACKGROUND_NONE)); if(darkMode) { themeProps.put("Sheet.bgColor", "333333"); } else { themeProps.put("Sheet.bgColor", "FFFFFF"); } themeProps.put("Sheet.transparency", "255"); themeProps.put("Sheet.border", RoundRectBorder.create() //.topOnlyMode(true) .bottomLeftMode(false) .bottomRightMode(false) .cornerRadius(2f)); themeProps.put("Sheet.sel#derive", "Sheet"); themeProps.put("Sheet.press#derive", "Sheet"); themeProps.put("Sheet.dis#derive", "Sheet"); themeProps.put("SheetTitle.fgColor", foreground); themeProps.put("SheetTitle.transparency", "0"); themeProps.put("SheetTitle.font", bold); themeProps.put("SheetTitle.align", centerAlign); themeProps.put("SheetTitle.sel#derive", "SheetTitle"); themeProps.put("SheetTitle.press#derive", "SheetTitle"); themeProps.put("SheetTitle.dis#derive", "SheetTitle"); themeProps.put("SheetTitleBar.transparency", "0"); themeProps.put("SheetTitleBar.border", Border.createCompoundBorder(Border.createEmpty(), Border.createLineBorder(1, 0xcccccc), Border.createEmpty(), Border.createEmpty())); themeProps.put("SheetTitleBar.sel#derive", "SheetTitleBar"); themeProps.put("SheetTitleBar.press#derive", "SheetTitleBar"); themeProps.put("SheetTitleBar.dis#derive", "SheetTitleBar"); if(darkMode) { themeProps.put("SheetBackButton.fgColor", "999999"); } else { themeProps.put("SheetBackButton.fgColor", "333333"); } themeProps.put("SheetBackButton.transparency", "0"); themeProps.put("SheetBackButton.border", Border.createEmpty()); themeProps.put("SheetBackButton.sel#derive", "SheetBackButton"); themeProps.put("SheetBackButton.press#derive", "SheetBackButton"); themeProps.put("SheetBackButton.dis#derive", "SheetBackButton"); } if (installedTheme == null || !installedTheme.containsKey("ChartComponent.derive")) { themeProps.put("ChartComponent.transparency", "0"); themeProps.put("ChartComponent.sel#derive", "ChartComponent"); themeProps.put("ChartComponent.press#derive", "ChartComponent"); } if(installedTheme == null || !installedTheme.containsKey("Button.derive")) { themeProps.put("Button.border", Border.getDefaultBorder()); themeProps.put("Button.padding", "4,4,4,4"); } if(installedTheme == null || !installedTheme.containsKey("Button.sel#derive")) { themeProps.put("Button.sel#border", Border.getDefaultBorder()); themeProps.put("Button.sel#bgColor", "a0a0a0"); themeProps.put("Button.sel#padding", "4,4,4,4"); } if(installedTheme == null || !installedTheme.containsKey("RaisedButton.derive")) { themeProps.put("RaisedButton.derive", "Button"); themeProps.put("RaisedButton.sel#derive", "Button.sel"); themeProps.put("RaisedButton.press#derive", "Button.press"); themeProps.put("RaisedButton.dis#derive", "Button.dis"); } if(installedTheme == null || !installedTheme.containsKey("Button.press#derive")) { themeProps.put("Button.press#border", Border.getDefaultBorder().createPressedVersion()); themeProps.put("Button.press#derive", "Button"); themeProps.put("Button.press#padding", "4,4,4,4"); } themeProps.put("Button.dis#derive", "Button"); if(installedTheme == null || !installedTheme.containsKey("CalendarTitle.derive")) { themeProps.put("CalendarTitle.align", centerAlign); } if(installedTheme == null || !installedTheme.containsKey("CalendarMultipleDay.derive")) { themeProps.put("CalendarMultipleDay.border", Border.getDefaultBorder()); themeProps.put("CalendarMultipleDay.align", centerAlign); } themeProps.put("CalendarMultipleDay.sel#derive", "CalendarMultipleDay"); if(installedTheme == null || !installedTheme.containsKey("CalendarSelectedDay.derive")) { themeProps.put("CalendarSelectedDay.border", Border.getDefaultBorder()); themeProps.put("CalendarSelectedDay.align", centerAlign); } themeProps.put("CalendarSelectedDay.sel#derive", "CalendarSelectedDay"); if(installedTheme == null || !installedTheme.containsKey("CalendarDay.derive")) { themeProps.put("CalendarDay.align", centerAlign); } themeProps.put("CalendarDay.dis#derive", "CalendarDay"); themeProps.put("CalendarDay.press#derive", "CalendarDay"); if(installedTheme == null || !installedTheme.containsKey("CalendarDay.sel#derive")) { themeProps.put("CalendarDay.sel#align", centerAlign); } if(installedTheme == null || !installedTheme.containsKey("ComboBox.derive")) { themeProps.put("ComboBox.border", Border.getDefaultBorder()); } themeProps.put("ComboBox.sel#derive", "ComboBox"); if(installedTheme == null || !installedTheme.containsKey("MenuButton.derive")) { themeProps.put("MenuButton.transparency", "0"); } if(installedTheme == null || !installedTheme.containsKey("ComboBoxItem.derive")) { themeProps.put("ComboBoxItem.margin", "0,0,0,0"); themeProps.put("ComboBoxItem.transparency", "0"); } themeProps.put("ComboBoxItem.sel#derive", "ComboBoxItem"); themeProps.put("ComboBoxItem.dis#derive", "ComboBoxItem"); if(installedTheme == null || !installedTheme.containsKey("ComboBoxList.derive")) { themeProps.put("ComboBoxList.margin", "2,2,2,2"); themeProps.put("ComboBoxList.padding", "0,0,0,0"); themeProps.put("ComboBoxList.transparency", "0"); } if(installedTheme == null || !installedTheme.containsKey("ComboBoxList.sel#derive")) { themeProps.put("ComboBoxList.sel#margin", "2,2,2,2"); themeProps.put("ComboBoxList.sel#padding", "0,0,0,0"); themeProps.put("ComboBoxList.sel#transparency", "0"); } if(installedTheme == null || !installedTheme.containsKey("ComboBoxPopup.derive")) { themeProps.put("ComboBoxPopup.border", Border.getDefaultBorder()); } themeProps.put("ComboBoxPopup.sel#derive", "ComboBoxPopup"); if(installedTheme == null || !installedTheme.containsKey("Command.derive")) { themeProps.put("Command.margin", "0,0,0,0"); themeProps.put("Command.transparency", "0"); } themeProps.put("Command.sel#derive", "Command"); themeProps.put("Command.dis#derive", "Command"); if(installedTheme == null || !installedTheme.containsKey("CommandList.derive")) { themeProps.put("CommandList.margin", "0,0,0,0"); themeProps.put("CommandList.padding", "0,0,0,0"); themeProps.put("CommandList.transparency", "0"); } themeProps.put("CommandList.sel#derive", "CommandList"); if(installedTheme == null || !installedTheme.containsKey("ComponentGroup.derive")) { themeProps.put("ComponentGroup.derive", "Container"); } if(installedTheme == null || !installedTheme.containsKey("Container.derive")) { themeProps.put("Container.transparency", "0"); themeProps.put("Container.margin", "0,0,0,0"); themeProps.put("Container.padding", "0,0,0,0"); } themeProps.put("Container.sel#derive", "Container"); themeProps.put("Container.dis#derive", "Container"); themeProps.put("Container.press#derive", "Container"); if(installedTheme == null || !installedTheme.containsKey("Switch.derive")) { themeProps.put("Switch.transparency", "255"); themeProps.put("Switch.bgColor", "9F9E9E"); themeProps.put("Switch.fgColor", "EDEDED"); } if(installedTheme == null || !installedTheme.containsKey("Switch.sel#derive")) { themeProps.put("Switch.sel#transparency", "255"); themeProps.put("Switch.sel#bgColor", "757E84"); themeProps.put("Switch.sel#fgColor", "222C32"); } if(installedTheme == null || !installedTheme.containsKey("OnOffSwitch.derive")) { themeProps.put("OnOffSwitch.transparency", "255"); themeProps.put("OnOffSwitch.bgColor", "222222"); themeProps.put("OnOffSwitch.padding", "0,0,0,0"); themeProps.put("OnOffSwitch.font", lightFont); } if(installedTheme == null || !installedTheme.containsKey("OnOffSwitch.sel#derive")) { themeProps.put("OnOffSwitch.sel#transparency", "255"); themeProps.put("OnOffSwitch.sel#bgColor", "222222"); themeProps.put("OnOffSwitch.sel#padding", "0,0,0,0"); themeProps.put("OnOffSwitch.sel#font", lightFont); } if(installedTheme == null || !installedTheme.containsKey("ContentPane.derive")) { themeProps.put("ContentPane.transparency", "0"); themeProps.put("ContentPane.margin", "0,0,0,0"); themeProps.put("ContentPane.padding", "0,0,0,0"); } themeProps.put("ContentPane.sel#derive", "ContentPane"); if (installedTheme == null || !installedTheme.containsKey("PopupDialog.derive")) { themeProps.put("PopupDialog.derive", "Dialog"); themeProps.put("PopupDialog.border", RoundRectBorder.create(). cornerRadius(2f). shadowOpacity(60).shadowSpread(3.0f)); themeProps.put("PopupDialog.transparency", "255"); themeProps.put("PopupDialog.bgColor", background); themeProps.put("PopupDialog.padding", "4,4,4,4"); themeProps.put("PopupDialog.padUnit", new byte[]{Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS}); } if (installedTheme == null || !installedTheme.containsKey("TooltipDialog.derive")) { themeProps.put("TooltipDialog.derive", "Dialog"); themeProps.put("TooltipDialog.border", RoundRectBorder.create(). cornerRadius(2f)); themeProps.put("TooltipDialog.transparency", "255"); themeProps.put("TooltipDialog.bgColor", "dddddd"); themeProps.put("TooltipDialog.padding", "4,4,4,4"); themeProps.put("TooltipDialog.padUnit", new byte[]{Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS}); } if (installedTheme == null || !installedTheme.containsKey("Tooltip.derive")) { themeProps.put("Tooltip.derive", "Label"); themeProps.put("Tooltip.fgColor", "0"); themeProps.put("Tooltip.align", centerAlign); themeProps.put("TooltipDialog.padding", "2,2,2,2"); themeProps.put("TooltipDialog.padUnit", new byte[]{Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS}); } if(installedTheme == null || !installedTheme.containsKey("DialogContentPane.derive")) { themeProps.put("DialogContentPane.margin", "0,0,0,0"); themeProps.put("DialogContentPane.padding", "0,0,0,0"); themeProps.put("DialogContentPane.transparency", "0"); } if(installedTheme == null || !installedTheme.containsKey("PopupContentPane.derive")) { themeProps.put("PopupContentPane.derive", "DialogContentPane"); } if(installedTheme == null || !installedTheme.containsKey("DialogTitle.derive")) { themeProps.put("DialogTitle.align", centerAlign); } if(installedTheme == null || !installedTheme.containsKey("PopupDialogTitle.derive")) { themeProps.put("PopupDialogTitle.derive", "DialogTitle"); } if(installedTheme == null || !installedTheme.containsKey("Form.derive")) { themeProps.put("Form.padding", "0,0,0,0"); themeProps.put("Form.margin", "0,0,0,0"); } themeProps.put("Form.sel#derive", "Form"); if(installedTheme == null || !installedTheme.containsKey("HorizontalScroll.derive")) { themeProps.put("HorizontalScroll.margin", "0,0,0,0"); themeProps.put("HorizontalScroll.padding", "1,1,1,1"); } if(installedTheme == null || !installedTheme.containsKey("HorizontalScrollThumb.derive")) { themeProps.put("HorizontalScrollThumb.padding", "0,0,0,0"); themeProps.put("HorizontalScrollThumb.bgColor", foreground); themeProps.put("HorizontalScrollThumb.margin", "0,0,0,0"); } if(installedTheme == null || !installedTheme.containsKey("List.derive")) { themeProps.put("List.transparency", "0"); themeProps.put("List.margin", "0,0,0,0"); } themeProps.put("List.sel#derive", "List"); if(installedTheme == null || !installedTheme.containsKey("ListRenderer.derive")) { themeProps.put("ListRenderer.transparency", "0"); } if(installedTheme == null || !installedTheme.containsKey("ListRenderer.sel#derive")) { themeProps.put("ListRenderer.sel#transparency", "100"); } themeProps.put("ListRenderer.dis#derive", "ListRenderer"); if(installedTheme == null || !installedTheme.containsKey("Menu.derive")) { themeProps.put("Menu.padding", "0,0,0,0"); } themeProps.put("Menu.sel#derive", "Menu"); if(installedTheme == null || !installedTheme.containsKey("PopupContentPane.derive")) { themeProps.put("PopupContentPane.transparency", "0"); } if(installedTheme == null || !installedTheme.containsKey("Scroll.derive")) { themeProps.put("Scroll.margin", "0,0,0,0"); int halfMM = Display.getInstance().convertToPixels(10, true) / 20; halfMM = Math.max(1, halfMM); themeProps.put("Scroll.padding", halfMM + "," + halfMM + "," + halfMM + "," + halfMM); } if(installedTheme == null || !installedTheme.containsKey("ScrollThumb.derive")) { themeProps.put("ScrollThumb.padding", "0,0,0,0"); themeProps.put("ScrollThumb.margin", "0,0,0,0"); themeProps.put("ScrollThumb.bgColor", foreground); } if(installedTheme == null || !installedTheme.containsKey("SliderFull.derive")) { themeProps.put("SliderFull.bgColor", foreground); } themeProps.put("SliderFull.sel#derive", "SliderFull"); if(installedTheme == null || !installedTheme.containsKey("SoftButton.derive")) { themeProps.put("SoftButton.transparency", "255"); themeProps.put("SoftButton.margin", "0,0,0,0"); themeProps.put("SoftButton.padding", "0,0,0,0"); } themeProps.put("SoftButton.sel#derive", "SoftButton"); if(installedTheme == null || !installedTheme.containsKey("SoftButtonCenter.derive")) { themeProps.put("SoftButtonCenter.align", centerAlign); themeProps.put("SoftButtonCenter.transparency", "0"); themeProps.put("SoftButtonCenter.derive", "SoftButton"); themeProps.put("SoftButtonCenter.padding", "4,4,4,4"); } themeProps.put("SoftButtonCenter.sel#derive", "SoftButtonCenter"); themeProps.put("SoftButtonCenter.press#derive", "SoftButtonCenter"); themeProps.put("SoftButtonCenter.dis#derive", "SoftButtonCenter"); if(installedTheme == null || !installedTheme.containsKey("SoftButtonLeft.derive")) { themeProps.put("SoftButtonLeft.transparency", "0"); themeProps.put("SoftButtonLeft.derive", "SoftButton"); themeProps.put("SoftButtonLeft.padding", "4,4,4,4"); } themeProps.put("SoftButtonLeft.sel#derive", "SoftButtonLeft"); themeProps.put("SoftButtonLeft.press#derive", "SoftButtonLeft"); themeProps.put("SoftButtonLeft.dis#derive", "SoftButtonLeft"); if(installedTheme == null || !installedTheme.containsKey("SoftButtonRight.derive")) { themeProps.put("SoftButtonRight.align", rightAlign); themeProps.put("SoftButtonRight.transparency", "0"); themeProps.put("SoftButtonRight.derive", "SoftButton"); themeProps.put("SoftButtonRight.padding", "4,4,4,4"); } themeProps.put("SoftButtonRight.sel#derive", "SoftButtonRight"); themeProps.put("SoftButtonRight.press#derive", "SoftButtonRight"); themeProps.put("SoftButtonRight.dis#derive", "SoftButtonRight"); if(installedTheme == null || !installedTheme.containsKey("Spinner.derive")) { themeProps.put("Spinner.border", Border.getDefaultBorder()); } themeProps.put("Spinner.sel#derive", "Spinner"); if(installedTheme == null || !installedTheme.containsKey("SpinnerOverlay.derive")) { themeProps.put("SpinnerOverlay.transparency", "0"); } if(installedTheme == null || !installedTheme.containsKey("Tab.derive")) { themeProps.put("Tab.margin", "1,1,1,1"); } if(installedTheme == null || !installedTheme.containsKey("Tab.sel#derive")) { themeProps.put("Tab.sel#derive", "Tab"); themeProps.put("Tab.sel#border", Border.createLineBorder(1)); } // deprecated so there is no need to referesh this.... themeProps.put("TabbedPane.margin", "0,0,0,0"); themeProps.put("TabbedPane.padding", "0,0,0,0"); themeProps.put("TabbedPane.transparency", "0"); themeProps.put("TabbedPane.sel#margin", "0,0,0,0"); themeProps.put("TabbedPane.sel#padding", "0,0,0,0"); if(installedTheme == null || !installedTheme.containsKey("Table.derive")) { themeProps.put("Table.border", Border.getDefaultBorder()); } themeProps.put("Table.sel#derive", "Table"); if(installedTheme == null || !installedTheme.containsKey("TableCell.derive")) { themeProps.put("TableCell.transparency", "0"); } themeProps.put("TableCell.sel#derive", "TableCell"); if(installedTheme == null || !installedTheme.containsKey("TableHeader.derive")) { themeProps.put("TableHeader.transparency", "0"); } themeProps.put("TableHeader.sel#derive", "TableHeader"); if(installedTheme == null || !installedTheme.containsKey("Tabs.derive")) { themeProps.put("Tabs.bgColor", "a0a0a0"); themeProps.put("Tabs.padding", "0,0,0,0"); } if(installedTheme == null || !installedTheme.containsKey("TabsContainer.derive")) { themeProps.put("TabsContainer.padding", "0,0,0,0"); themeProps.put("TabsContainer.margin", "0,0,0,0"); themeProps.put("TabsContainer.bgColor", "a0a0a0"); } if(installedTheme == null || !installedTheme.containsKey("TextArea.derive")) { themeProps.put("TextArea.border", Border.getDefaultBorder()); } themeProps.put("TextArea.sel#derive", "TextArea"); themeProps.put("TextArea.dis#derive", "TextArea"); if(installedTheme == null || !installedTheme.containsKey("TextField.derive")) { themeProps.put("TextField.border", Border.getDefaultBorder()); } themeProps.put("InvalidEmblem.derive", "Label"); themeProps.put("InvalidEmblem.fgColor", "ff0000"); themeProps.put("InvalidEmblem.transparency", "0"); themeProps.put("TextField.sel#derive", "TextField"); themeProps.put("TextField.dis#derive", "TextField"); if(installedTheme == null || !installedTheme.containsKey("TextFieldInvalid.derive")) { themeProps.put("TextFieldInvalid.derive", "TextField"); themeProps.put("TextFieldInvalid.fgColor", "ff0000"); themeProps.put("TextFieldInvalid.sel#fgColor", "ff0000"); themeProps.put("TextFieldInvalid.sel#fgColor", "ff0000"); themeProps.put("TextFieldInvalid.sel#derive", "TextField"); themeProps.put("TextFieldInvalid.dis#derive", "TextField"); } if(installedTheme == null || !installedTheme.containsKey("TextAreaInvalid.derive")) { themeProps.put("TextAreaInvalid.derive", "TextArea"); themeProps.put("TextAreaInvalid.fgColor", "ff0000"); themeProps.put("TextAreaInvalid.sel#fgColor", "ff0000"); themeProps.put("TextAreaInvalid.sel#fgColor", "ff0000"); themeProps.put("TextAreaInvalid.sel#derive", "TextArea"); themeProps.put("TextAreaInvalid.dis#derive", "TextArea"); } if(installedTheme == null || !installedTheme.containsKey("TextHint.derive")) { themeProps.put("TextHint.transparency", "0"); themeProps.put("TextHint.fgColor", "cccccc"); themeProps.put("TextHint.font", italic); } if(installedTheme == null || !installedTheme.containsKey("Title.derive")) { themeProps.put("Title.margin", "0,0,0,0"); themeProps.put("Title.transparency", "255"); themeProps.put("Title.align", centerAlign); } themeProps.put("Title.sel#derive", "Title"); if(installedTheme == null || !installedTheme.containsKey("TitleArea.derive")) { themeProps.put("TitleArea.transparency", "0"); themeProps.put("TitleArea.margin", "0,0,0,0"); themeProps.put("TitleArea.padding", "0,0,0,0"); } if(installedTheme == null || !installedTheme.containsKey("TouchCommand.derive")) { themeProps.put("TouchCommand.border", Border.getDefaultBorder()); themeProps.put("TouchCommand.padding", "10,10,10,10"); themeProps.put("TouchCommand.margin", "0,0,0,0"); themeProps.put("TouchCommand.align", centerAlign); } if(installedTheme == null || !installedTheme.containsKey("TouchCommand.press#derive")) { themeProps.put("TouchCommand.press#border", Border.getDefaultBorder().createPressedVersion()); themeProps.put("TouchCommand.press#derive", "TouchCommand"); } themeProps.put("TouchCommand.sel#derive", "TouchCommand"); if(installedTheme == null || !installedTheme.containsKey("TouchCommand.dis#derive")) { themeProps.put("TouchCommand.dis#derive", "TouchCommand"); themeProps.put("TouchCommand.dis#fgColor", disabledColor); } if(installedTheme == null || !installedTheme.containsKey("AdsComponent.sel#derive")) { themeProps.put("AdsComponent.sel#border", Border.getDefaultBorder()); themeProps.put("AdsComponent.sel#padding", "2,2,2,2"); themeProps.put("AdsComponent.sel#transparency", "0"); } themeProps.put("AdsComponent#derive", "Container"); themeProps.put("WebBrowser#derive", "Container"); if (installedTheme == null || !installedTheme.containsKey("MapZoomOut.derive")) { themeProps.put("MapZoomOut.derive", "Button"); } themeProps.put("MapZoomOut.sel#derive", "Button.sel"); themeProps.put("MapZoomOut.press#derive", "Button.press"); if (installedTheme == null || !installedTheme.containsKey("MapZoomIn.derive")) { themeProps.put("MapZoomIn.derive", "Button"); } themeProps.put("MapZoomIn.sel#derive", "Button.sel"); themeProps.put("MapZoomIn.press#derive", "Button.press"); if (installedTheme == null || !installedTheme.containsKey("SideCommand.derive")) { themeProps.put("SideCommand.derive", "TouchCommand"); themeProps.put("SideCommand.align", leftAlign); } if (installedTheme == null || !installedTheme.containsKey("SideCommand.sel#.derive")) { themeProps.put("SideCommand.sel#derive", "TouchCommand.sel"); themeProps.put("SideCommand.sel#align", leftAlign); } if (installedTheme == null || !installedTheme.containsKey("SideCommand.press#.derive")) { themeProps.put("SideCommand.press#derive", "TouchCommand.press"); themeProps.put("SideCommand.press#align", leftAlign); } if (installedTheme == null || !installedTheme.containsKey("RightSideCommand.derive")) { themeProps.put("RightSideCommand.derive", "SideCommand"); themeProps.put("RightSideCommand.align", rightAlign); } if (installedTheme == null || !installedTheme.containsKey("RightSideCommand.sel#.derive")) { themeProps.put("RightSideCommand.sel#derive", "SideCommand.sel"); themeProps.put("RightSideCommand.sel#align", rightAlign); } if (installedTheme == null || !installedTheme.containsKey("RightSideCommand.press#.derive")) { themeProps.put("RightSideCommand.press#derive", "SideCommand.press"); themeProps.put("RightSideCommand.press#align", rightAlign); } if(installedTheme == null || !installedTheme.containsKey("SideNavigationPanel.derive")) { themeProps.put("SideNavigationPanel.padding", "0,0,0,0"); themeProps.put("SideNavigationPanel.margin", "0,0,0,0"); themeProps.put("SideNavigationPanel.bgColor", "343434"); themeProps.put("SideNavigationPanel.transparency", "255"); } if(installedTheme == null || !installedTheme.containsKey("RightSideNavigationPanel.derive")) { themeProps.put("RightSideNavigationPanel.derive", "SideNavigationPanel"); } if(installedTheme == null || !installedTheme.containsKey("PullToRefresh.derive")) { themeProps.put("PullToRefresh.padding", "0,0,0,0"); themeProps.put("PullToRefresh.margin", "0,0,0,0"); themeProps.put("PullToRefresh.align", centerAlign); themeProps.put("PullToRefresh.transparency", "0"); themeProps.put("PullToRefresh.fgColor", foreground); } if (installedTheme == null || !installedTheme.containsKey("AutoCompletePopup.derive")) { themeProps.put("AutoCompletePopup.transparency", "255"); themeProps.put("AutoCompletePopup.padding", "0,0,0,0"); themeProps.put("AutoCompletePopup.border", Border.createLineBorder(1)); } if (installedTheme == null || !installedTheme.containsKey("AutoCompletePopup.sel#derive")) { themeProps.put("AutoCompletePopup.sel#transparency", "255"); themeProps.put("AutoCompletePopup.sel#padding", "0,0,0,0"); themeProps.put("AutoCompletePopup.sel#border", Border.createLineBorder(1)); } if (installedTheme == null || !installedTheme.containsKey("AutoCompleteList.derive")) { themeProps.put("AutoCompleteList.margin", "1,1,1,1"); themeProps.put("AutoCompleteList.padding", "0,0,0,0"); } if (installedTheme == null || !installedTheme.containsKey("AutoCompleteList.sel#derive")) { themeProps.put("AutoCompleteList.sel#margin", "1,1,1,1"); themeProps.put("AutoCompleteList.sel#padding", "0,0,0,0"); } if (installedTheme == null || !installedTheme.containsKey("AutoCompleteList.press#derive")) { themeProps.put("AutoCompleteList.press#margin", "1,1,1,1"); themeProps.put("AutoCompleteList.press#padding", "0,0,0,0"); } if (installedTheme == null || !installedTheme.containsKey("CommandList.derive")) { themeProps.put("CommandList.transparency", "255"); themeProps.put("CommandList.border", Border.createLineBorder(1)); } if (installedTheme == null || !installedTheme.containsKey("CommandList.sel#derive")) { themeProps.put("CommandList.sel#transparency", "255"); themeProps.put("CommandList.sel#border", Border.createLineBorder(1)); } if (installedTheme == null || !installedTheme.containsKey("Toolbar.derive")) { themeProps.put("Toolbar.derive", "TitleArea"); } if(installedTheme == null || !installedTheme.containsKey("FloatingActionButton.derive")) { themeProps.put("FloatingActionButton.fgColor", "ffffff"); themeProps.put("FloatingActionButton.bgColor", "d32f2f"); themeProps.put("FloatingActionButton.transparency", "0"); themeProps.put("FloatingActionButton.marUnit", new byte[]{Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS}); themeProps.put("FloatingActionButton.margin", "0,2,1,2"); } if(installedTheme == null || !installedTheme.containsKey("FloatingActionButton.press#derive")) { themeProps.put("FloatingActionButton.press#fgColor", "ffffff"); themeProps.put("FloatingActionButton.press#bgColor", "b71c1c"); themeProps.put("FloatingActionButton.sel#transparency", "0"); themeProps.put("FloatingActionButton.press#marUnit", new byte[]{Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS}); themeProps.put("FloatingActionButton.press#margin", "0,2,1,2"); } if(installedTheme == null || !installedTheme.containsKey("FloatingActionButton.sel#derive")) { themeProps.put("FloatingActionButton.sel#fgColor", "ffffff"); themeProps.put("FloatingActionButton.sel#transparency", "0"); themeProps.put("FloatingActionButton.sel#bgColor", "b71c1c"); themeProps.put("FloatingActionButton.sel#marUnit", new byte[]{Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS}); themeProps.put("FloatingActionButton.sel#margin", "0,2,1,2"); } if(installedTheme == null || !installedTheme.containsKey("RefreshLabel.derive")) { themeProps.put("RefreshLabel.fgColor", "0"); themeProps.put("RefreshLabel.bgColor", "ffffff"); themeProps.put("RefreshLabel.transparency", "0"); themeProps.put("RefreshLabel.marUnit", new byte[]{Style.UNIT_TYPE_PIXELS, Style.UNIT_TYPE_PIXELS, Style.UNIT_TYPE_PIXELS, Style.UNIT_TYPE_PIXELS}); themeProps.put("RefreshLabel.padUnit", new byte[]{Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS}); themeProps.put("RefreshLabel.margin", "1,1,1,1"); themeProps.put("RefreshLabel.padding", "2,3,2,3"); } if(installedTheme == null || !installedTheme.containsKey("Badge.derive")) { themeProps.put("Badge.fgColor", "ffffff"); themeProps.put("Badge.bgColor", "d32f2f"); themeProps.put("Badge.press#fgColor", "ffffff"); themeProps.put("Badge.press#bgColor", "b71c1c"); themeProps.put("Badge.sel#fgColor", "ffffff"); themeProps.put("Badge.sel#bgColor", "b71c1c"); themeProps.put("Badge#padUnit", new byte[]{Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS}); themeProps.put("Badge#padding", "0,0,0,0"); themeProps.put("Badge.sel#padUnit", new byte[]{Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS}); themeProps.put("Badge.sel#padding", "0,0,0,0"); themeProps.put("Badge.press#padUnit", new byte[]{Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS}); themeProps.put("Badge.press#padding", "0,0,0,0"); if(Font.isNativeFontSchemeSupported()) { Font fnt = lightFont.derive(Display.getInstance().convertToPixels(1.5f), Font.STYLE_PLAIN); themeProps.put("Badge.font", fnt); themeProps.put("Badge.sel#font", fnt); themeProps.put("Badge.press#font", fnt); } themeProps.put("Badge.align", centerAlign); themeProps.put("Badge.sel#align", centerAlign); themeProps.put("Badge.press#align", centerAlign); } if(installedTheme == null || !installedTheme.containsKey("FloatingActionText.derive")) { themeProps.put("FloatingActionText.bgColor", background); themeProps.put("FloatingActionText.fgColor", "a0a0a0"); themeProps.put("FloatingActionText.align", rightAlign); } if(installedTheme == null || !installedTheme.containsKey("ErrorLabel.derive")) { themeProps.put("ErrorLabel.derive", "FloatingHint"); themeProps.put("ErrorLabel.sel#derive", "FloatingHint"); themeProps.put("ErrorLabel.press#derive", "FloatingHint"); themeProps.put("ErrorLabel.fgColor", "ff1744"); themeProps.put("ErrorLabel.sel#fgColor", "ff1744"); themeProps.put("ErrorLabel.press#fgColor", "ff1744"); } if(installedTheme == null || !installedTheme.containsKey("InputComponentAction.derive")) { themeProps.put("InputComponentAction.derive", "FloatingHint"); themeProps.put("InputComponentAction.font", Font.createTrueTypeFont(Font.NATIVE_MAIN_LIGHT, 3f)); } if(installedTheme == null || !installedTheme.containsKey("DescriptionLabel.derive")) { themeProps.put("DescriptionLabel.derive", "FloatingHint"); themeProps.put("DescriptionLabel.sel#derive", "FloatingHint"); themeProps.put("DescriptionLabel.press#derive", "FloatingHint"); themeProps.put("DescriptionLabel.fgColor", "666666"); themeProps.put("DescriptionLabel.sel#fgColor", "666666"); themeProps.put("DescriptionLabel.press#fgColor", "666666"); } if(installedTheme == null || !installedTheme.containsKey("TextComponent.derive")) { themeProps.put("TextComponent.derive", "Container"); } if (installedTheme == null || !installedTheme.containsKey("Spinner3DRow.derive")) { // For the rows of the Spinner3D widget themeProps.put("Spinner3DRow.derive", "Label"); themeProps.put("Spinner3DRow.sel#derive", "Label"); themeProps.put("Spinner3DRow.fgColor", "878A93"); themeProps.put("Spinner3DRow.transparency", "0"); themeProps.put("Spinner3DRow.sel#fgColor", "2A2B2F"); themeProps.put("Spinner3DRow.border", Border.createEmpty()); themeProps.put("Spinner3DRow.align", centerAlign); themeProps.put("Spinner3DRow.sel#align", centerAlign); themeProps.put("Spinner3DRow.padding", "1.5,1.5,1,1"); themeProps.put("Spinner3DRow.sel#padding", "1.5,1.5,1,1"); themeProps.put("Spinner3DRow.padUnit", new byte[]{Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS}); themeProps.put("Spinner3DRow.sel#padUnit", new byte[]{Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS}); themeProps.put("Spinner3DRow.font", Font.createTrueTypeFont(Font.NATIVE_MAIN_LIGHT, 2.8f)); themeProps.put("Spinner3DRow.sel#font", Font.createTrueTypeFont(Font.NATIVE_MAIN_LIGHT, 2.8f)); } if (installedTheme == null || !installedTheme.containsKey("Spinner3DOverlay.bgColor")) { themeProps.put("Spinner3DOverlay.transparency", "255"); themeProps.put("Spinner3DOverlay.bgColor", "efeff4"); themeProps.put("Spinner3DOverlay.fgColor", "abb8b7"); } if (installedTheme == null || !installedTheme.containsKey("PickerDialog.border")) { // For the interaction dialog when showing a Picker in lightweight mode themeProps.put("PickerDialog.padding", "0,0,0,0"); themeProps.put("PickerDialog.border", Border.createEmpty()); } if (installedTheme == null || !installedTheme.containsKey("PickerDialogTablet.derive")) { themeProps.put("PickerDialogTablet.derive", "Dialog"); } if (installedTheme == null || !installedTheme.containsKey("PickerDialogContent.bgColor")) { // For the content pane of the interaction dialog when showing a Picker in lightweight mode themeProps.put("PickerDialogContent.padding", "0,0,0,0"); themeProps.put("PickerDialogContent.margin", "0,0,0,0"); themeProps.put("PickerDialogContent.border", Border.createEmpty()); themeProps.put("PickerDialogContent.bgColor", "D1D4DD"); themeProps.put("PickerDialogContent.transparency", "255"); } if (installedTheme == null || !installedTheme.containsKey("PicketDialogContentTablet.derive")) { themeProps.put("PickerDialogContentTablet.derive", "PopupContentPane"); } if (installedTheme == null || !installedTheme.containsKey("PickerButtonBarTablet")) { if (installedTheme != null && installedTheme.containsKey("PickerButtonBarTabletNative")) { themeProps.put("PickerButtonBarTablet.derive", "PickerButtonBarTabletNative"); } else { themeProps.put("PickerButtonBarTablet.derive", "Container"); } } if (installedTheme == null || !installedTheme.containsKey("PickerButton")) { // For the buttons of the picker in lightweight mode (the Cancel and Done buttons) themeProps.put("PickerButton.derive", "Button"); themeProps.put("PickerButton.sel#derive", "Button.sel"); themeProps.put("PickerButton.press#derive", "Button.pres"); } if (installedTheme == null || !installedTheme.containsKey("Picker.derive")) { themeProps.put("Picker.derive", "TextField"); themeProps.put("Picker.sel#derive", "TextField.sel"); themeProps.put("Picker.press#derive", "TextField.press"); themeProps.put("Picker.dis#derive", "TextField.dis"); themeProps.put("Picker.sel#border", Border.createLineBorder(1, 0x206afb)); } } /** * Allows manual theme loading from a hashtable of key/value pairs * * @param themeProps the properties of the given theme */ public void setThemeProps(Hashtable themeProps) { if (accessible) { setThemePropsImpl(themeProps); } wasThemeInstalled = true; } /** * Adds the given theme properties on top of the existing properties without * clearing the existing theme first * * @param themeProps the properties of the given theme */ public void addThemeProps(Hashtable themeProps) { if (accessible) { buildTheme(themeProps); styles.clear(); selectedStyles.clear(); imageCache.clear(); current.refreshTheme(false); } } /** * Returns a theme constant defined in the resource editor * * @param constantName the name of the constant * @param def default value * @return the value of the constant or the default if the constant isn't in the theme */ public int getThemeConstant(String constantName, int def) { String v = (String) themeConstants.get(constantName); if (v != null) { try { return Integer.parseInt(v); } catch(NumberFormatException err) { Log.e(err); } } return def; } /** * Returns a theme constant defined in the resource editor * * @param constantName the name of the constant * @param def default value * @return the value of the constant or the default if the constant isn't in the theme */ public String getThemeConstant(String constantName, String def) { String v = (String) themeConstants.get(constantName); if (v != null) { return v; } return def; } /** * Returns a theme constant defined in the resource editor as a boolean value * * @param constantName the name of the constant * @param def default value * @return the value of the constant or the default if the constant isn't in the theme */ public boolean isThemeConstant(String constantName, boolean def) { String c = getThemeConstant(constantName, null); if (c == null) { return def; } return c.equalsIgnoreCase("true") || c.equals("1"); } /** * Returns a theme constant defined in the resource editor as a boolean value or null if the constant isn't defined * * @param constantName the name of the constant * @return the value of the constant or null if the constant isn't in the theme */ public Boolean isThemeConstant(String constantName) { String c = getThemeConstant(constantName, null); if (c == null) { return null; } if(c.equalsIgnoreCase("true") || c.equals("1")) { return Boolean.TRUE; } return Boolean.FALSE; } /** * Returns a theme constant defined in the resource editor * * @param constantName the name of the constant * @return the image if defined */ public Image getThemeImageConstant(String constantName) { return (Image) themeConstants.get(constantName); } /** * Returns a theme mask constant * * @param constantName the name of the constant * @return the mask if defined */ public Object getThemeMaskConstant(String constantName) { Object o = themeConstants.get(constantName + "Mask"); if(o != null) { return o; } Image i = (Image) themeConstants.get(constantName); if(i == null) { return null; } o = i.createMask(); themeConstants.put(constantName + "Mask", o); return o; } void setThemePropsImpl(Hashtable themeProps) { resetThemeProps(themeProps); styles.clear(); themeConstants.clear(); selectedStyles.clear(); imageCache.clear(); if (themelisteners != null) { themelisteners.fireActionEvent(new ActionEvent(themeProps,ActionEvent.Type.Theme)); } buildTheme(themeProps); current.refreshTheme(true); } private void buildTheme(Hashtable themeProps) { String con = (String)themeProps.get("@includeNativeBool"); if(con != null && con.equalsIgnoreCase("true") && Display.getInstance().hasNativeTheme()) { boolean a = accessible; accessible = true; Display.getInstance().installNativeTheme(); accessible = a; } Enumeration e = themeProps.keys(); while (e.hasMoreElements()) { String key = (String) e.nextElement(); // this is a constant not a theme entry if (key.startsWith("@")) { themeConstants.put(key.substring(1, key.length()), themeProps.get(key)); continue; } this.themeProps.put(key, themeProps.get(key)); } if (!this.themeProps.containsKey("PickerButtonBar.derive")) { // For the button bar (with Cancel and Done) of the Picker interaction dialog in lightweight mode if (this.themeProps.containsKey("PickerButtonBarNative.derive")) { this.themeProps.put("PickerButtonBar.derive", "PickerButtonBarNative"); } else { this.themeProps.put("PickerButtonBar.margin", "0,0,0,0"); this.themeProps.put("PickerButtonBar.border", Border.createCompoundBorder(Border.createLineBorder(1, ColorUtil.rgb(148, 150, 151)), Border.createEmpty(), Border.createEmpty(), Border.createEmpty())); this.themeProps.put("PickerButtonBar.bgColor", "F0F1F3"); this.themeProps.put("PickerButtonBar.transparency", "255"); } } if (!this.themeProps.containsKey("PickerButtonTablet.derive")) { // For the buttons of the picker in lightweight mode (the Cancel and Done buttons) if (this.themeProps.containsKey("PickerButtonTabletNative.derive")) { this.themeProps.put("PickerButtonTablet.derive", "PickerButtonTabletNative"); this.themeProps.put("PickerButtonTablet.sel#derive", "PickerButtonTabletNative.sel"); this.themeProps.put("PickerButtonTablet.press#derive", "PickerButtonTabletNative.press"); } else { this.themeProps.put("PickerButtonTablet.derive", "Button"); this.themeProps.put("PickerButtonTablet.sel#derive", "Button"); this.themeProps.put("PickerButtonTablet.press#derive", "Button"); } } // necessary to clear up the style so we don't get resedue from the previous UI defaultStyle = new Style(); //create's the default style defaultStyle = createStyle("", "", false); defaultSelectedStyle = new Style(defaultStyle); defaultSelectedStyle = createStyle("", "sel#", true); String overlayThemes = (String)themeProps.get("@OverlayThemes"); if (overlayThemes != null) { java.util.List<String> overlayThemesArr = StringUtil.tokenize(overlayThemes, ','); for (String th : overlayThemesArr) { th = th.trim(); if (th.length() == 0) { continue; } try { Resources res = Resources.openLayered("/"+th); boolean a = accessible; accessible = true; addThemeProps(res.getTheme(res.getThemeResourceNames()[0])); accessible = a; } catch (Exception ex) { System.err.println("Failed to load overlay theme file specified by @overlayThemes theme constant: "+th); Log.e(ex); } } } } // Cache used to keep track of parsed styles. private Map<String,String> parseCache; private Map<String,String> parseCache() { if (parseCache == null) { parseCache = new HashMap<String,String>(); } return parseCache; } private String fromFloatArray(float[] arr) { StringBuilder sb = new StringBuilder(); int len = arr.length; boolean first=true; for (int i=0; i<len; i++) { if (first) first = false; else sb.append(","); sb.append(arr[i]); } return sb.toString(); } private String fromByteArray(byte[] arr) { StringBuilder sb = new StringBuilder(); int len = arr.length; boolean first=true; for (int i=0; i<len; i++) { if (first) first = false; else sb.append(","); sb.append(arr[i]); } return sb.toString(); } /** * Creates a style by providing style strings in a specific format. This method allows for the use of inline styles * to override the styles in {@link com.codename1.ui.Component} * @param theme Theme used to retrieve images referenced in the style strings. * @param id The style ID (UIID) to use to cache the style inside the theme. * @param prefix Prefix to use for styles. Corresponds to the {@literal prefix} argument in {@link #getComponentStyleImpl(java.lang.String, boolean, java.lang.String) * @param baseStyle The style class from which this new style should derive. * @param selected True if this is for a selected style. * @param styleString Array of style strings to be parsed. The format is {@literal key1:value1; key2:value2; etc...}. While this looks similar to CSS, it is important to note that it is NOT * CSS. The keys and values correspond to the properties of {@link com.codename1.ui.plaf.Style} and their associated values. * @return A style object representing the styles that were provided in the styleString. * * <h3>Example Usage</h3> * * {@code * Style s = parseStyle(theme, "Button[MyCustomButton]", "", "Button", false, * "fgColor:ff0000; font:18mm; border: 1px solid ff0000; bgType:none; padding: 3mm; margin: 1mm"); * * // Create a 9-piece image border on the fly: * Style s = parseStyle(theme, "Button[MyCustomButton]", "", "Button", false, * "border:splicedImage /notes.png 0.3 0.4 0.3 0.4"); * // This splices the image found at /notes.png into 9 pieces. Splice insets are specified by the 4 floating point values * // at the end of the border directive: [top] [right] [bottom] [left]. * } */ Style parseStyle(Resources theme, String id, String prefix, String baseStyle, boolean selected, String... styleString) { String cacheKey = selected ? id + ".sel" : id + "." + prefix; String originalId = id; if (id == null || id.length() == 0) { //if no id return the default style id = ""; } else { id = id + "."; } if (Arrays.toString(styleString).equals(parseCache().get(cacheKey)) && ((selected && selectedStyles.containsKey(id)) || (!selected && this.styles.containsKey(id)))) { return getComponentStyleImpl(originalId, selected, prefix); } parseCache().put(cacheKey, Arrays.toString(styleString)); Style base = baseStyle != null ? getComponentStyleImpl(baseStyle, selected, prefix) : null; Map<String,String> styles = new HashMap<String,String>(); for (String str : styleString) { StyleParser.parseString(styles, str); } StyleInfo styleInfo = new StyleInfo(styles); if (prefix != null && prefix.length() > 0) { id += prefix; } if (themeProps == null) { resetThemeProps(null); } if (baseStyle != null) { themeProps.put(id+"derive", baseStyle); } else { themeProps.remove(id+"derive"); } String val = null; Integer bgColor = styleInfo.getBgColor(); if (bgColor != null) { themeProps.put(id + Style.BG_COLOR, Integer.toHexString(bgColor)); } else { themeProps.remove(id + Style.BG_COLOR); } Integer fgColor = styleInfo.getFgColor(); if (fgColor != null) { themeProps.put(id + Style.FG_COLOR, Integer.toHexString(fgColor)); } else { themeProps.remove(id + Style.FG_COLOR); } BorderInfo border = styleInfo.getBorder(); if (border != null) { themeProps.put(id + Style.BORDER, border.createBorder(theme)); } else { themeProps.remove(id + Style.BORDER); } Integer bgType = styleInfo.getBgType(); if (bgType != null) { themeProps.put(id + Style.BACKGROUND_TYPE, bgType.byteValue()); } else { themeProps.remove(id + Style.BACKGROUND_TYPE); } ImageInfo bgImage = styleInfo.getBgImage(); if (bgImage != null) { themeProps.put(id + Style.BG_IMAGE, bgImage.getImage(theme)); } else { themeProps.remove(id + Style.BG_IMAGE); } MarginInfo margin = styleInfo.getMargin(); if (margin != null) { float[] marginArr = margin.createMargin(base); themeProps.put(id + Style.MARGIN, marginArr[Component.TOP]+","+marginArr[Component.BOTTOM]+","+marginArr[Component.LEFT]+","+marginArr[Component.RIGHT]); byte[] unitArr = margin.createMarginUnit(base); themeProps.put(id + Style.MARGIN_UNIT, new byte[]{unitArr[Component.TOP], unitArr[Component.BOTTOM], unitArr[Component.LEFT], unitArr[Component.RIGHT]}); } else { themeProps.remove(id + Style.MARGIN); themeProps.remove(id + Style.MARGIN_UNIT); }