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