FileDocCategorySizeDatePackage
GearsBaseDialog.javaAPI DocAndroid 1.5 API12950Wed May 06 22:42:42 BST 2009com.android.browser

GearsBaseDialog.java

/*
 * 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;
  }

}