1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- 2 * This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 package org.mozilla.gecko.home; 7 8 import org.mozilla.gecko.R; 9 import org.mozilla.gecko.home.PanelLayout.DatasetBacked; 10 import org.mozilla.gecko.home.PanelLayout.PanelView; 11 import org.mozilla.gecko.widget.RecyclerViewClickSupport; 12 import org.mozilla.gecko.widget.RecyclerViewClickSupport.OnItemClickListener; 13 import org.mozilla.gecko.widget.RecyclerViewClickSupport.OnItemLongClickListener; 14 15 import android.annotation.SuppressLint; 16 import android.content.Context; 17 import android.content.res.Resources; 18 import android.database.Cursor; 19 import android.support.v7.widget.GridLayoutManager; 20 import android.support.v7.widget.RecyclerView; 21 import android.view.View; 22 23 /** 24 * RecyclerView implementation for grid home panels. 25 */ 26 @SuppressLint("ViewConstructor") // View is only created from code 27 public class PanelRecyclerView extends RecyclerView 28 implements DatasetBacked, PanelView, OnItemClickListener, OnItemLongClickListener { 29 private final PanelRecyclerViewAdapter adapter; 30 private final GridLayoutManager layoutManager; 31 private final PanelViewItemHandler itemHandler; 32 private final float columnWidth; 33 private final boolean autoFit; 34 private final HomeConfig.ViewConfig viewConfig; 35 36 private PanelLayout.OnItemOpenListener itemOpenListener; 37 private HomeContextMenuInfo contextMenuInfo; 38 private HomeContextMenuInfo.Factory contextMenuInfoFactory; 39 PanelRecyclerView(Context context, HomeConfig.ViewConfig viewConfig)40 public PanelRecyclerView(Context context, HomeConfig.ViewConfig viewConfig) { 41 super(context); 42 43 this.viewConfig = viewConfig; 44 45 final Resources resources = context.getResources(); 46 47 int spanCount; 48 if (viewConfig.getItemType() == HomeConfig.ItemType.ICON) { 49 autoFit = false; 50 spanCount = getResources().getInteger(R.integer.panel_icon_grid_view_columns); 51 } else { 52 autoFit = true; 53 spanCount = 1; 54 } 55 56 columnWidth = resources.getDimension(R.dimen.panel_grid_view_column_width); 57 layoutManager = new GridLayoutManager(context, spanCount); 58 adapter = new PanelRecyclerViewAdapter(context, viewConfig); 59 itemHandler = new PanelViewItemHandler(); 60 61 layoutManager.setSpanSizeLookup(new PanelSpanSizeLookup()); 62 63 setLayoutManager(layoutManager); 64 setAdapter(adapter); 65 66 int horizontalSpacing = (int) resources.getDimension(R.dimen.panel_grid_view_horizontal_spacing); 67 int verticalSpacing = (int) resources.getDimension(R.dimen.panel_grid_view_vertical_spacing); 68 int outerSpacing = (int) resources.getDimension(R.dimen.panel_grid_view_outer_spacing); 69 70 addItemDecoration(new SpacingDecoration(horizontalSpacing, verticalSpacing)); 71 72 setPadding(outerSpacing, outerSpacing, outerSpacing, outerSpacing); 73 setClipToPadding(false); 74 75 RecyclerViewClickSupport.addTo(this) 76 .setOnItemClickListener(this) 77 .setOnItemLongClickListener(this); 78 } 79 80 @Override onMeasure(int widthSpec, int heightSpec)81 protected void onMeasure(int widthSpec, int heightSpec) { 82 super.onMeasure(widthSpec, heightSpec); 83 84 if (autoFit) { 85 // Adjust span based on space available (What GridView does when you say numColumns="auto_fit") 86 final int spanCount = (int) Math.max(1, getMeasuredWidth() / columnWidth); 87 layoutManager.setSpanCount(spanCount); 88 } 89 } 90 91 @Override onAttachedToWindow()92 public void onAttachedToWindow() { 93 super.onAttachedToWindow(); 94 itemHandler.setOnItemOpenListener(itemOpenListener); 95 } 96 97 @Override onDetachedFromWindow()98 public void onDetachedFromWindow() { 99 super.onDetachedFromWindow(); 100 itemHandler.setOnItemOpenListener(null); 101 } 102 103 @Override setDataset(Cursor cursor)104 public void setDataset(Cursor cursor) { 105 adapter.swapCursor(cursor); 106 } 107 108 @Override setFilterManager(PanelLayout.FilterManager manager)109 public void setFilterManager(PanelLayout.FilterManager manager) { 110 adapter.setFilterManager(manager); 111 itemHandler.setFilterManager(manager); 112 } 113 114 @Override setOnItemOpenListener(PanelLayout.OnItemOpenListener listener)115 public void setOnItemOpenListener(PanelLayout.OnItemOpenListener listener) { 116 itemOpenListener = listener; 117 itemHandler.setOnItemOpenListener(listener); 118 } 119 120 @Override getContextMenuInfo()121 public HomeContextMenuInfo getContextMenuInfo() { 122 return contextMenuInfo; 123 } 124 125 @Override setContextMenuInfoFactory(HomeContextMenuInfo.Factory factory)126 public void setContextMenuInfoFactory(HomeContextMenuInfo.Factory factory) { 127 contextMenuInfoFactory = factory; 128 } 129 130 @Override onItemClicked(RecyclerView recyclerView, int position, View v)131 public void onItemClicked(RecyclerView recyclerView, int position, View v) { 132 if (viewConfig.hasHeaderConfig()) { 133 if (position == 0) { 134 itemOpenListener.onItemOpen(viewConfig.getHeaderConfig().getUrl(), null); 135 return; 136 } 137 138 position--; 139 } 140 141 itemHandler.openItemAtPosition(adapter.getCursor(), position); 142 } 143 144 @Override onItemLongClicked(RecyclerView recyclerView, int position, View v)145 public boolean onItemLongClicked(RecyclerView recyclerView, int position, View v) { 146 if (viewConfig.hasHeaderConfig()) { 147 if (position == 0) { 148 final HomeConfig.HeaderConfig headerConfig = viewConfig.getHeaderConfig(); 149 150 final HomeContextMenuInfo info = new HomeContextMenuInfo(v, position, -1); 151 info.url = headerConfig.getUrl(); 152 info.title = headerConfig.getUrl(); 153 154 contextMenuInfo = info; 155 return showContextMenuForChild(this); 156 } 157 158 position--; 159 } 160 161 Cursor cursor = adapter.getCursor(); 162 cursor.moveToPosition(position); 163 164 contextMenuInfo = contextMenuInfoFactory.makeInfoForCursor(recyclerView, position, -1, cursor); 165 return showContextMenuForChild(this); 166 } 167 168 private class PanelSpanSizeLookup extends GridLayoutManager.SpanSizeLookup { 169 @Override getSpanSize(int position)170 public int getSpanSize(int position) { 171 if (position == 0 && viewConfig.hasHeaderConfig()) { 172 return layoutManager.getSpanCount(); 173 } 174 175 return 1; 176 } 177 } 178 } 179