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.FolderConfiguration;
22 import com.android.ide.common.resources.configuration.LocaleQualifier;
23 import com.android.ide.eclipse.adt.internal.editors.IconFactory;
24 import com.google.common.collect.Maps;
25 
26 import org.eclipse.swt.graphics.Image;
27 import org.eclipse.wb.internal.core.DesignerPlugin;
28 
29 import java.util.Locale;
30 import java.util.Map;
31 
32 /**
33  * The {@linkplain FlagManager} provides access to flags for regions known
34  * to {@link LocaleManager}. It also contains some locale related display
35  * functions.
36  * <p>
37  * All the flag images came from the WindowBuilder subversion repository
38  * http://dev.eclipse.org/svnroot/tools/org.eclipse.windowbuilder/trunk (and in
39  * particular, a snapshot of revision 424). However, it appears that the icons
40  * are from http://www.famfamfam.com/lab/icons/flags/ which states that "these
41  * flag icons are available for free use for any purpose with no requirement for
42  * attribution." Adding the URL here such that we can check back occasionally
43  * and see if there are corrections or updates. Also note that the flag names
44  * are in ISO 3166-1 alpha-2 country codes.
45  */
46 public class FlagManager {
47     private static final FlagManager sInstance = new FlagManager();
48 
49     /**
50      * Returns the {@linkplain FlagManager} singleton
51      *
52      * @return the {@linkplain FlagManager} singleton, never null
53      */
54     @NonNull
get()55     public static FlagManager get() {
56         return sInstance;
57     }
58 
59     /** Use the {@link #get()} factory method */
FlagManager()60     private FlagManager() {
61     }
62 
63     /** Map from region to flag icon */
64     private final Map<String, Image> mImageMap = Maps.newHashMap();
65 
66     /**
67      * Returns the empty flag icon used to indicate an unknown country
68      *
69      * @return the globe icon used to indicate an unknown country
70      */
getEmptyIcon()71     public static Image getEmptyIcon() {
72       return DesignerPlugin.getImage("nls/flags/flag_empty.png"); //$NON-NLS-1$
73     }
74 
75     /**
76      * Returns the globe icon used to indicate "any" language
77      *
78      * @return the globe icon used to indicate "any" language
79      */
getGlobeIcon()80     public static Image getGlobeIcon() {
81         return IconFactory.getInstance().getIcon("globe"); //$NON-NLS-1$
82     }
83 
84     /**
85      * Returns the flag for the given language and region.
86      *
87      * @param language the language, or null (if null, region must not be null),
88      *            the 2 letter language code (ISO 639-1), in lower case
89      * @param region the region, or null (if null, language must not be null),
90      *            the 2 letter region code (ISO 3166-1 alpha-2), in upper case
91      * @return a suitable flag icon, or null
92      */
93     @Nullable
getFlag(@ullable String language, @Nullable String region)94     public Image getFlag(@Nullable String language, @Nullable String region) {
95         assert region != null || language != null;
96         if (region == null || region.isEmpty()) {
97             // Look up the region for a given language
98             assert language != null;
99 
100             // Special cases where we have a dedicated flag available:
101             if (language.equals("ca")) {        //$NON-NLS-1$
102               return getIcon("catalonia");      //$NON-NLS-1$
103             }
104             else if (language.equals("gd")) { //$NON-NLS-1$
105               return getIcon("scotland");     //$NON-NLS-1$
106             }
107             else if (language.equals("cy")) { //$NON-NLS-1$
108               return getIcon("wales");        //$NON-NLS-1$
109             }
110 
111             // Prefer the local registration of the current locale; even if
112             // for example the default locale for English is the US, if the current
113             // default locale is English, then use its associated country, which could
114             // for example be Australia.
115             Locale locale = Locale.getDefault();
116             if (language.equals(locale.getLanguage())) {
117                 Image flag = getFlag(locale.getCountry());
118                 if (flag != null) {
119                     return flag;
120                 }
121             }
122 
123             region = LocaleManager.getLanguageRegion(language);
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      */
getFlag(@ullable LocaleQualifier locale)142     public Image getFlag(@Nullable LocaleQualifier locale) {
143         if (locale == null) {
144             return null;
145           }
146           String languageCode = locale.getLanguage();
147           String regionCode = locale.getRegion();
148           if (LocaleQualifier.FAKE_VALUE.equals(languageCode)) {
149             languageCode = 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
getFlagForFolderName(@onNull String folder)162     public Image getFlagForFolderName(@NonNull String folder) {
163         FolderConfiguration configuration = FolderConfiguration.getConfigForFolder(folder);
164         if (configuration != null) {
165           return get().getFlag(configuration);
166         }
167 
168         return null;
169     }
170 
171     /**
172      * Returns the flag for the given folder
173      *
174      * @param configuration the folder configuration
175      * @return a suitable flag icon, or null
176      */
177     @Nullable
getFlag(@onNull FolderConfiguration configuration)178     public Image getFlag(@NonNull FolderConfiguration configuration) {
179         return getFlag(configuration.getLocaleQualifier());
180     }
181 
182 
183 
184     /**
185      * Returns the flag for the given region.
186      *
187      * @param region the 2 letter region code (ISO 3166-1 alpha-2), in upper case
188      * @return a suitable flag icon, or null
189      */
190     @Nullable
getFlag(@onNull String region)191     public Image getFlag(@NonNull String region) {
192         assert region.length() == 2
193                 && Character.isUpperCase(region.charAt(0))
194                 && Character.isUpperCase(region.charAt(1)) : region;
195 
196         return getIcon(region);
197     }
198 
getIcon(@onNull String base)199     private Image getIcon(@NonNull String base) {
200         Image flagImage = mImageMap.get(base);
201           if (flagImage == null) {
202               // TODO: Special case locale currently running on system such
203               // that the current country matches the current locale
204               if (mImageMap.containsKey(base)) {
205                   // Already checked: there's just no image there
206                   return null;
207               }
208               String flagFileName = base.toLowerCase(Locale.US) + ".png"; //$NON-NLS-1$
209               flagImage = DesignerPlugin.getImage("nls/flags/" + flagFileName); //$NON-NLS-1$
210               mImageMap.put(base, flagImage);
211           }
212 
213         return flagImage;
214     }
215 }
216