2013-06-20 18:45:58 +00:00
|
|
|
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
|
|
|
* 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/. */
|
|
|
|
|
|
|
|
package org.mozilla.gecko.home;
|
|
|
|
|
|
|
|
import org.mozilla.gecko.R;
|
|
|
|
import org.mozilla.gecko.ThumbnailHelper;
|
|
|
|
import android.content.Context;
|
2013-08-02 17:03:21 +00:00
|
|
|
import android.content.res.TypedArray;
|
2013-10-16 15:39:34 +00:00
|
|
|
import android.graphics.Rect;
|
2013-06-20 18:45:58 +00:00
|
|
|
import android.util.AttributeSet;
|
2013-07-22 20:08:38 +00:00
|
|
|
import android.view.ContextMenu.ContextMenuInfo;
|
2013-06-20 18:45:58 +00:00
|
|
|
import android.view.View;
|
|
|
|
import android.widget.AbsListView;
|
|
|
|
import android.widget.GridView;
|
|
|
|
|
|
|
|
/**
|
2013-09-17 20:24:48 +00:00
|
|
|
* A grid view of top and pinned sites.
|
|
|
|
* Each cell in the grid is a TopSitesGridItemView.
|
2013-06-20 18:45:58 +00:00
|
|
|
*/
|
2013-09-17 20:24:48 +00:00
|
|
|
public class TopSitesGridView extends GridView {
|
|
|
|
private static final String LOGTAG = "GeckoTopSitesGridView";
|
2013-06-20 18:45:58 +00:00
|
|
|
|
2013-10-16 17:09:41 +00:00
|
|
|
// Listener for editing pinned sites.
|
|
|
|
public static interface OnEditPinnedSiteListener {
|
2013-11-04 22:39:00 +00:00
|
|
|
public void onEditPinnedSite(int position, String searchTerm);
|
2013-07-22 19:49:36 +00:00
|
|
|
}
|
|
|
|
|
2013-09-17 20:24:48 +00:00
|
|
|
// Max number of top sites that needs to be shown.
|
|
|
|
private final int mMaxSites;
|
2013-06-20 18:45:58 +00:00
|
|
|
|
|
|
|
// Number of columns to show.
|
2013-07-02 21:31:34 +00:00
|
|
|
private final int mNumColumns;
|
2013-06-20 18:45:58 +00:00
|
|
|
|
2013-08-07 16:39:26 +00:00
|
|
|
// Horizontal spacing in between the rows.
|
|
|
|
private final int mHorizontalSpacing;
|
|
|
|
|
|
|
|
// Vertical spacing in between the rows.
|
2013-08-02 17:03:21 +00:00
|
|
|
private final int mVerticalSpacing;
|
|
|
|
|
2013-09-06 23:36:46 +00:00
|
|
|
// Measured width of this view.
|
|
|
|
private int mMeasuredWidth;
|
|
|
|
|
|
|
|
// Measured height of this view.
|
|
|
|
private int mMeasuredHeight;
|
|
|
|
|
2015-06-24 20:25:16 +00:00
|
|
|
// A dummy View used to measure the required size of the child Views.
|
|
|
|
private final TopSitesGridItemView dummyChildView;
|
|
|
|
|
2013-07-22 20:08:38 +00:00
|
|
|
// Context menu info.
|
2013-09-17 20:24:48 +00:00
|
|
|
private TopSitesGridContextMenuInfo mContextMenuInfo;
|
2013-07-22 20:08:38 +00:00
|
|
|
|
2013-10-16 15:39:34 +00:00
|
|
|
// Whether we're handling focus changes or not. This is used
|
|
|
|
// to avoid infinite re-layouts when using this GridView as
|
|
|
|
// a ListView header view (see bug 918044).
|
|
|
|
private boolean mIsHandlingFocusChange;
|
|
|
|
|
2013-09-17 20:24:48 +00:00
|
|
|
public TopSitesGridView(Context context) {
|
2013-06-20 18:45:58 +00:00
|
|
|
this(context, null);
|
|
|
|
}
|
|
|
|
|
2013-09-17 20:24:48 +00:00
|
|
|
public TopSitesGridView(Context context, AttributeSet attrs) {
|
|
|
|
this(context, attrs, R.attr.topSitesGridViewStyle);
|
2013-06-20 18:45:58 +00:00
|
|
|
}
|
|
|
|
|
2013-09-17 20:24:48 +00:00
|
|
|
public TopSitesGridView(Context context, AttributeSet attrs, int defStyle) {
|
2013-06-20 18:45:58 +00:00
|
|
|
super(context, attrs, defStyle);
|
2013-09-17 20:24:48 +00:00
|
|
|
mMaxSites = getResources().getInteger(R.integer.number_of_top_sites);
|
2013-06-20 18:45:58 +00:00
|
|
|
mNumColumns = getResources().getInteger(R.integer.number_of_top_sites_cols);
|
|
|
|
setNumColumns(mNumColumns);
|
2013-08-02 17:03:21 +00:00
|
|
|
|
2013-09-17 20:24:48 +00:00
|
|
|
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TopSitesGridView, defStyle, 0);
|
|
|
|
mHorizontalSpacing = a.getDimensionPixelOffset(R.styleable.TopSitesGridView_android_horizontalSpacing, 0x00);
|
|
|
|
mVerticalSpacing = a.getDimensionPixelOffset(R.styleable.TopSitesGridView_android_verticalSpacing, 0x00);
|
2013-08-02 17:03:21 +00:00
|
|
|
a.recycle();
|
2015-06-24 20:25:16 +00:00
|
|
|
|
|
|
|
dummyChildView = new TopSitesGridItemView(context);
|
|
|
|
// Set a default LayoutParams on the child, if it doesn't have one on its own.
|
|
|
|
AbsListView.LayoutParams params = (AbsListView.LayoutParams) dummyChildView.getLayoutParams();
|
|
|
|
if (params == null) {
|
|
|
|
params = new AbsListView.LayoutParams(AbsListView.LayoutParams.WRAP_CONTENT,
|
|
|
|
AbsListView.LayoutParams.WRAP_CONTENT);
|
|
|
|
dummyChildView.setLayoutParams(params);
|
|
|
|
}
|
2013-06-20 18:45:58 +00:00
|
|
|
}
|
|
|
|
|
2013-10-16 15:39:34 +00:00
|
|
|
@Override
|
|
|
|
protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
|
|
|
|
mIsHandlingFocusChange = true;
|
|
|
|
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
|
|
|
|
mIsHandlingFocusChange = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void requestLayout() {
|
|
|
|
if (!mIsHandlingFocusChange) {
|
|
|
|
super.requestLayout();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-20 18:45:58 +00:00
|
|
|
@Override
|
|
|
|
public int getColumnWidth() {
|
|
|
|
// This method will be called from onMeasure() too.
|
|
|
|
// It's better to use getMeasuredWidth(), as it is safe in this case.
|
2013-08-07 16:39:26 +00:00
|
|
|
final int totalHorizontalSpacing = mNumColumns > 0 ? (mNumColumns - 1) * mHorizontalSpacing : 0;
|
|
|
|
return (getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - totalHorizontalSpacing) / mNumColumns;
|
2013-06-20 18:45:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
|
|
|
// Sets the padding for this view.
|
|
|
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
|
|
|
|
|
|
|
final int measuredWidth = getMeasuredWidth();
|
2013-09-06 23:36:46 +00:00
|
|
|
if (measuredWidth == mMeasuredWidth) {
|
|
|
|
// Return the cached values as the width is the same.
|
|
|
|
setMeasuredDimension(mMeasuredWidth, mMeasuredHeight);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-11-04 19:48:58 +00:00
|
|
|
final int columnWidth = getColumnWidth();
|
2013-06-20 18:45:58 +00:00
|
|
|
|
2013-09-06 23:36:46 +00:00
|
|
|
// Measure the exact width of the child, and the height based on the width.
|
2013-09-17 20:24:48 +00:00
|
|
|
// Note: the child (and TopSitesThumbnailView) takes care of calculating its height.
|
2013-11-04 19:48:58 +00:00
|
|
|
int childWidthSpec = MeasureSpec.makeMeasureSpec(columnWidth, MeasureSpec.EXACTLY);
|
2013-09-06 23:36:46 +00:00
|
|
|
int childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
|
2015-06-24 20:25:16 +00:00
|
|
|
dummyChildView.measure(childWidthSpec, childHeightSpec);
|
|
|
|
final int childHeight = dummyChildView.getMeasuredHeight();
|
2013-06-20 18:45:58 +00:00
|
|
|
|
2013-11-04 19:48:58 +00:00
|
|
|
// This is the maximum width of the contents of each child in the grid.
|
|
|
|
// Use this as the target width for thumbnails.
|
2015-06-24 20:25:16 +00:00
|
|
|
final int thumbnailWidth = dummyChildView.getMeasuredWidth() - dummyChildView.getPaddingLeft() - dummyChildView.getPaddingRight();
|
2013-11-04 19:48:58 +00:00
|
|
|
ThumbnailHelper.getInstance().setThumbnailWidth(thumbnailWidth);
|
|
|
|
|
2013-09-17 20:24:48 +00:00
|
|
|
// Number of rows required to show these top sites.
|
|
|
|
final int rows = (int) Math.ceil((double) mMaxSites / mNumColumns);
|
2013-06-20 18:45:58 +00:00
|
|
|
final int childrenHeight = childHeight * rows;
|
2013-08-02 17:03:21 +00:00
|
|
|
final int totalVerticalSpacing = rows > 0 ? (rows - 1) * mVerticalSpacing : 0;
|
2013-06-20 18:45:58 +00:00
|
|
|
|
|
|
|
// Total height of this view.
|
2013-08-02 17:03:21 +00:00
|
|
|
final int measuredHeight = childrenHeight + getPaddingTop() + getPaddingBottom() + totalVerticalSpacing;
|
2013-06-20 18:45:58 +00:00
|
|
|
setMeasuredDimension(measuredWidth, measuredHeight);
|
2013-09-06 23:36:46 +00:00
|
|
|
mMeasuredWidth = measuredWidth;
|
|
|
|
mMeasuredHeight = measuredHeight;
|
2013-06-20 18:45:58 +00:00
|
|
|
}
|
|
|
|
|
2013-07-22 20:08:38 +00:00
|
|
|
@Override
|
|
|
|
public ContextMenuInfo getContextMenuInfo() {
|
|
|
|
return mContextMenuInfo;
|
|
|
|
}
|
|
|
|
|
2014-11-05 20:14:34 +00:00
|
|
|
public void setContextMenuInfo(TopSitesGridContextMenuInfo contextMenuInfo) {
|
|
|
|
mContextMenuInfo = contextMenuInfo;
|
2013-07-22 19:49:36 +00:00
|
|
|
}
|
|
|
|
|
2013-07-22 20:08:38 +00:00
|
|
|
/**
|
2014-03-12 18:21:24 +00:00
|
|
|
* Stores information regarding the creation of the context menu for a GridView item.
|
2013-07-22 20:08:38 +00:00
|
|
|
*/
|
2014-03-12 18:21:24 +00:00
|
|
|
public static class TopSitesGridContextMenuInfo extends HomeContextMenuInfo {
|
2014-05-07 11:01:20 +00:00
|
|
|
public int type = -1;
|
2013-09-05 18:34:26 +00:00
|
|
|
|
2014-03-12 18:21:24 +00:00
|
|
|
public TopSitesGridContextMenuInfo(View targetView, int position, long id) {
|
2013-07-22 20:08:38 +00:00
|
|
|
super(targetView, position, id);
|
2014-09-13 00:12:33 +00:00
|
|
|
this.itemType = RemoveItemType.HISTORY;
|
2013-09-05 18:34:26 +00:00
|
|
|
}
|
2013-07-22 20:08:38 +00:00
|
|
|
}
|
2013-06-20 18:45:58 +00:00
|
|
|
}
|