1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.eclipse.org/org/documents/epl-v10.php 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.ide.eclipse.adt.internal.editors.layout.configuration; 17 18 import com.android.annotations.NonNull; 19 import com.android.annotations.Nullable; 20 import com.android.ide.common.resources.LocaleManager; 21 import com.android.ide.common.resources.configuration.LanguageQualifier; 22 import com.android.ide.common.resources.configuration.RegionQualifier; 23 import com.android.ide.eclipse.adt.internal.editors.IconFactory; 24 import com.google.common.base.Splitter; 25 import com.google.common.collect.Maps; 26 27 import org.eclipse.swt.graphics.Image; 28 import org.eclipse.wb.internal.core.DesignerPlugin; 29 30 import java.util.Locale; 31 import java.util.Map; 32 33 /** 34 * The {@linkplain FlagManager} provides access to flags for regions known 35 * to {@link LocaleManager}. It also contains some locale related display 36 * functions. 37 * <p> 38 * All the flag images came from the WindowBuilder subversion repository 39 * http://dev.eclipse.org/svnroot/tools/org.eclipse.windowbuilder/trunk (and in 40 * particular, a snapshot of revision 424). However, it appears that the icons 41 * are from http://www.famfamfam.com/lab/icons/flags/ which states that "these 42 * flag icons are available for free use for any purpose with no requirement for 43 * attribution." Adding the URL here such that we can check back occasionally 44 * and see if there are corrections or updates. Also note that the flag names 45 * are in ISO 3166-1 alpha-2 country codes. 46 */ 47 public class FlagManager { 48 private static final FlagManager sInstance = new FlagManager(); 49 50 /** 51 * Returns the {@linkplain FlagManager} singleton 52 * 53 * @return the {@linkplain FlagManager} singleton, never null 54 */ 55 @NonNull 56 public static FlagManager get() { 57 return sInstance; 58 } 59 60 /** Use the {@link #get()} factory method */ 61 private FlagManager() { 62 } 63 64 /** Map from region to flag icon */ 65 private Map<String, Image> mImageMap = Maps.newHashMap(); 66 67 /** 68 * Returns the empty flag icon used to indicate an unknown country 69 * 70 * @return the globe icon used to indicate an unknown country 71 */ 72 public static Image getEmptyIcon() { 73 return DesignerPlugin.getImage("nls/flags/flag_empty.png"); //$NON-NLS-1$ 74 } 75 76 /** 77 * Returns the globe icon used to indicate "any" language 78 * 79 * @return the globe icon used to indicate "any" language 80 */ 81 public static Image getGlobeIcon() { 82 return IconFactory.getInstance().getIcon("globe"); //$NON-NLS-1$ 83 } 84 85 /** 86 * Returns the flag for the given language and region. 87 * 88 * @param language the language, or null (if null, region must not be null), 89 * the 2 letter language code (ISO 639-1), in lower case 90 * @param region the region, or null (if null, language must not be null), 91 * the 2 letter region code (ISO 3166-1 alpha-2), in upper case 92 * @return a suitable flag icon, or null 93 */ 94 @Nullable 95 public Image getFlag(@Nullable String language, @Nullable String region) { 96 assert region != null || language != null; 97 if (region == null || region.isEmpty()) { 98 // Look up the region for a given language 99 assert language != null; 100 101 // Prefer the local registration of the current locale; even if 102 // for example the default locale for English is the US, if the current 103 // default locale is English, then use its associated country, which could 104 // for example be Australia. 105 Locale locale = Locale.getDefault(); 106 if (language.equals(locale.getLanguage())) { 107 Image flag = getFlag(locale.getCountry()); 108 if (flag != null) { 109 return flag; 110 } 111 } 112 113 // Special cases where we have a dedicated flag available: 114 if (language.equals("ca")) { //$NON-NLS-1$ 115 region = "catalonia"; //$NON-NLS-1$ 116 } else if (language.equals("gd")) { //$NON-NLS-1$ 117 region = "scotland"; //$NON-NLS-1$ 118 } else if (language.equals("cy")) { //$NON-NLS-1$ 119 region = "wales"; //$NON-NLS-1$ 120 } else { 121 // Attempt to look up the country from the language 122 region = LocaleManager.getLanguageRegion(language); 123 } 124 } 125 126 if (region == null || region.isEmpty()) { 127 // No country specified, and the language is for a country we 128 // don't have a flag for 129 return null; 130 } 131 132 return getIcon(region); 133 } 134 135 /** 136 * Returns the flag for the given language and region. 137 * 138 * @param language the language qualifier, or null (if null, region must not be null), 139 * @param region the region, or null (if null, language must not be null), 140 * @return a suitable flag icon, or null 141 */ 142 public Image getFlag(LanguageQualifier language, RegionQualifier region) { 143 String languageCode = language != null ? language.getValue() : null; 144 String regionCode = region != null ? region.getValue() : null; 145 if (LanguageQualifier.FAKE_LANG_VALUE.equals(languageCode)) { 146 languageCode = null; 147 } 148 if (RegionQualifier.FAKE_REGION_VALUE.equals(regionCode)) { 149 regionCode = null; 150 } 151 return getFlag(languageCode, regionCode); 152 } 153 154 /** 155 * Returns a flag for a given resource folder name (such as 156 * {@code values-en-rUS}), or null 157 * 158 * @param folder the folder name 159 * @return a corresponding flag icon, or null if none was found 160 */ 161 @Nullable 162 public Image getFlagForFolderName(@NonNull String folder) { 163 RegionQualifier region = null; 164 LanguageQualifier language = null; 165 for (String qualifier : Splitter.on('-').split(folder)) { 166 if (qualifier.length() == 3) { 167 region = RegionQualifier.getQualifier(qualifier); 168 if (region != null) { 169 break; 170 } 171 } else if (qualifier.length() == 2 && language == null) { 172 language = LanguageQualifier.getQualifier(qualifier); 173 } 174 } 175 if (region != null || language != null) { 176 return FlagManager.get().getFlag(language, region); 177 } 178 179 return null; 180 } 181 182 /** 183 * Returns the flag for the given region. 184 * 185 * @param region the 2 letter region code (ISO 3166-1 alpha-2), in upper case 186 * @return a suitable flag icon, or null 187 */ 188 @Nullable 189 public Image getFlag(@NonNull String region) { 190 assert region.length() == 2 191 && Character.isUpperCase(region.charAt(0)) 192 && Character.isUpperCase(region.charAt(1)) : region; 193 194 return getIcon(region); 195 } 196 197 private Image getIcon(@NonNull String base) { 198 Image flagImage = mImageMap.get(base); 199 if (flagImage == null) { 200 // TODO: Special case locale currently running on system such 201 // that the current country matches the current locale 202 if (mImageMap.containsKey(base)) { 203 // Already checked: there's just no image there 204 return null; 205 } 206 String flagFileName = base.toLowerCase(Locale.US) + ".png"; //$NON-NLS-1$ 207 flagImage = DesignerPlugin.getImage("nls/flags/" + flagFileName); //$NON-NLS-1$ 208 mImageMap.put(base, flagImage); 209 } 210 211 return flagImage; 212 } 213 } 214