blob: afd0dd2b9e0d4310c162dd5758922d3f3e6d955a [file] [log] [blame]
The Android Open Source Projected217d92008-12-17 18:05:52 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
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
17package com.android.browser;
18
19import android.app.Activity;
20import android.content.Context;
21import android.content.res.Resources;
22import android.graphics.Bitmap;
23import android.graphics.BitmapFactory;
24import android.os.Handler;
The Android Open Source Project765e7c92009-01-09 17:51:25 -080025import android.text.Spannable;
26import android.text.SpannableString;
27import android.text.style.UnderlineSpan;
The Android Open Source Projected217d92008-12-17 18:05:52 -080028import android.util.Log;
29import android.view.InflateException;
30import android.view.LayoutInflater;
31import android.view.View;
32import android.view.ViewGroup;
33import android.widget.Button;
34import android.widget.ImageView;
35import android.widget.TextView;
36
37import java.io.InputStream;
38import java.io.IOException;
39import java.lang.ClassCastException;
40import java.net.HttpURLConnection;
41import java.net.MalformedURLException;
42import java.net.URL;
43
44import org.json.JSONException;
45import org.json.JSONObject;
46
47/**
48 * Base dialog class for gears
49 */
50class GearsBaseDialog {
51
52 private static final String TAG = "GearsNativeDialog";
53 protected Handler mHandler;
54 protected Activity mActivity;
55 protected String mDialogArguments;
56
57 private Bitmap mIcon;
58 private final int MAX_ICON_SIZE = 64;
59 protected int mChoosenIconSize;
60
61 // Dialog closing types
62 public static final int CANCEL = 0;
63 public static final int ALWAYS_DENY = 1;
64 public static final int ALLOW = 2;
65 public static final int DENY = 3;
66 public static final int NEW_ICON = 4;
67 public static final int UPDATE_ICON = 5;
68 public static final int REQUEST_ICON = 6;
69 public static final int PAUSE_REQUEST_ICON = 7;
70
71 protected final String LOCAL_DATA_STRING = "localData";
72 protected final String LOCAL_STORAGE_STRING = "localStorage";
73 protected final String LOCATION_DATA_STRING = "locationData";
74
75 protected String mGearsVersion = "UNDEFINED";
76 protected boolean mDebug = false;
77
78 public GearsBaseDialog(Activity activity, Handler handler, String arguments) {
79 mActivity = activity;
80 mHandler = handler;
81 mDialogArguments = arguments;
82 }
83
84 Resources getResources() {
85 return mActivity.getResources();
86 }
87
88 Object getSystemService(String name) {
89 return mActivity.getSystemService(name);
90 }
91
92 View findViewById(int id) {
93 return mActivity.findViewById(id);
94 }
95
96 private String getString(int id) {
97 return mActivity.getString(id);
98 }
99
100 public void setDebug(boolean debug) {
101 mDebug = debug;
102 }
103
104 public void setGearsVersion(String version) {
105 mGearsVersion = version;
106 }
107
108 public String closeDialog(int closingType) {
109 return null;
110 }
111
112 /*
113 * Utility methods for setting up the dialogs elements
114 */
115
116 /**
117 * Inflate a given layout in a view (which has to be
118 * a ViewGroup, e.g. LinearLayout).
119 * This is used to share the basic dialog outline among
120 * the different dialog types.
121 */
122 void inflate(int layout, int viewID) {
123 LayoutInflater inflater = (LayoutInflater) getSystemService(
124 Context.LAYOUT_INFLATER_SERVICE);
125 View view = findViewById(viewID);
126 if (view != null) {
127 try {
128 ViewGroup viewGroup = (ViewGroup) view;
129 inflater.inflate(layout, viewGroup);
130 } catch (ClassCastException e) {
131 String msg = "exception, the view (" + view + ")";
132 msg += " is not a ViewGroup";
133 Log.e(TAG, msg, e);
134 } catch (InflateException e) {
135 Log.e(TAG, "exception while inflating the layout", e);
136 }
137 } else {
138 String msg = "problem, trying to inflate a non-existent view";
139 msg += " (" + viewID + ")";
140 Log.e(TAG, msg);
141 }
142 }
143
144 /**
145 * Button setup.
146 * Set the button's text and its listener. If the text resource's id
147 * is 0, makes the button invisible.
148 */
149 void setupButton(int buttonRscID,
150 int rscString,
The Android Open Source Project765e7c92009-01-09 17:51:25 -0800151 View.OnClickListener listener,
152 boolean isLink,
153 boolean requestFocus) {
The Android Open Source Projected217d92008-12-17 18:05:52 -0800154 View view = findViewById(buttonRscID);
155 if (view == null) {
156 return;
157 }
The Android Open Source Project765e7c92009-01-09 17:51:25 -0800158
The Android Open Source Projected217d92008-12-17 18:05:52 -0800159 Button button = (Button) view;
160
161 if (rscString == 0) {
162 button.setVisibility(View.GONE);
163 } else {
164 CharSequence text = getString(rscString);
165 button.setText(text);
166 button.setOnClickListener(listener);
The Android Open Source Project765e7c92009-01-09 17:51:25 -0800167 if (isLink) {
168 displayAsLink(button);
169 }
170 if (requestFocus) {
171 button.requestFocus();
172 }
The Android Open Source Projected217d92008-12-17 18:05:52 -0800173 }
174 }
175
176 /**
The Android Open Source Project765e7c92009-01-09 17:51:25 -0800177 * Button setup: as the above method, except that 'isLink' and
178 * 'requestFocus' default to false.
179 */
180 void setupButton(int buttonRsc, int rsc,
181 View.OnClickListener listener) {
182 setupButton(buttonRsc, rsc, listener, false, false);
183 }
184
185 /**
The Android Open Source Projected217d92008-12-17 18:05:52 -0800186 * Utility method to setup the three dialog buttons.
187 */
188 void setupButtons(int alwaysDenyRsc, int allowRsc, int denyRsc) {
189 setupButton(R.id.button_alwaysdeny, alwaysDenyRsc,
190 new Button.OnClickListener() {
191 public void onClick(View v) {
192 mHandler.sendEmptyMessage(ALWAYS_DENY);
193 }
The Android Open Source Project765e7c92009-01-09 17:51:25 -0800194 }, true, false);
The Android Open Source Projected217d92008-12-17 18:05:52 -0800195
196 setupButton(R.id.button_allow, allowRsc,
197 new Button.OnClickListener() {
198 public void onClick(View v) {
199 mHandler.sendEmptyMessage(ALLOW);
200 }
The Android Open Source Project765e7c92009-01-09 17:51:25 -0800201 }, false, true);
The Android Open Source Projected217d92008-12-17 18:05:52 -0800202
203 setupButton(R.id.button_deny, denyRsc,
204 new Button.OnClickListener() {
205 public void onClick(View v) {
206 mHandler.sendEmptyMessage(DENY);
207 }
208 });
209 }
210
211 /**
The Android Open Source Project765e7c92009-01-09 17:51:25 -0800212 * Display a button as an HTML link. Remove the background, set the
213 * text color to R.color.dialog_link and draw an underline
214 */
215 void displayAsLink(Button button) {
216 if (button == null) {
217 return;
218 }
219
220 CharSequence text = button.getText();
221 button.setBackgroundDrawable(null);
222 int color = getResources().getColor(R.color.dialog_link);
223 button.setTextColor(color);
224 SpannableString str = new SpannableString(text);
225 str.setSpan(new UnderlineSpan(), 0, str.length(),
226 Spannable.SPAN_INCLUSIVE_INCLUSIVE);
227 button.setText(str);
228 button.setFocusable(false);
229 }
230
231 /**
The Android Open Source Projected217d92008-12-17 18:05:52 -0800232 * Utility method to set elements' text indicated in
233 * the dialogs' arguments.
234 */
235 void setLabel(JSONObject json, String name, int rsc) {
236 try {
237 if (json.has(name)) {
238 String text = json.getString(name);
239 View view = findViewById(rsc);
240 if (view != null && text != null) {
241 TextView textView = (TextView) view;
242 textView.setText(text);
243 textView.setVisibility(View.VISIBLE);
244 }
245 }
246 } catch (JSONException e) {
247 Log.e(TAG, "json exception", e);
248 }
249 }
250
251 /**
252 * Utility class to download an icon in the background.
253 * Once done ask the UI thread to update the icon.
254 */
255 class IconDownload implements Runnable {
256 private String mUrlString;
257
258 IconDownload(String url) {
259 mUrlString = url;
260 }
261
262 public void run() {
263 if (mUrlString == null) {
264 return;
265 }
266 try {
267 URL url = new URL(mUrlString);
268 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
269 connection.setDoInput(true);
270 connection.connect();
271 int length = connection.getContentLength();
272 InputStream is = connection.getInputStream();
273 Bitmap customIcon = BitmapFactory.decodeStream(is);
274 if (customIcon != null) {
275 mIcon = customIcon;
276 mHandler.sendEmptyMessage(UPDATE_ICON);
277 }
278 } catch (ClassCastException e) {
279 Log.e(TAG, "Class cast exception (" + mUrlString + ")", e);
280 } catch (MalformedURLException e) {
281 Log.e(TAG, "Malformed url (" + mUrlString + ") ", e);
282 } catch (IOException e) {
283 Log.e(TAG, "Exception downloading icon (" + mUrlString + ") ", e);
284 }
285 }
286 }
287
288 /**
289 * Utility method to update the icon.
290 * Called on the UI thread.
291 */
292 public void updateIcon() {
293 if (mIcon == null) {
294 return;
295 }
296 View view = findViewById(R.id.origin_icon);
297 if (view != null) {
298 ImageView imageView = (ImageView) view;
299 imageView.setMaxHeight(MAX_ICON_SIZE);
300 imageView.setMaxWidth(MAX_ICON_SIZE);
301 imageView.setScaleType(ImageView.ScaleType.FIT_XY);
302 imageView.setImageBitmap(mIcon);
303 imageView.setVisibility(View.VISIBLE);
304 }
305 }
306
307 /**
308 * Utility method to download an icon from a url and set
309 * it to the GUI element R.id.origin_icon.
310 * It is used both in the shortcut dialog and the
311 * permission dialog.
312 * The actual download is done in the background via
313 * IconDownload; once the icon is downlowded the UI is updated
314 * via updateIcon().
315 * The icon size is included in the layout with the choosen
316 * size, although not displayed, to limit text reflow once
317 * the icon is received.
318 */
319 void downloadIcon(String url) {
320 if (url == null) {
321 return;
322 }
323 View view = findViewById(R.id.origin_icon);
324 if (view != null) {
325 view.setMinimumWidth(mChoosenIconSize);
326 view.setMinimumHeight(mChoosenIconSize);
327 view.setVisibility(View.INVISIBLE);
328 }
329 Thread thread = new Thread(new IconDownload(url));
330 thread.start();
331 }
332
333 /**
334 * Utility method that get the dialogMessage
335 * and icon and ask the setupDialog(message,icon)
336 * method to set the values.
337 */
338 public void setupDialog() {
339 TextView dialogMessage = null;
340 ImageView icon = null;
341
342 View view = findViewById(R.id.dialog_message);
343 if (view != null) {
344 dialogMessage = (TextView) view;
345 }
346
347 View iconView = findViewById(R.id.icon);
348 if (iconView != null) {
349 icon = (ImageView) iconView;
350 }
351
352 if ((dialogMessage != null) && (icon != null)) {
353 setupDialog(dialogMessage, icon);
354 dialogMessage.setVisibility(View.VISIBLE);
355 }
356 }
357
358 /*
359 * Set the message and icon of the dialog
360 */
361 public void setupDialog(TextView message, ImageView icon) {
362 message.setText(R.string.unrecognized_dialog_message);
363 icon.setImageResource(R.drawable.gears_icon_48x48);
364 message.setVisibility(View.VISIBLE);
365 }
366
367 /**
368 * Setup the dialog
369 * By default, just display a simple message.
370 */
371 public void setup() {
372 setupButtons(0, 0, R.string.default_button);
373 setupDialog();
374 }
375
The Android Open Source Projected217d92008-12-17 18:05:52 -0800376}