Bug 1147064 - Add colored buttons. r=margaret

This commit is contained in:
Chenxia Liu 2015-05-21 16:27:38 -07:00
parent 68367db37c
commit ae4a3b371f
12 changed files with 129 additions and 120 deletions

View File

@ -9,6 +9,7 @@ import java.util.HashSet;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONArray;
import org.mozilla.gecko.AppConstants.Versions;
import org.mozilla.gecko.util.GeckoEventListener;
import org.mozilla.gecko.util.ThreadUtils;
@ -113,9 +114,21 @@ public class DoorHangerPopup extends AnchoredPopup
final DoorhangerConfig config = new DoorhangerConfig(tabId, id, doorhangerType, this);
config.setMessage(json.getString("message"));
config.appendButtonsFromJSON(json.getJSONArray("buttons"));
config.setOptions(json.getJSONObject("options"));
final JSONArray buttonArray = json.getJSONArray("buttons");
int numButtons = buttonArray.length();
if (numButtons > 2) {
Log.e(LOGTAG, "Doorhanger can have a maximum of two buttons!");
numButtons = 2;
}
for (int i = 0; i < numButtons; i++) {
final JSONObject buttonJSON = buttonArray.getJSONObject(i);
final boolean isPositive = buttonJSON.optBoolean("positive", false);
config.setButton(buttonJSON.getString("label"), buttonJSON.getInt("callback"), isPositive);
}
return config;
}

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false">
<shape>
<solid android:color="@color/toolbar_menu_dark_grey" />
</shape>
</item>
<item android:state_pressed="true">
<shape>
<solid android:color="@color/toolbar_grey_pressed" />
</shape>
</item>
</selector>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false">
<shape>
<solid android:color="@color/link_blue"/>
</shape>
</item>
<item android:state_pressed="true">
<shape>
<solid android:color="@color/link_blue_pressed" />
</shape>
</item>
</selector>

View File

@ -23,17 +23,23 @@
</LinearLayout>
<View android:id="@+id/divider_buttons"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/divider_light"
android:visibility="gone"/>
<LinearLayout android:id="@+id/doorhanger_buttons"
android:layout_width="match_parent"
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="gone"/>
android:orientation="horizontal">
<Button android:id="@+id/doorhanger_button_negative"
style="@style/Widget.Doorhanger.Button"
android:textColor="@android:color/black"
android:background="@drawable/action_bar_button_negative"
android:visibility="gone"/>
<Button android:id="@+id/doorhanger_button_positive"
style="@style/Widget.Doorhanger.Button"
android:textColor="@android:color/white"
android:background="@drawable/action_bar_button_positive"
android:visibility="gone"/>
</LinearLayout>
<View android:id="@+id/divider_doorhanger"
android:layout_width="match_parent"

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="48dip"
android:textColor="@color/placeholder_active_grey"
android:textSize="14sp"
android:background="@drawable/action_bar_button"/>

View File

@ -9,6 +9,7 @@
<color name="action_orange">#E66000</color>
<color name="action_orange_pressed">#DC5600</color>
<color name="link_blue">#0096DD</color>
<color name="link_blue_pressed">#0082C6</color>
<color name="private_browsing_purple">#CF68FF</color>
<color name="placeholder_active_grey">#222222</color>

View File

@ -281,6 +281,14 @@
<item name="android:textSize">18sp</item>
</style>
<style name="Widget.Doorhanger.Button" parent="Widget.BaseButton">
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_weight">1</item>
<item name="android:minHeight">48dp</item>
<item name="android:textSize">14sp</item>
</style>
<!--
TextAppearance
Note: Gecko uses light theme as default, while Android uses dark.

View File

@ -202,8 +202,8 @@ public class SiteIdentityPopup extends AnchoredPopup implements GeckoEventListen
final DoorhangerConfig config = new DoorhangerConfig(DoorHanger.Type.LOGIN, buttonClickListener);
// Set buttons.
config.appendButton(mContext.getString(R.string.button_cancel), ButtonType.CANCEL.ordinal());
config.appendButton(mContext.getString(R.string.button_copy), ButtonType.COPY.ordinal());
config.setButton(mContext.getString(R.string.button_cancel), ButtonType.CANCEL.ordinal(), false);
config.setButton(mContext.getString(R.string.button_copy), ButtonType.COPY.ordinal(), true);
// Set message.
String username = ((JSONObject) logins.get(0)).getString("username");
@ -361,10 +361,10 @@ public class SiteIdentityPopup extends AnchoredPopup implements GeckoEventListen
private void addNotificationButtons(DoorhangerConfig config, boolean blocked) {
if (blocked) {
config.appendButton(mContext.getString(R.string.disable_protection), ButtonType.DISABLE.ordinal());
config.appendButton(mContext.getString(R.string.keep_blocking), ButtonType.KEEP_BLOCKING.ordinal());
config.setButton(mContext.getString(R.string.disable_protection), ButtonType.DISABLE.ordinal(), false);
config.setButton(mContext.getString(R.string.keep_blocking), ButtonType.KEEP_BLOCKING.ordinal(), true);
} else {
config.appendButton(mContext.getString(R.string.enable_protection), ButtonType.ENABLE.ordinal());
config.setButton(mContext.getString(R.string.enable_protection), ButtonType.ENABLE.ordinal(), true);
}
}

View File

@ -69,7 +69,7 @@ public class DefaultDoorHanger extends DoorHanger {
addLink(link.label, link.url, link.delimiter);
}
setButtons(config);
addButtonsToLayout(config);
}
@Override

View File

@ -7,15 +7,12 @@ package org.mozilla.gecko.widget;
import android.content.Context;
import android.content.res.Resources;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewStub;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.gecko.R;
@ -39,17 +36,13 @@ public abstract class DoorHanger extends LinearLayout {
public void onButtonClick(JSONObject response, DoorHanger doorhanger);
}
protected static final LayoutParams sButtonParams;
static {
sButtonParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1.0f);
}
private static final String LOGTAG = "GeckoDoorHanger";
// Divider between doorhangers.
private final View mDivider;
protected final LinearLayout mButtonsContainer;
private final Button mNegativeButton;
private final Button mPositiveButton;
protected final OnButtonClickListener mOnButtonClickListener;
// The tab this doorhanger is associated with.
@ -89,7 +82,8 @@ public abstract class DoorHanger extends LinearLayout {
mDivider = findViewById(R.id.divider_doorhanger);
mIcon = (ImageView) findViewById(R.id.doorhanger_icon);
mButtonsContainer = (LinearLayout) findViewById(R.id.doorhanger_buttons);
mNegativeButton = (Button) findViewById(R.id.doorhanger_button_negative);
mPositiveButton = (Button) findViewById(R.id.doorhanger_button_positive);
mOnButtonClickListener = config.getButtonClickListener();
mDividerColor = mResources.getColor(R.color.divider_light);
@ -113,17 +107,21 @@ public abstract class DoorHanger extends LinearLayout {
}
}
protected void setButtons(DoorhangerConfig config) {
final JSONArray buttons = config.getButtons();
for (int i = 0; i < buttons.length(); i++) {
try {
final JSONObject buttonObject = buttons.getJSONObject(i);
final String label = buttonObject.getString("label");
final int callbackId = buttonObject.getInt("callback");
addButtonToLayout(label, callbackId);
} catch (JSONException e) {
Log.e(LOGTAG, "Error creating doorhanger button", e);
}
protected void addButtonsToLayout(DoorhangerConfig config) {
final DoorhangerConfig.ButtonConfig negativeButtonConfig = config.getNegativeButtonConfig();
final DoorhangerConfig.ButtonConfig positiveButtonConfig = config.getPositiveButtonConfig();
if (negativeButtonConfig != null) {
mNegativeButton.setText(negativeButtonConfig.label);
mNegativeButton.setOnClickListener(makeOnButtonClickListener(negativeButtonConfig.callback));
mNegativeButton.setVisibility(VISIBLE);
}
if (positiveButtonConfig != null) {
mPositiveButton.setText(positiveButtonConfig.label);
mPositiveButton.setOnClickListener(makeOnButtonClickListener(positiveButtonConfig.callback));
mPositiveButton.setVisibility(VISIBLE);
// TODO: set positive button click listener for LoginDoorhanger callback
}
}
@ -148,37 +146,6 @@ public abstract class DoorHanger extends LinearLayout {
mIcon.setVisibility(View.VISIBLE);
}
/**
* Creates and adds a button into the DoorHanger.
* @param text Button text
* @param id Identifier associated with the button
*/
private void addButtonToLayout(String text, int id) {
final Button button = createButtonInstance(text, id);
if (mButtonsContainer.getChildCount() == 0) {
// If this is the first button we're adding, make the choices layout visible.
mButtonsContainer.setVisibility(View.VISIBLE);
// Make the divider above the buttons visible.
View divider = findViewById(R.id.divider_buttons);
divider.setVisibility(View.VISIBLE);
} else {
// Add a vertical divider between additional buttons.
Divider divider = new Divider(getContext(), null);
divider.setOrientation(Divider.Orientation.VERTICAL);
divider.setBackgroundColor(mDividerColor);
mButtonsContainer.addView(divider);
}
mButtonsContainer.addView(button, sButtonParams);
}
protected Button createButtonInstance(String text, int id) {
final Button button = (Button) LayoutInflater.from(getContext()).inflate(R.layout.doorhanger_button, null);
button.setText(text);
button.setOnClickListener(makeOnButtonClickListener(id));
return button;
}
protected abstract OnClickListener makeOnButtonClickListener(final int id);
/*

View File

@ -5,9 +5,6 @@
package org.mozilla.gecko.widget;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.gecko.widget.DoorHanger.Type;
@ -26,6 +23,15 @@ public class DoorhangerConfig {
}
}
public static class ButtonConfig {
public final String label;
public final int callback;
public ButtonConfig(String label, int callback) {
this.label = label;
this.callback = callback;
}
}
private static final String LOGTAG = "DoorhangerConfig";
private final int tabId;
@ -35,7 +41,8 @@ public class DoorhangerConfig {
private String message;
private JSONObject options;
private Link link;
private JSONArray buttons = new JSONArray();
private ButtonConfig positiveButtonConfig;
private ButtonConfig negativeButtonConfig;
public DoorhangerConfig(Type type, DoorHanger.OnButtonClickListener listener) {
// XXX: This should only be used by SiteIdentityPopup doorhangers which
@ -79,39 +86,27 @@ public class DoorhangerConfig {
return options;
}
/**
* Add buttons from JSON to the Config object.
* @param buttons JSONArray of JSONObjects of the form { label: <label>, callback: <callback_id> }
*/
public void appendButtonsFromJSON(JSONArray buttons) {
try {
for (int i = 0; i < buttons.length(); i++) {
this.buttons.put(buttons.get(i));
}
} catch (JSONException e) {
Log.e(LOGTAG, "Error parsing buttons from JSON", e);
public void setButton(String label, int callbackId, boolean isPositive) {
final ButtonConfig buttonConfig = new ButtonConfig(label, callbackId);
if (isPositive) {
positiveButtonConfig = buttonConfig;
} else {
negativeButtonConfig = buttonConfig;
}
}
public void appendButton(String label, int callbackId) {
final JSONObject button = new JSONObject();
try {
button.put("label", label);
button.put("callback", callbackId);
this.buttons.put(button);
} catch (JSONException e) {
Log.e(LOGTAG, "Error creating button", e);
}
public ButtonConfig getPositiveButtonConfig() {
return positiveButtonConfig;
}
public ButtonConfig getNegativeButtonConfig() {
return negativeButtonConfig;
}
public DoorHanger.OnButtonClickListener getButtonClickListener() {
return this.buttonClickListener;
}
public JSONArray getButtons() {
return buttons;
}
public void setLink(String label, String url, String delimiter) {
this.link = new Link(label, url, delimiter);
}

View File

@ -7,8 +7,6 @@ package org.mozilla.gecko.widget;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
@ -29,7 +27,6 @@ import ch.boye.httpclientandroidlib.util.TextUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONArray;
import org.mozilla.gecko.AppConstants;
import org.mozilla.gecko.R;
import org.mozilla.gecko.favicons.Favicons;
import org.mozilla.gecko.favicons.OnFaviconLoadedListener;
@ -42,6 +39,7 @@ public class LoginDoorHanger extends DoorHanger {
private final TextView mTitle;
private final TextView mMessage;
private final TextView mLink;
// TODO: Fix callback for pos/neg button.
private int mCallbackID;
public LoginDoorHanger(Context context, DoorhangerConfig config) {
@ -65,7 +63,7 @@ public class LoginDoorHanger extends DoorHanger {
protected void loadConfig(DoorhangerConfig config) {
setOptions(config.getOptions());
setMessage(config.getMessage());
setButtons(config);
addButtonsToLayout(config);
}
@Override
@ -105,13 +103,6 @@ public class LoginDoorHanger extends DoorHanger {
addActionText(actionText);
}
@Override
protected Button createButtonInstance(final String text, final int id) {
// HACK: Confirm button will the the rightmost/last button added. Bug 1147064 should add differentiation of the two.
mCallbackID = id;
return super.createButtonInstance(text, id);
}
@Override
protected OnClickListener makeOnButtonClickListener(final int id) {
return new Button.OnClickListener() {