Bug 751205 - (Part 3) Factor out arrow/anchor positioning code to ArrowPopup. r=wesj

This commit is contained in:
Margaret Leibovic 2013-06-20 08:06:15 -07:00
parent 2e234e82b0
commit 3a3887bdc7
5 changed files with 77 additions and 69 deletions

View File

@ -20,6 +20,8 @@ import org.mozilla.gecko.util.UiAsyncTask;
import org.mozilla.gecko.PrefsHelper;
import org.json.JSONObject;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
@ -291,7 +293,14 @@ public class BrowserToolbar implements Tabs.OnTabsChangedListener,
if (mSiteSecurity.getVisibility() != View.VISIBLE)
return;
mActivity.getSiteIdentityPopup().show(mSiteSecurity);
JSONObject identityData = Tabs.getInstance().getSelectedTab().getIdentityData();
if (identityData == null) {
Log.e(LOGTAG, "Selected tab has no identity data");
return;
}
SiteIdentityPopup siteIdentityPopup = mActivity.getSiteIdentityPopup();
siteIdentityPopup.updateIdentity(identityData);
siteIdentityPopup.show();
}
};
@ -304,6 +313,7 @@ public class BrowserToolbar implements Tabs.OnTabsChangedListener,
mSiteSecurity = (ImageButton) mLayout.findViewById(R.id.site_security);
mSiteSecurity.setOnClickListener(faviconListener);
mSiteSecurityVisible = (mSiteSecurity.getVisibility() == View.VISIBLE);
mActivity.getSiteIdentityPopup().setAnchor(mSiteSecurity);
mProgressSpinner = (AnimationDrawable) mActivity.getResources().getDrawable(R.drawable.progress_spinner);

View File

@ -6,7 +6,6 @@
package org.mozilla.gecko;
import org.mozilla.gecko.util.GeckoEventListener;
import org.mozilla.gecko.util.HardwareUtils;
import org.mozilla.gecko.widget.ArrowPopup;
import org.json.JSONArray;
@ -14,9 +13,7 @@ import org.json.JSONObject;
import android.os.Build;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.RelativeLayout;
import java.util.HashSet;
@ -24,15 +21,12 @@ public class DoorHangerPopup extends ArrowPopup
implements GeckoEventListener, Tabs.OnTabsChangedListener {
private static final String LOGTAG = "GeckoDoorHangerPopup";
private View mAnchor;
// Stores a set of all active DoorHanger notifications. A DoorHanger is
// uniquely identified by its tabId and value.
private HashSet<DoorHanger> mDoorHangers;
DoorHangerPopup(GeckoApp aActivity, View aAnchor) {
super(aActivity);
mAnchor = aAnchor;
super(aActivity, aAnchor);
mDoorHangers = new HashSet<DoorHanger>();
@ -47,10 +41,6 @@ public class DoorHangerPopup extends ArrowPopup
Tabs.unregisterOnTabsChangedListener(this);
}
void setAnchor(View aAnchor) {
mAnchor = aAnchor;
}
@Override
public void handleMessage(String event, JSONObject geckoObject) {
try {
@ -236,10 +226,6 @@ public class DoorHangerPopup extends ArrowPopup
return;
}
int[] anchorLocation = new int[2];
if (mAnchor != null)
mAnchor.getLocationInWindow(anchorLocation);
// Make the popup focusable for accessibility. This gets done here
// so the node can be accessibility focused, but on pre-ICS devices this
// causes crashes, so it is done after the popup is shown.
@ -247,18 +233,7 @@ public class DoorHangerPopup extends ArrowPopup
setFocusable(true);
}
// If there's no anchor or the anchor is out of the window bounds,
// just show the popup at the top of the gecko app view.
if (mAnchor == null || anchorLocation[1] < 0) {
showAtLocation(mActivity.getView(), Gravity.TOP, 0, 0);
} else {
// On tablets, we need to position the popup so that the center of the arrow points to the
// center of the anchor view. On phones the popup stretches across the entire screen, so the
// arrow position is determined by its left margin.
int offset = HardwareUtils.isTablet() ? mAnchor.getWidth()/2 - mArrowWidth/2 -
((RelativeLayout.LayoutParams) mArrow.getLayoutParams()).leftMargin : 0;
showAsDropDown(mAnchor, offset, -mYOffset);
}
show();
if (Build.VERSION.SDK_INT < 14) {
// Make the popup focusable for keyboard accessibility.

View File

@ -4,7 +4,6 @@
package org.mozilla.gecko;
import org.mozilla.gecko.util.HardwareUtils;
import org.mozilla.gecko.widget.ArrowPopup;
import org.json.JSONException;
@ -16,7 +15,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
/**
@ -40,7 +38,7 @@ public class SiteIdentityPopup extends ArrowPopup {
private ImageView mLarry;
SiteIdentityPopup(BrowserApp aActivity) {
super(aActivity);
super(aActivity, null);
mResources = aActivity.getResources();
}
@ -63,19 +61,10 @@ public class SiteIdentityPopup extends ArrowPopup {
mLarry = (ImageView) layout.findViewById(R.id.larry);
}
public void show(View v) {
Tab selectedTab = Tabs.getInstance().getSelectedTab();
if (selectedTab == null) {
Log.e(LOGTAG, "Selected tab is null");
return;
}
JSONObject identityData = selectedTab.getIdentityData();
if (identityData == null) {
Log.e(LOGTAG, "Tab has no identity data");
return;
}
/*
* @param identityData A JSONObject that holds the current tab's identity data.
*/
public void updateIdentity(JSONObject identityData) {
String mode;
try {
mode = identityData.getString("mode");
@ -124,22 +113,5 @@ public class SiteIdentityPopup extends ArrowPopup {
mHost.setTextColor(mResources.getColor(R.color.identity_identified));
mOwner.setTextColor(mResources.getColor(R.color.identity_identified));
}
int[] anchorLocation = new int[2];
v.getLocationOnScreen(anchorLocation);
int arrowWidth = mResources.getDimensionPixelSize(R.dimen.menu_popup_arrow_width);
int leftMargin = anchorLocation[0] + (v.getWidth() - arrowWidth) / 2;
int offset = 0;
if (HardwareUtils.isTablet()) {
int popupWidth = mResources.getDimensionPixelSize(R.dimen.doorhanger_width);
offset = 0 - popupWidth + arrowWidth*3/2 + v.getWidth()/2;
}
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) mArrow.getLayoutParams();
layoutParams.setMargins(leftMargin, 0, 0, 0);
showAsDropDown(v, offset, -mYOffset);
}
}

View File

@ -22,7 +22,7 @@
<ImageView android:id="@+id/arrow"
android:layout_width="@dimen/menu_popup_arrow_width"
android:layout_height="12dip"
android:layout_marginLeft="4dip"
android:layout_marginLeft="20dip"
android:layout_alignParentTop="true"
android:src="@drawable/menu_popup_arrow_top"
android:scaleType="fitXY"/>

View File

@ -10,6 +10,7 @@ import org.mozilla.gecko.R;
import org.mozilla.gecko.util.HardwareUtils;
import android.graphics.drawable.BitmapDrawable;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -19,26 +20,34 @@ import android.widget.PopupWindow;
import android.widget.RelativeLayout;
public class ArrowPopup extends PopupWindow {
protected GeckoApp mActivity;
protected boolean mInflated;
protected final GeckoApp mActivity;
private View mAnchor;
private ImageView mArrow;
private int mArrowWidth;
private int mYOffset;
protected LinearLayout mContent;
protected ImageView mArrow;
protected boolean mInflated;
protected int mArrowWidth;
protected int mYOffset;
public ArrowPopup(GeckoApp aActivity) {
public ArrowPopup(GeckoApp aActivity, View aAnchor) {
super(aActivity);
mActivity = aActivity;
mAnchor = aAnchor;
mInflated = false;
mArrowWidth = aActivity.getResources().getDimensionPixelSize(R.dimen.menu_popup_arrow_width);
mYOffset = aActivity.getResources().getDimensionPixelSize(R.dimen.menu_popup_offset);
setAnimationStyle(R.style.PopupAnimation);
}
public void setAnchor(View aAnchor) {
mAnchor = aAnchor;
}
protected void init() {
setBackgroundDrawable(new BitmapDrawable());
setOutsideTouchable(true);
@ -55,4 +64,46 @@ public class ArrowPopup extends PopupWindow {
mInflated = true;
}
/*
* Shows the popup with the arrow pointing to the center of the anchor view. If an anchor hasn't
* been set or isn't visible, the popup will just be shown at the top of the gecko app view.
*/
public void show() {
int[] anchorLocation = new int[2];
if (mAnchor != null)
mAnchor.getLocationInWindow(anchorLocation);
// If there's no anchor or the anchor is out of the window bounds,
// just show the popup at the top of the gecko app view.
if (mAnchor == null || anchorLocation[1] < 0) {
showAtLocation(mActivity.getView(), Gravity.TOP, 0, 0);
return;
}
// Remove padding from the width of the anchor when calculating the arrow offset.
int anchorWidth = mAnchor.getWidth() - mAnchor.getPaddingLeft() - mAnchor.getPaddingRight();
// This is the difference between the edge of the anchor view and the edge of the arrow view.
// We're making an assumption here that the anchor view is wider than the arrow view.
int arrowOffset = (anchorWidth - mArrowWidth)/2 + mAnchor.getPaddingLeft();
// The horizontal offset of the popup window, relative to the left side of the anchor view.
int offset = 0;
RelativeLayout.LayoutParams arrowLayoutParams = (RelativeLayout.LayoutParams) mArrow.getLayoutParams();
if (HardwareUtils.isTablet()) {
// On tablets, the popup has a fixed width, so we use a horizontal offset to position it.
// The arrow's left margin is set by the arrow_popup.xml layout file.
// This assumes that anchor is not too close to the right side of the screen.
offset = arrowOffset - arrowLayoutParams.leftMargin;
} else {
// On phones, the popup takes up the width of the screen, so we set the arrow's left
// margin to make it line up with the anchor.
int leftMargin = anchorLocation[0] + arrowOffset;
arrowLayoutParams.setMargins(leftMargin, 0, 0, 0);
}
showAsDropDown(mAnchor, offset, -mYOffset);
}
}