|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 package org.mozilla.gecko.preferences; |
|
6 |
|
7 import org.json.JSONException; |
|
8 import org.json.JSONObject; |
|
9 import org.mozilla.gecko.R; |
|
10 import org.mozilla.gecko.favicons.Favicons; |
|
11 import org.mozilla.gecko.favicons.decoders.FaviconDecoder; |
|
12 import org.mozilla.gecko.util.ThreadUtils; |
|
13 import org.mozilla.gecko.widget.FaviconView; |
|
14 |
|
15 import android.app.AlertDialog; |
|
16 import android.content.Context; |
|
17 import android.graphics.Bitmap; |
|
18 import android.graphics.drawable.BitmapDrawable; |
|
19 import android.text.SpannableString; |
|
20 import android.util.Log; |
|
21 import android.view.View; |
|
22 import android.widget.Toast; |
|
23 |
|
24 /** |
|
25 * Represents an element in the list of search engines on the preferences menu. |
|
26 */ |
|
27 public class SearchEnginePreference extends CustomListPreference { |
|
28 protected String LOGTAG = "SearchEnginePreference"; |
|
29 |
|
30 protected static final int INDEX_REMOVE_BUTTON = 1; |
|
31 |
|
32 // The icon to display in the prompt when clicked. |
|
33 private BitmapDrawable mPromptIcon; |
|
34 |
|
35 // The bitmap backing the drawable above - needed separately for the FaviconView. |
|
36 private Bitmap mIconBitmap; |
|
37 |
|
38 private FaviconView mFaviconView; |
|
39 |
|
40 public SearchEnginePreference(Context context, SearchPreferenceCategory parentCategory) { |
|
41 super(context, parentCategory); |
|
42 } |
|
43 |
|
44 /** |
|
45 * Called by Android when we're bound to the custom view. Allows us to set the custom properties |
|
46 * of our custom view elements as we desire (We can now use findViewById on them). |
|
47 * |
|
48 * @param view The view instance for this Preference object. |
|
49 */ |
|
50 @Override |
|
51 protected void onBindView(View view) { |
|
52 super.onBindView(view); |
|
53 |
|
54 // Set the icon in the FaviconView. |
|
55 mFaviconView = ((FaviconView) view.findViewById(R.id.search_engine_icon)); |
|
56 mFaviconView.updateAndScaleImage(mIconBitmap, getTitle().toString()); |
|
57 } |
|
58 |
|
59 @Override |
|
60 protected int getPreferenceLayoutResource() { |
|
61 return R.layout.preference_search_engine; |
|
62 } |
|
63 |
|
64 /** |
|
65 * Returns the strings to be displayed in the dialog. |
|
66 */ |
|
67 @Override |
|
68 protected String[] createDialogItems() { |
|
69 return new String[] { LABEL_SET_AS_DEFAULT, |
|
70 LABEL_REMOVE }; |
|
71 } |
|
72 |
|
73 @Override |
|
74 public void showDialog() { |
|
75 // If this is the last engine, then we are the default, and none of the options |
|
76 // on this menu can do anything. |
|
77 if (mParentCategory.getPreferenceCount() == 1) { |
|
78 ThreadUtils.postToUiThread(new Runnable() { |
|
79 @Override |
|
80 public void run() { |
|
81 Toast.makeText(getContext(), R.string.pref_search_last_toast, Toast.LENGTH_SHORT).show(); |
|
82 } |
|
83 }); |
|
84 return; |
|
85 } |
|
86 |
|
87 super.showDialog(); |
|
88 } |
|
89 |
|
90 @Override |
|
91 protected void configureDialogBuilder(AlertDialog.Builder builder) { |
|
92 // Copy the icon from this object to the prompt we produce. We lazily create the drawable, |
|
93 // as the user may not ever actually tap this object. |
|
94 if (mPromptIcon == null && mIconBitmap != null) { |
|
95 mPromptIcon = new BitmapDrawable(getContext().getResources(), mFaviconView.getBitmap()); |
|
96 } |
|
97 |
|
98 builder.setIcon(mPromptIcon); |
|
99 } |
|
100 |
|
101 @Override |
|
102 protected void onDialogIndexClicked(int index) { |
|
103 switch (index) { |
|
104 case INDEX_SET_DEFAULT_BUTTON: |
|
105 mParentCategory.setDefault(this); |
|
106 break; |
|
107 |
|
108 case INDEX_REMOVE_BUTTON: |
|
109 mParentCategory.uninstall(this); |
|
110 break; |
|
111 |
|
112 default: |
|
113 Log.w(LOGTAG, "Selected index out of range."); |
|
114 break; |
|
115 } |
|
116 } |
|
117 |
|
118 /** |
|
119 * Configure this Preference object from the Gecko search engine JSON object. |
|
120 * @param geckoEngineJSON The Gecko-formatted JSON object representing the search engine. |
|
121 * @throws JSONException If the JSONObject is invalid. |
|
122 */ |
|
123 public void setSearchEngineFromJSON(JSONObject geckoEngineJSON) throws JSONException { |
|
124 final String engineName = geckoEngineJSON.getString("name"); |
|
125 final SpannableString titleSpannable = new SpannableString(engineName); |
|
126 |
|
127 setTitle(titleSpannable); |
|
128 |
|
129 final String iconURI = geckoEngineJSON.getString("iconURI"); |
|
130 // Keep a reference to the bitmap - we'll need it later in onBindView. |
|
131 try { |
|
132 final int desiredWidth; |
|
133 if (mFaviconView != null) { |
|
134 desiredWidth = mFaviconView.getWidth(); |
|
135 } else { |
|
136 // largestFaviconSize is initialized when Favicons is attached to a |
|
137 // context, which occurs during GeckoApp.onCreate. That might not |
|
138 // ever happen (leaving it at 0), so we fall back. |
|
139 if (Favicons.largestFaviconSize == 0) { |
|
140 desiredWidth = 128; |
|
141 } else { |
|
142 desiredWidth = Favicons.largestFaviconSize; |
|
143 } |
|
144 } |
|
145 |
|
146 // TODO: use the cache. Bug 961600. |
|
147 mIconBitmap = FaviconDecoder.getMostSuitableBitmapFromDataURI(iconURI, desiredWidth); |
|
148 |
|
149 } catch (IllegalArgumentException e) { |
|
150 Log.e(LOGTAG, "IllegalArgumentException creating Bitmap. Most likely a zero-length bitmap.", e); |
|
151 } catch (NullPointerException e) { |
|
152 Log.e(LOGTAG, "NullPointerException creating Bitmap. Most likely a zero-length bitmap.", e); |
|
153 } |
|
154 } |
|
155 } |