/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.browser;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.UnderlineSpan;
import android.util.Log;
import android.view.InflateException;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import java.io.InputStream;
import java.io.IOException;
import java.lang.ClassCastException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Base dialog class for gears
*/
class GearsBaseDialog {
private static final String TAG = "GearsNativeDialog";
protected Handler mHandler;
protected Activity mActivity;
protected String mDialogArguments;
private Bitmap mIcon;
private final int MAX_ICON_SIZE = 64;
protected int mChoosenIconSize;
// Dialog closing types
public static final int CANCEL = 0;
public static final int ALWAYS_DENY = 1;
public static final int ALLOW = 2;
public static final int DENY = 3;
public static final int NEW_ICON = 4;
public static final int UPDATE_ICON = 5;
public static final int REQUEST_ICON = 6;
public static final int PAUSE_REQUEST_ICON = 7;
public static final int CLEAR_REQUEST_ICON = 8;
protected final String LOCAL_DATA_STRING = "localData";
protected final String LOCAL_STORAGE_STRING = "localStorage";
protected final String LOCATION_DATA_STRING = "locationData";
protected String mGearsVersion = "UNDEFINED";
protected boolean mDebug = false;
public GearsBaseDialog(Activity activity, Handler handler, String arguments) {
mActivity = activity;
mHandler = handler;
mDialogArguments = arguments;
}
Resources getResources() {
return mActivity.getResources();
}
Object getSystemService(String name) {
return mActivity.getSystemService(name);
}
View findViewById(int id) {
return mActivity.findViewById(id);
}
private String getString(int id) {
return mActivity.getString(id);
}
public void setDebug(boolean debug) {
mDebug = debug;
}
public void setGearsVersion(String version) {
mGearsVersion = version;
}
public String closeDialog(int closingType) {
return null;
}
/*
* Utility methods for setting up the dialogs elements
*/
/**
* Inflate a given layout in a view (which has to be
* a ViewGroup, e.g. LinearLayout).
* This is used to share the basic dialog outline among
* the different dialog types.
*/
void inflate(int layout, int viewID) {
LayoutInflater inflater = (LayoutInflater) getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
View view = findViewById(viewID);
if (view != null) {
try {
ViewGroup viewGroup = (ViewGroup) view;
inflater.inflate(layout, viewGroup);
} catch (ClassCastException e) {
String msg = "exception, the view (" + view + ")";
msg += " is not a ViewGroup";
Log.e(TAG, msg, e);
} catch (InflateException e) {
Log.e(TAG, "exception while inflating the layout", e);
}
} else {
String msg = "problem, trying to inflate a non-existent view";
msg += " (" + viewID + ")";
Log.e(TAG, msg);
}
}
/**
* Button setup.
* Set the button's text and its listener. If the text resource's id
* is 0, makes the button invisible.
*/
void setupButton(int buttonRscID,
int rscString,
View.OnClickListener listener,
boolean isLink,
boolean requestFocus) {
View view = findViewById(buttonRscID);
if (view == null) {
return;
}
Button button = (Button) view;
if (rscString == 0) {
button.setVisibility(View.GONE);
} else {
CharSequence text = getString(rscString);
button.setText(text);
button.setOnClickListener(listener);
if (isLink) {
displayAsLink(button);
}
if (requestFocus) {
button.requestFocus();
}
}
}
/**
* Button setup: as the above method, except that 'isLink' and
* 'requestFocus' default to false.
*/
void setupButton(int buttonRsc, int rsc,
View.OnClickListener listener) {
setupButton(buttonRsc, rsc, listener, false, false);
}
/**
* Utility method to setup the three dialog buttons.
*/
void setupButtons(int alwaysDenyRsc, int allowRsc, int denyRsc) {
setupButton(R.id.button_alwaysdeny, alwaysDenyRsc,
new Button.OnClickListener() {
public void onClick(View v) {
mHandler.sendEmptyMessage(ALWAYS_DENY);
}
});
setupButton(R.id.button_allow, allowRsc,
new Button.OnClickListener() {
public void onClick(View v) {
mHandler.sendEmptyMessage(ALLOW);
}
});
setupButton(R.id.button_deny, denyRsc,
new Button.OnClickListener() {
public void onClick(View v) {
mHandler.sendEmptyMessage(DENY);
}
});
}
/**
* Display a button as an HTML link. Remove the background, set the
* text color to R.color.dialog_link and draw an underline
*/
void displayAsLink(Button button) {
if (button == null) {
return;
}
CharSequence text = button.getText();
button.setBackgroundDrawable(null);
int color = getResources().getColor(R.color.dialog_link);
button.setTextColor(color);
SpannableString str = new SpannableString(text);
str.setSpan(new UnderlineSpan(), 0, str.length(),
Spannable.SPAN_INCLUSIVE_INCLUSIVE);
button.setText(str);
button.setFocusable(false);
}
/**
* Utility method to set elements' text indicated in
* the dialogs' arguments.
*/
void setLabel(JSONObject json, String name, int rsc) {
try {
if (json.has(name)) {
String text = json.getString(name);
View view = findViewById(rsc);
if (view != null && text != null) {
TextView textView = (TextView) view;
textView.setText(text);
textView.setVisibility(View.VISIBLE);
}
}
} catch (JSONException e) {
Log.e(TAG, "json exception", e);
}
}
/**
* Utility method to hide a view.
*/
void hideView(View v, int rsc) {
if (rsc == 0) {
return;
}
View view;
if (v == null) {
view = findViewById(rsc);
} else {
view = v.findViewById(rsc);
}
if (view != null) {
view.setVisibility(View.GONE);
}
}
/**
* Utility method to show a view.
*/
void showView(View v, int rsc) {
if (rsc == 0) {
return;
}
View view;
if (v == null) {
view = findViewById(rsc);
} else {
view = v.findViewById(rsc);
}
if (view != null) {
view.setVisibility(View.VISIBLE);
}
}
/**
* Utility method to set a text.
*/
void setText(View v, int rsc, CharSequence text) {
if (rsc == 0) {
return;
}
View view = v.findViewById(rsc);
if (view != null) {
TextView textView = (TextView) view;
textView.setText(text);
textView.setVisibility(View.VISIBLE);
}
}
/**
* Utility method to set a text.
*/
void setText(View v, int rsc, int txtRsc) {
if (rsc == 0) {
return;
}
View view = v.findViewById(rsc);
if (view != null) {
TextView textView = (TextView) view;
if (txtRsc == 0) {
textView.setVisibility(View.GONE);
} else {
CharSequence text = getString(txtRsc);
textView.setText(text);
textView.setVisibility(View.VISIBLE);
}
}
}
/**
* Utility class to download an icon in the background.
* Once done ask the UI thread to update the icon.
*/
class IconDownload implements Runnable {
private String mUrlString;
IconDownload(String url) {
mUrlString = url;
}
public void run() {
if (mUrlString == null) {
return;
}
try {
URL url = new URL(mUrlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
int length = connection.getContentLength();
InputStream is = connection.getInputStream();
Bitmap customIcon = BitmapFactory.decodeStream(is);
if (customIcon != null) {
mIcon = customIcon;
mHandler.sendEmptyMessage(UPDATE_ICON);
}
} catch (ClassCastException e) {
Log.e(TAG, "Class cast exception (" + mUrlString + ")", e);
} catch (MalformedURLException e) {
Log.e(TAG, "Malformed url (" + mUrlString + ") ", e);
} catch (IOException e) {
Log.e(TAG, "Exception downloading icon (" + mUrlString + ") ", e);
}
}
}
/**
* Utility method to update the icon.
* Called on the UI thread.
*/
public void updateIcon() {
if (mIcon == null) {
return;
}
View view = findViewById(R.id.origin_icon);
if (view != null) {
ImageView imageView = (ImageView) view;
imageView.setMaxHeight(MAX_ICON_SIZE);
imageView.setMaxWidth(MAX_ICON_SIZE);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setImageBitmap(mIcon);
imageView.setVisibility(View.VISIBLE);
}
}
/**
* Utility method to download an icon from a url and set
* it to the GUI element R.id.origin_icon.
* It is used both in the shortcut dialog and the
* permission dialog.
* The actual download is done in the background via
* IconDownload; once the icon is downlowded the UI is updated
* via updateIcon().
* The icon size is included in the layout with the choosen
* size, although not displayed, to limit text reflow once
* the icon is received.
*/
void downloadIcon(String url) {
if (url == null) {
return;
}
View view = findViewById(R.id.origin_icon);
if (view != null) {
view.setMinimumWidth(mChoosenIconSize);
view.setMinimumHeight(mChoosenIconSize);
view.setVisibility(View.INVISIBLE);
}
Thread thread = new Thread(new IconDownload(url));
thread.start();
}
/**
* Utility method that get the dialogMessage
* and icon and ask the setupDialog(message,icon)
* method to set the values.
*/
public void setupDialog() {
TextView dialogMessage = null;
ImageView icon = null;
View view = findViewById(R.id.dialog_message);
if (view != null) {
dialogMessage = (TextView) view;
}
View iconView = findViewById(R.id.icon);
if (iconView != null) {
icon = (ImageView) iconView;
}
if ((dialogMessage != null) && (icon != null)) {
setupDialog(dialogMessage, icon);
dialogMessage.setVisibility(View.VISIBLE);
}
}
/*
* Set the message and icon of the dialog
*/
public void setupDialog(TextView message, ImageView icon) {
message.setText(R.string.unrecognized_dialog_message);
icon.setImageResource(R.drawable.ic_dialog_menu_generic);
message.setVisibility(View.VISIBLE);
}
/**
* Setup the dialog
* By default, just display a simple message.
*/
public void setup() {
setupButtons(0, 0, R.string.default_button);
setupDialog();
}
/**
* Method called when the back button is pressed,
* allowing the dialog to intercept the default behaviour.
*/
public boolean handleBackButton() {
return false;
}
/**
* Returns the resource string of the notification displayed
* after the dialog. By default, does not return one.
*/
public int notification() {
return 0;
}
/**
* If a secondary dialog (e.g. a confirmation dialog) is created,
* GearsNativeDialog will call this method.
*/
public Dialog onCreateDialog(int id) {
// This should be redefined by subclasses as needed.
return null;
}
}
|