/* * � Copyright IBM Corp. 2011 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. */ package com.ibm.xsp.extlib.designer.common.properties; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import com.ibm.commons.extension.ExtensionManager; import com.ibm.commons.iloader.node.lookups.api.AbstractLookup; import com.ibm.commons.iloader.node.lookups.api.ILookup; import com.ibm.commons.iloader.node.lookups.api.LookupListener; import com.ibm.commons.util.StringUtil; import com.ibm.designer.domino.ide.resources.extensions.DesignerProject; import com.ibm.designer.domino.ide.resources.extensions.util.DesignerDELookup; import com.ibm.xsp.stylekit.StyleKitFactory; import com.ibm.xsp.stylekit.StyleKitListFactory; /** * @author mleland * */ public class AppThemeLookup extends AbstractLookup implements LookupListener { // Hardcoded Theme Labels and Codes public final static String[] theme_Standard_Ids = {"webstandard", "oneui", "oneuiv2", "oneuiv2.1", "oneuiv3.0.2"}; // $NON-NLS-1$ $NON-NLS-2$ $NON-NLS-3$ $NON-NLS-4$ $NON-NLS-5$ public final static String[] theme_Standard_Labels = {"webstandard", "OneUI", "OneUI V2", "OneUI V2.1", "OneUI V3.0.2"}; // $NLX-AppThemeLookup.webstandard_sys-1$ $NLX-AppThemeLookup.OneUI.1_sys-2$ $NLX-AppThemeLookup.OneUIV2_sys-3$ $NLX-AppThemeLookup.OneUIV21_sys.1-4$ $NLX-AppThemeLookup.OneUIV302_sys-5$ public final static String[] theme_Mobile_Ids = {"oneui_idx_v1.3"}; // $NON-NLS-1$ public final static String[] theme_Mobile_Labels = {"OneUI IDX V1.3"}; // $NLX-AppThemeLookup.OneUIIDXV13-1$ public final static String[] theme_IPhone_Ids = {"oneui_idx_v1.3", "iphone"}; // $NON-NLS-1$ $NON-NLS-2$ public final static String[] theme_IPhone_Labels = {"OneUI IDX V1.3", "iPhone"}; // $NLX-AppThemeLookup.OneUIIDXV13-1$ $NLX-AppThemeLookup.iPhone-2$ public final static String[] theme_Android_Ids = {"oneui_idx_v1.3", "android"}; // $NON-NLS-1$ $NON-NLS-2$ public final static String[] theme_Android_Labels = {"OneUI IDX V1.3", "Android"}; // $NLX-AppThemeLookup.OneUIIDXV13-1$ $NLX-AppThemeLookup.Android-2$ // StyleKitList Factories to suppress private final static String[] SUPPRESS_FACTORIES = {"com.ibm.xsp.extlib.oneui.themes.OneUIStyleKitFactory", // $NON-NLS-1$ "com.ibm.xsp.extlib.mobile.themes.MobileStyleKitFactory", // $NON-NLS-1$ "com.ibm.xsp.theme.oneui_idx.ThemeStyleKitFactory", // $NON-NLS-1$ "com.ibm.xsp.theme.oneuiv302.ThemeStyleKitFactory"}; // $NON-NLS-1$ // Extension sometimes used with themes private final static String THEME_EXT = ".theme"; // $NON-NLS-1$ // Private Fields private final String _defCode; private final String _defLabel; private final DesignerDELookup _themeLookup; private final String[] _hardCodedLabels; private final String[] _hardCodedIds; private List<Theme> _themeList; /* * Theme Sources */ private enum AppThemeSource { THEME_SRC_HARDCODED, THEME_SRC_APPLICATION, THEME_SRC_CONTRIBUTED }; /* * Utilty Class for representing a theme */ private class Theme { private String _label; private final String _id; private final AppThemeSource _src; /* * Contructor */ public Theme(final String label, final String id, final AppThemeSource src) { _id = id; _src = src; if (src == AppThemeSource.THEME_SRC_APPLICATION) { _label = StringUtil.format("{0} (Application)", label); // $NLX-AppThemeLookup.0Application-1$ } else { _label = label; } } /* * Gets the display label */ public String getLabel() { return _label != null ? _label : _id; } /* * Gets the ID */ public String getId() { return _id; } /* * Gets the theme source */ public AppThemeSource getSrc() { return _src; } /* * Forces a theme label */ public void setLabel(String newLabel) { _label = newLabel; } } public AppThemeLookup(final DesignerProject prj, final String defCode, final String defLabel, final String[] hardCodedIds, final String[] hardCodedLabels) { _defCode = defCode; _defLabel = defLabel; _hardCodedIds = hardCodedIds; _hardCodedLabels = hardCodedLabels; // Create the theme list _themeList = new ArrayList<Theme>(); // Get the application theme lookup _themeLookup = DesignerDELookup.getThemesLookup(prj); _themeLookup.addLookupListener(this); // Now load the themes loadThemes(); } /* * Loads all the themes from scratch */ private void loadThemes() { _themeList.clear(); // Add the application themes loadApplicationThemes(); // Add contributed themes loadContributedThemes(); // Add the hard-coded themes loadHardCodedThemes(); // Handle duplicate labels fixDuplicateLabels(); // Sort - must do this last sortThemes(); } /* * Loads Application themes */ private void loadApplicationThemes() { // Add in the application themes for (int i=0; i < _themeLookup.size(); i++) { addTheme(new Theme(_themeLookup.getLabel(i), _themeLookup.getLabel(i).concat(THEME_EXT), AppThemeSource.THEME_SRC_APPLICATION)); } } /* * Loads themes contributed through the extension point */ private void loadContributedThemes() { // Get the styleKitFactories List<StyleKitFactory> styleKitFactories = ExtensionManager.findServices( null, this.getClass().getClassLoader(), StyleKitFactory.STYLEKIT_FACTORY_SERVICE, StyleKitFactory.class); // Remove suppressed factories Iterator<StyleKitFactory> iterator = styleKitFactories.iterator(); while (iterator.hasNext()) { String factoryName = iterator.next().getClass().getCanonicalName(); for (String suppress: SUPPRESS_FACTORIES) { if (StringUtil.equalsIgnoreCase(suppress, factoryName)) { iterator.remove(); break; } } } // Look for instances of StyleKitListFactory for (StyleKitFactory styleKitFactory : styleKitFactories) { if( styleKitFactory instanceof StyleKitListFactory ){ StyleKitListFactory listFactory = (StyleKitListFactory) styleKitFactory; String[] themeIds = listFactory.getThemeIds(); if (themeIds != null) { for (String themeId:themeIds) { addTheme(new Theme(themeId, themeId, AppThemeSource.THEME_SRC_CONTRIBUTED)); } } } } } /* * Loads the hard-coded themes */ private void loadHardCodedThemes() { // Add the hardcoded themes for (int i=0; i < _hardCodedLabels.length; i++) { addTheme(new Theme(_hardCodedLabels[i], _hardCodedIds[i], AppThemeSource.THEME_SRC_HARDCODED)); } } /* * Adds a theme to the theme list whilst enforcing theme precedence * Returns true if theme was added */ private boolean addTheme(final Theme theme) { // Assume success boolean added = true; // Check for an existing theme with this ID Theme existingTheme = getThemeFromId(theme.getId()); if (existingTheme == null) { // Not on list already - add it _themeList.add(theme); } else { // There's an existing theme with this ID on the list switch (theme.getSrc()) { case THEME_SRC_APPLICATION: // Application themes trump all others _themeList.remove(existingTheme); _themeList.add(theme); break; case THEME_SRC_CONTRIBUTED: if (existingTheme.getSrc() == AppThemeSource.THEME_SRC_HARDCODED) { // Contributed themes trump hard-coded ones _themeList.remove(existingTheme); _themeList.add(theme); } else if (existingTheme.getSrc() == AppThemeSource.THEME_SRC_CONTRIBUTED) { // Multiple contributed themes with this ID - use the ID as the label existingTheme.setLabel(null); added = false; } else { added = false; } break; case THEME_SRC_HARDCODED: // Hardcoded themes do not trump any others added = false; break; } } return added; } /* * Gets a theme from the list using its ID */ private Theme getThemeFromId(final String Id) { String compareId = removeThemeIdExtension(Id); for (Theme theme:_themeList) { if (StringUtil.equalsIgnoreCase(compareId, removeThemeIdExtension(theme.getId()))) { return theme; } } return null; } /* * Removes the ".theme" extension from an ID */ private String removeThemeIdExtension(final String Id) { if (StringUtil.endsWithIgnoreCase(Id, THEME_EXT)) { return Id.substring(0, Id.length() - THEME_EXT.length()); } return Id; } /* * Sorts the theme list alphabetically */ private void sortThemes() { Collections.sort(_themeList, new Comparator<Theme>() { @Override public int compare(Theme t1, Theme t2) { return StringUtil.compareToIgnoreCase(t1.getLabel(), t2.getLabel()); } }); } /* * Fixes any duplicate labels on the theme list */ private void fixDuplicateLabels() { List<Theme> newList = new ArrayList<Theme>(); // Loop until we've removed all items from the list while (_themeList.size() > 0) { // Remove the head of the list as the target Theme theme = _themeList.remove(0); // Iterate looking for duplicate labels boolean duplicates = false; Iterator<Theme> iterator = _themeList.iterator(); while (iterator.hasNext()) { Theme listTheme = iterator.next(); if (StringUtil.equalsIgnoreCase(listTheme.getLabel(), theme.getLabel())) { // Found a dubplicate label - remove from existing list iterator.remove(); // Include the ID in the new label and add to the new list listTheme.setLabel(StringUtil.format("{0} [{1}]", listTheme.getLabel(), listTheme.getId())); //$NLX-AppThemeLookup.ThemeLabelFormat-1$ newList.add(listTheme); // Record the fact we've found a duplicate duplicates = true; } } if (duplicates) { // Duplicate(s) were found - change the label of the target theme.setLabel(StringUtil.format("{0} [{1}]", theme.getLabel(), theme.getId())); //$NLX-AppThemeLookup.ThemeLabelFormat-1$ } // Add the target to the new list newList.add(theme); } // Swap in the new list _themeList = newList; } /* * Removes the listener */ public void dispose() { _themeLookup.removeLookupListener(this); } /* * Returns the size of the lookup */ @Override public int size() { // +1 for the default theme return (_themeList.size() + 1); } /* * Returns the ID for a chosen index */ @Override public String getCode(final int index) { if (index == 0) { return _defCode; } if ((index > 0) && (index <= _themeList.size())) { return _themeList.get(index-1).getId(); } return ""; } /* * Returns the label for a chosen index */ @Override public String getLabel(final int index) { if (index == 0) { return _defLabel; } if ((index > 0) && (index <= _themeList.size())) { return _themeList.get(index-1).getLabel(); } return ""; } /* * Comparison function */ @Override public boolean equals(final Object obj) { if(obj instanceof AppThemeLookup) { if(((AppThemeLookup)obj).size() != this.size()) { return false; } for(int i = 0; i < size(); i++) { if(!StringUtil.equals(getCode(i), ((AppThemeLookup)obj).getCode(i))) { return false; } if(!StringUtil.equals(getLabel(i), ((AppThemeLookup)obj).getLabel(i))) { return false; } } return true; } return super.equals(obj); } /* * Reloads everything */ @Override public void lookupChanged(final ILookup lookup) { loadThemes(); notifyLookupChanged(); } }