Home | History | Annotate | Download | only in configuration
      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