OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.chrome.browser.photo_picker; |
| 6 |
| 7 import android.app.Activity; |
| 8 import android.content.Context; |
| 9 import android.graphics.Rect; |
| 10 import android.support.v7.widget.GridLayoutManager; |
| 11 import android.support.v7.widget.RecyclerView; |
| 12 import android.support.v7.widget.Toolbar.OnMenuItemClickListener; |
| 13 import android.util.AttributeSet; |
| 14 import android.view.LayoutInflater; |
| 15 import android.view.MenuItem; |
| 16 import android.view.View; |
| 17 import android.widget.RelativeLayout; |
| 18 |
| 19 import org.chromium.chrome.R; |
| 20 import org.chromium.chrome.browser.widget.selection.SelectableListLayout; |
| 21 import org.chromium.chrome.browser.widget.selection.SelectionDelegate; |
| 22 import org.chromium.ui.PhotoPickerListener; |
| 23 |
| 24 import java.util.ArrayList; |
| 25 import java.util.List; |
| 26 |
| 27 /** |
| 28 * A class for keeping track of common data associated with showing photos in |
| 29 * the photo picker, for example the RecyclerView and the bitmap caches. |
| 30 */ |
| 31 public class PickerCategoryView extends RelativeLayout implements OnMenuItemClic
kListener { |
| 32 // The dialog that owns us. |
| 33 private PhotoPickerDialog mDialog; |
| 34 |
| 35 // The view containing the RecyclerView and the toolbar, etc. |
| 36 private SelectableListLayout<PickerBitmap> mSelectableListLayout; |
| 37 |
| 38 // Our context. |
| 39 private Context mContext; |
| 40 |
| 41 // The list of images on disk, sorted by last-modified first. |
| 42 private List<PickerBitmap> mPickerBitmaps; |
| 43 |
| 44 // True if multi-selection is allowed in the picker. |
| 45 private boolean mMultiSelectionAllowed; |
| 46 |
| 47 // The callback to notify the listener of decisions reached in the picker. |
| 48 private PhotoPickerListener mListener; |
| 49 |
| 50 // The RecyclerView showing the images. |
| 51 private RecyclerView mRecyclerView; |
| 52 |
| 53 // The {@link PickerAdapter} for the RecyclerView. |
| 54 private PickerAdapter mPickerAdapter; |
| 55 |
| 56 // The {@link SelectionDelegate} keeping track of which images are selected. |
| 57 private SelectionDelegate<PickerBitmap> mSelectionDelegate; |
| 58 |
| 59 /** |
| 60 * The number of columns to show. Note: mColumns and mPadding (see below) sh
ould both be even |
| 61 * numbers or both odd, not a mix (the column padding will not be of uniform
thickness if they |
| 62 * are a mix). |
| 63 */ |
| 64 private int mColumns; |
| 65 |
| 66 // The padding between columns. See also comment for mColumns. |
| 67 private int mPadding; |
| 68 |
| 69 // The size of the bitmaps (equal length for width and height). |
| 70 private int mImageSize; |
| 71 |
| 72 public PickerCategoryView(Context context) { |
| 73 super(context); |
| 74 postConstruction(context); |
| 75 } |
| 76 |
| 77 public PickerCategoryView(Context context, AttributeSet attrs) { |
| 78 super(context, attrs); |
| 79 postConstruction(context); |
| 80 } |
| 81 |
| 82 public PickerCategoryView(Context context, AttributeSet attrs, int defStyle)
{ |
| 83 super(context, attrs, defStyle); |
| 84 postConstruction(context); |
| 85 } |
| 86 |
| 87 /** |
| 88 * A helper function for initializing the PickerCategoryView. |
| 89 * @param context The context to use. |
| 90 */ |
| 91 @SuppressWarnings("unchecked") // mSelectableListLayout |
| 92 private void postConstruction(Context context) { |
| 93 mContext = context; |
| 94 |
| 95 mSelectionDelegate = new SelectionDelegate<PickerBitmap>(); |
| 96 |
| 97 View root = LayoutInflater.from(context).inflate(R.layout.photo_picker_d
ialog, this); |
| 98 mSelectableListLayout = |
| 99 (SelectableListLayout<PickerBitmap>) root.findViewById(R.id.sele
ctable_list); |
| 100 |
| 101 mPickerAdapter = new PickerAdapter(this); |
| 102 mRecyclerView = mSelectableListLayout.initializeRecyclerView(mPickerAdap
ter); |
| 103 mSelectableListLayout.initializeToolbar(R.layout.photo_picker_toolbar, m
SelectionDelegate, |
| 104 R.string.photo_picker_select_images, null, R.id.photo_picker_nor
mal_menu_group, |
| 105 R.id.photo_picker_selection_mode_menu_group, R.color.default_pri
mary_color, false, |
| 106 this); |
| 107 |
| 108 Rect appRect = new Rect(); |
| 109 ((Activity) context).getWindow().getDecorView().getWindowVisibleDisplayF
rame(appRect); |
| 110 calculateGridMetrics(appRect.width()); |
| 111 |
| 112 RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(mConte
xt, mColumns); |
| 113 mRecyclerView.setHasFixedSize(true); |
| 114 mRecyclerView.setLayoutManager(mLayoutManager); |
| 115 // TODO(finnur): Implement grid spacing. |
| 116 // TODO(finnur): Implement caching. |
| 117 // TODO(finnur): Remove this once the decoder service is in place. |
| 118 prepareBitmaps(); |
| 119 } |
| 120 |
| 121 /** |
| 122 * Initializes the PickerCategoryView object. |
| 123 * @param dialog The dialog showing us. |
| 124 * @param listener The listener who should be notified of actions. |
| 125 * @param multiSelectionAllowed Whether to allow the user to select more tha
n one image. |
| 126 */ |
| 127 public void initialize( |
| 128 PhotoPickerDialog dialog, PhotoPickerListener listener, boolean mult
iSelectionAllowed) { |
| 129 // TODO(finnur): Change selection delegate to support single-selection. |
| 130 |
| 131 mDialog = dialog; |
| 132 mMultiSelectionAllowed = multiSelectionAllowed; |
| 133 mListener = listener; |
| 134 } |
| 135 |
| 136 // OnMenuItemClickListener: |
| 137 |
| 138 @Override |
| 139 public boolean onMenuItemClick(MenuItem item) { |
| 140 if (item.getItemId() == R.id.close_menu_id) { |
| 141 mListener.onPickerUserAction(PhotoPickerListener.Action.CANCEL, null
); |
| 142 mDialog.dismiss(); |
| 143 return true; |
| 144 } else if (item.getItemId() == R.id.selection_mode_done_menu_id) { |
| 145 notifyPhotosSelected(); |
| 146 mDialog.dismiss(); |
| 147 return true; |
| 148 } |
| 149 return false; |
| 150 } |
| 151 |
| 152 // Simple accessors: |
| 153 |
| 154 public int getImageSize() { |
| 155 return mImageSize; |
| 156 } |
| 157 |
| 158 public SelectionDelegate<PickerBitmap> getSelectionDelegate() { |
| 159 return mSelectionDelegate; |
| 160 } |
| 161 |
| 162 public List<PickerBitmap> getPickerBitmaps() { |
| 163 return mPickerBitmaps; |
| 164 } |
| 165 |
| 166 public boolean isMultiSelectAllowed() { |
| 167 return mMultiSelectionAllowed; |
| 168 } |
| 169 |
| 170 /** |
| 171 * Notifies the listener that the user selected to launch the gallery. |
| 172 */ |
| 173 public void showGallery() { |
| 174 mListener.onPickerUserAction(PhotoPickerListener.Action.LAUNCH_GALLERY,
null); |
| 175 } |
| 176 |
| 177 /** |
| 178 * Notifies the listener that the user selected to launch the camera intent. |
| 179 */ |
| 180 public void showCamera() { |
| 181 mListener.onPickerUserAction(PhotoPickerListener.Action.LAUNCH_CAMERA, n
ull); |
| 182 } |
| 183 |
| 184 /** |
| 185 * Calculates image size and how many columns can fit on-screen. |
| 186 * @param width The total width of the boundary to show the images in. |
| 187 */ |
| 188 private void calculateGridMetrics(int width) { |
| 189 int minSize = |
| 190 mContext.getResources().getDimensionPixelSize(R.dimen.photo_pick
er_tile_min_size); |
| 191 mPadding = mContext.getResources().getDimensionPixelSize(R.dimen.photo_p
icker_tile_gap); |
| 192 mColumns = Math.max(1, (width - mPadding) / (minSize + mPadding)); |
| 193 mImageSize = (width - mPadding * (mColumns + 1)) / (mColumns); |
| 194 |
| 195 // Make sure columns and padding are either both even or both odd. |
| 196 if (((mColumns % 2) == 0) != ((mPadding % 2) == 0)) { |
| 197 mPadding++; |
| 198 } |
| 199 } |
| 200 |
| 201 /** |
| 202 * Prepares bitmaps for loading. |
| 203 */ |
| 204 private void prepareBitmaps() { |
| 205 // TODO(finnur): Use worker thread to fetch bitmaps instead of hard-codi
ng. |
| 206 mPickerBitmaps = new ArrayList<>(); |
| 207 mPickerBitmaps.add(0, new PickerBitmap("", 0, PickerBitmap.GALLERY)); |
| 208 mPickerBitmaps.add(0, new PickerBitmap("", 0, PickerBitmap.CAMERA)); |
| 209 mPickerBitmaps.add(new PickerBitmap("foo/bar1.jpg", 1, PickerBitmap.PICT
URE)); |
| 210 mPickerBitmaps.add(new PickerBitmap("foo/bar2.jpg", 2, PickerBitmap.PICT
URE)); |
| 211 mPickerBitmaps.add(new PickerBitmap("foo/bar3.jpg", 3, PickerBitmap.PICT
URE)); |
| 212 mPickerBitmaps.add(new PickerBitmap("foo/bar4.jpg", 4, PickerBitmap.PICT
URE)); |
| 213 mPickerAdapter.notifyDataSetChanged(); |
| 214 } |
| 215 |
| 216 /** |
| 217 * Notifies any listeners that one or more photos have been selected. |
| 218 */ |
| 219 private void notifyPhotosSelected() { |
| 220 List<PickerBitmap> selectedFiles = mSelectionDelegate.getSelectedItems()
; |
| 221 String[] photos = new String[selectedFiles.size()]; |
| 222 int i = 0; |
| 223 for (PickerBitmap bitmap : selectedFiles) { |
| 224 photos[i++] = bitmap.getFilePath(); |
| 225 } |
| 226 |
| 227 mListener.onPickerUserAction(PhotoPickerListener.Action.PHOTOS_SELECTED,
photos); |
| 228 } |
| 229 } |
OLD | NEW |