blob: 3379537dd8cb2ede59df6df300bb9b360c922e31 [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;
The Android Open Source Projectfbb2a3a2009-02-13 12:57:52 -080020import android.app.Dialog;
The Android Open Source Projected217d92008-12-17 18:05:52 -080021import android.content.Context;
22import android.content.res.Resources;
23import android.graphics.Bitmap;
24import android.graphics.BitmapFactory;
25import android.os.Handler;
The Android Open Source Project765e7c92009-01-09 17:51:25 -080026import android.text.Spannable;
27import android.text.SpannableString;
28import android.text.style.UnderlineSpan;
The Android Open Source Projected217d92008-12-17 18:05:52 -080029import android.util.Log;
30import android.view.InflateException;
31import android.view.LayoutInflater;
32import android.view.View;
33import android.view.ViewGroup;
34import android.widget.Button;
35import android.widget.ImageView;
36import android.widget.TextView;
37
38import java.io.InputStream;
39import java.io.IOException;
40import java.lang.ClassCastException;
41import java.net.HttpURLConnection;
42import java.net.MalformedURLException;
43import java.net.URL;
44
45import org.json.JSONException;
46import org.json.JSONObject;
47
48/**
49 * Base dialog class for gears
50 */
51class GearsBaseDialog {
52
53 private static final String TAG = "GearsNativeDialog";
54 protected Handler mHandler;
55 protected Activity mActivity;
56 protected String mDialogArguments;
57
58 private Bitmap mIcon;
59 private final int MAX_ICON_SIZE = 64;
60 protected int mChoosenIconSize;
61
62 // Dialog closing types
63 public static final int CANCEL = 0;
64 public static final int ALWAYS_DENY = 1;
65 public static final int ALLOW = 2;
66 public static final int DENY = 3;
67 public static final int NEW_ICON = 4;
68 public static final int UPDATE_ICON = 5;
69 public static final int REQUEST_ICON = 6;
70 public static final int PAUSE_REQUEST_ICON = 7;
71
72 protected final String LOCAL_DATA_STRING = "localData";
73 protected final String LOCAL_STORAGE_STRING = "localStorage";
74 protected final String LOCATION_DATA_STRING = "locationData";
75
76 protected String mGearsVersion = "UNDEFINED";
77 protected boolean mDebug = false;
78
79 public GearsBaseDialog(Activity activity, Handler handler, String arguments) {
80 mActivity = activity;
81 mHandler = handler;
82 mDialogArguments = arguments;
83 }
84
85 Resources getResources() {
86 return mActivity.getResources();
87 }
88
89 Object getSystemService(String name) {
90 return mActivity.getSystemService(name);
91 }
92
93 View findViewById(int id) {
94 return mActivity.findViewById(id);
95 }
96
97 private String getString(int id) {
98 return mActivity.getString(id);
99 }
100
101 public void setDebug(boolean debug) {
102 mDebug = debug;
103 }
104
105 public void setGearsVersion(String version) {
106 mGearsVersion = version;
107 }
108
109 public String closeDialog(int closingType) {
110 return null;
111 }
112
113 /*
114 * Utility methods for setting up the dialogs elements
115 */
116
117 /**
118 * Inflate a given layout in a view (which has to be
119 * a ViewGroup, e.g. LinearLayout).
120 * This is used to share the basic dialog outline among
121 * the different dialog types.
122 */
123 void inflate(int layout, int viewID) {
124 LayoutInflater inflater = (LayoutInflater) getSystemService(
125 Context.LAYOUT_INFLATER_SERVICE);
126 View view = findViewById(viewID);
127 if (view != null) {
128 try {
129 ViewGroup viewGroup = (ViewGroup) view;
130 inflater.inflate(layout, viewGroup);
131 } catch (ClassCastException e) {
132 String msg = "exception, the view (" + view + ")";
133 msg += " is not a ViewGroup";
134 Log.e(TAG, msg, e);
135 } catch (InflateException e) {
136 Log.e(TAG, "exception while inflating the layout", e);
137 }
138 } else {
139 String msg = "problem, trying to inflate a non-existent view";
140 msg += " (" + viewID + ")";
141 Log.e(TAG, msg);
142 }
143 }
144
145 /**
146 * Button setup.
147 * Set the button's text and its listener. If the text resource's id
148 * is 0, makes the button invisible.
149 */
150 void setupButton(int buttonRscID,
151 int rscString,
The Android Open Source Project765e7c92009-01-09 17:51:25 -0800152 View.OnClickListener listener,
153 boolean isLink,
154 boolean requestFocus) {
The Android Open Source Projected217d92008-12-17 18:05:52 -0800155 View view = findViewById(buttonRscID);
156 if (view == null) {
157 return;
158 }
The Android Open Source Project765e7c92009-01-09 17:51:25 -0800159
The Android Open Source Projected217d92008-12-17 18:05:52 -0800160 Button button = (Button) view;
161
162 if (rscString == 0) {
163 button.setVisibility(View.GONE);
164 } else {
165 CharSequence text = getString(rscString);
166 button.setText(text);
167 button.setOnClickListener(listener);
The Android Open Source Project765e7c92009-01-09 17:51:25 -0800168 if (isLink) {
169 displayAsLink(button);
170 }
171 if (requestFocus) {
172 button.requestFocus();
173 }
The Android Open Source Projected217d92008-12-17 18:05:52 -0800174 }
175 }
176
177 /**
The Android Open Source Project765e7c92009-01-09 17:51:25 -0800178 * Button setup: as the above method, except that 'isLink' and
179 * 'requestFocus' default to false.
180 */
181 void setupButton(int buttonRsc, int rsc,
182 View.OnClickListener listener) {
183 setupButton(buttonRsc, rsc, listener, false, false);
184 }
185
186 /**
The Android Open Source Projected217d92008-12-17 18:05:52 -0800187 * Utility method to setup the three dialog buttons.
188 */
189 void setupButtons(int alwaysDenyRsc, int allowRsc, int denyRsc) {
190 setupButton(R.id.button_alwaysdeny, alwaysDenyRsc,
191 new Button.OnClickListener() {
192 public void onClick(View v) {
193 mHandler.sendEmptyMessage(ALWAYS_DENY);
194 }
The Android Open Source Projectfbb2a3a2009-02-13 12:57:52 -0800195 });
The Android Open Source Projected217d92008-12-17 18:05:52 -0800196
197 setupButton(R.id.button_allow, allowRsc,
198 new Button.OnClickListener() {
199 public void onClick(View v) {
200 mHandler.sendEmptyMessage(ALLOW);
201 }
The Android Open Source Projectfbb2a3a2009-02-13 12:57:52 -0800202 });
The Android Open Source Projected217d92008-12-17 18:05:52 -0800203
204 setupButton(R.id.button_deny, denyRsc,
205 new Button.OnClickListener() {
206 public void onClick(View v) {
207 mHandler.sendEmptyMessage(DENY);
208 }
209 });
210 }
211
212 /**
The Android Open Source Project765e7c92009-01-09 17:51:25 -0800213 * Display a button as an HTML link. Remove the background, set the
214 * text color to R.color.dialog_link and draw an underline
215 */
216 void displayAsLink(Button button) {
217 if (button == null) {
218 return;
219 }
220
221 CharSequence text = button.getText();
222 button.setBackgroundDrawable(null);
223 int color = getResources().getColor(R.color.dialog_link);
224 button.setTextColor(color);
225 SpannableString str = new SpannableString(text);
226 str.setSpan(new UnderlineSpan(), 0, str.length(),
227 Spannable.SPAN_INCLUSIVE_INCLUSIVE);
228 button.setText(str);
229 button.setFocusable(false);
230 }
231
232 /**
The Android Open Source Projected217d92008-12-17 18:05:52 -0800233 * Utility method to set elements' text indicated in
234 * the dialogs' arguments.
235 */
236 void setLabel(JSONObject json, String name, int rsc) {
237 try {
238 if (json.has(name)) {
239 String text = json.getString(name);
240 View view = findViewById(rsc);
241 if (view != null && text != null) {
242 TextView textView = (TextView) view;
243 textView.setText(text);
244 textView.setVisibility(View.VISIBLE);
245 }
246 }
247 } catch (JSONException e) {
248 Log.e(TAG, "json exception", e);
249 }
250 }
251
252 /**
The Android Open Source Projectfbb2a3a2009-02-13 12:57:52 -0800253 * Utility method to hide a view.
254 */
255 void hideView(View v, int rsc) {
256 if (rsc == 0) {
257 return;
258 }
259 View view = v.findViewById(rsc);
260 if (view != null) {
261 view.setVisibility(View.GONE);
262 }
263 }
264
265 /**
266 * Utility method to show a view.
267 */
268 void showView(View v, int rsc) {
269 if (rsc == 0) {
270 return;
271 }
272 View view = v.findViewById(rsc);
273 if (view != null) {
274 view.setVisibility(View.VISIBLE);
275 }
276 }
277
278 /**
279 * Utility method to set a text.
280 */
281 void setText(View v, int rsc, CharSequence text) {
282 if (rsc == 0) {
283 return;
284 }
285 View view = v.findViewById(rsc);
286 if (view != null) {
287 TextView textView = (TextView) view;
288 textView.setText(text);
289 textView.setVisibility(View.VISIBLE);
290 }
291 }
292
293 /**
294 * Utility method to set a text.
295 */
296 void setText(View v, int rsc, int txtRsc) {
297 if (rsc == 0) {
298 return;
299 }
300 View view = v.findViewById(rsc);
301 if (view != null) {
302 TextView textView = (TextView) view;
303 if (txtRsc == 0) {
304 textView.setVisibility(View.GONE);
305 } else {
306 CharSequence text = getString(txtRsc);
307 textView.setText(text);
308 textView.setVisibility(View.VISIBLE);
309 }
310 }
311 }
312
313 /**
The Android Open Source Projected217d92008-12-17 18:05:52 -0800314 * Utility class to download an icon in the background.
315 * Once done ask the UI thread to update the icon.
316 */
317 class IconDownload implements Runnable {
318 private String mUrlString;
319
320 IconDownload(String url) {
321 mUrlString = url;
322 }
323
324 public void run() {
325 if (mUrlString == null) {
326 return;
327 }
328 try {
329 URL url = new URL(mUrlString);
330 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
331 connection.setDoInput(true);
332 connection.connect();
333 int length = connection.getContentLength();
334 InputStream is = connection.getInputStream();
335 Bitmap customIcon = BitmapFactory.decodeStream(is);
336 if (customIcon != null) {
337 mIcon = customIcon;
338 mHandler.sendEmptyMessage(UPDATE_ICON);
339 }
340 } catch (ClassCastException e) {
341 Log.e(TAG, "Class cast exception (" + mUrlString + ")", e);
342 } catch (MalformedURLException e) {
343 Log.e(TAG, "Malformed url (" + mUrlString + ") ", e);
344 } catch (IOException e) {
345 Log.e(TAG, "Exception downloading icon (" + mUrlString + ") ", e);
346 }
347 }
348 }
349
350 /**
351 * Utility method to update the icon.
352 * Called on the UI thread.
353 */
354 public void updateIcon() {
355 if (mIcon == null) {
356 return;
357 }
358 View view = findViewById(R.id.origin_icon);
359 if (view != null) {
360 ImageView imageView = (ImageView) view;
361 imageView.setMaxHeight(MAX_ICON_SIZE);
362 imageView.setMaxWidth(MAX_ICON_SIZE);
363 imageView.setScaleType(ImageView.ScaleType.FIT_XY);
364 imageView.setImageBitmap(mIcon);
365 imageView.setVisibility(View.VISIBLE);
366 }
367 }
368
369 /**
370 * Utility method to download an icon from a url and set
371 * it to the GUI element R.id.origin_icon.
372 * It is used both in the shortcut dialog and the
373 * permission dialog.
374 * The actual download is done in the background via
375 * IconDownload; once the icon is downlowded the UI is updated
376 * via updateIcon().
377 * The icon size is included in the layout with the choosen
378 * size, although not displayed, to limit text reflow once
379 * the icon is received.
380 */
381 void downloadIcon(String url) {
382 if (url == null) {
383 return;
384 }
385 View view = findViewById(R.id.origin_icon);
386 if (view != null) {
387 view.setMinimumWidth(mChoosenIconSize);
388 view.setMinimumHeight(mChoosenIconSize);
389 view.setVisibility(View.INVISIBLE);
390 }
391 Thread thread = new Thread(new IconDownload(url));
392 thread.start();
393 }
394
395 /**
396 * Utility method that get the dialogMessage
397 * and icon and ask the setupDialog(message,icon)
398 * method to set the values.
399 */
400 public void setupDialog() {
401 TextView dialogMessage = null;
402 ImageView icon = null;
403
404 View view = findViewById(R.id.dialog_message);
405 if (view != null) {
406 dialogMessage = (TextView) view;
407 }
408
409 View iconView = findViewById(R.id.icon);
410 if (iconView != null) {
411 icon = (ImageView) iconView;
412 }
413
414 if ((dialogMessage != null) && (icon != null)) {
415 setupDialog(dialogMessage, icon);
416 dialogMessage.setVisibility(View.VISIBLE);
417 }
418 }
419
420 /*
421 * Set the message and icon of the dialog
422 */
423 public void setupDialog(TextView message, ImageView icon) {
424 message.setText(R.string.unrecognized_dialog_message);
The Android Open Source Projectfbb2a3a2009-02-13 12:57:52 -0800425 icon.setImageResource(R.drawable.ic_dialog_menu_generic);
The Android Open Source Projected217d92008-12-17 18:05:52 -0800426 message.setVisibility(View.VISIBLE);
427 }
428
429 /**
430 * Setup the dialog
431 * By default, just display a simple message.
432 */
433 public void setup() {
434 setupButtons(0, 0, R.string.default_button);
435 setupDialog();
436 }
437
The Android Open Source Projectfbb2a3a2009-02-13 12:57:52 -0800438 /**
439 * Method called when the back button is pressed,
440 * allowing the dialog to intercept the default behaviour.
441 */
442 public boolean handleBackButton() {
443 return false;
444 }
445
446 /**
447 * Returns the resource string of the notification displayed
448 * after the dialog. By default, does not return one.
449 */
450 public int notification() {
451 return 0;
452 }
453
454 /**
455 * If a secondary dialog (e.g. a confirmation dialog) is created,
456 * GearsNativeDialog will call this method.
457 */
458 public Dialog onCreateDialog(int id) {
459 // This should be redefined by subclasses as needed.
460 return null;
461 }
462
The Android Open Source Projected217d92008-12-17 18:05:52 -0800463}