• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.browser;
17 
18 import android.animation.Animator;
19 import android.animation.Animator.AnimatorListener;
20 import android.animation.AnimatorSet;
21 import android.animation.ObjectAnimator;
22 import android.app.Fragment;
23 import android.app.LoaderManager.LoaderCallbacks;
24 import android.content.ContentResolver;
25 import android.content.ContentUris;
26 import android.content.Context;
27 import android.content.CursorLoader;
28 import android.content.Loader;
29 import android.database.Cursor;
30 import android.graphics.Bitmap;
31 import android.graphics.BitmapFactory;
32 import android.net.Uri;
33 import android.os.Bundle;
34 import android.view.ContextMenu;
35 import android.view.ContextMenu.ContextMenuInfo;
36 import android.view.LayoutInflater;
37 import android.view.MenuInflater;
38 import android.view.MenuItem;
39 import android.view.View;
40 import android.view.View.MeasureSpec;
41 import android.view.ViewGroup;
42 import android.widget.AdapterView;
43 import android.widget.AdapterView.AdapterContextMenuInfo;
44 import android.widget.AdapterView.OnItemClickListener;
45 import android.widget.GridView;
46 import android.widget.ImageView;
47 import android.widget.ResourceCursorAdapter;
48 import android.widget.TextView;
49 
50 import com.android.browser.provider.SnapshotProvider.Snapshots;
51 
52 import java.text.DateFormat;
53 import java.util.Date;
54 
55 public class BrowserSnapshotPage extends Fragment implements
56         LoaderCallbacks<Cursor>, OnItemClickListener {
57 
58     public static final String EXTRA_ANIMATE_ID = "animate_id";
59 
60     private static final int LOADER_SNAPSHOTS = 1;
61     private static final String[] PROJECTION = new String[] {
62         Snapshots._ID,
63         Snapshots.TITLE,
64         Snapshots.VIEWSTATE_SIZE,
65         Snapshots.THUMBNAIL,
66         Snapshots.FAVICON,
67         Snapshots.URL,
68         Snapshots.DATE_CREATED,
69     };
70     private static final int SNAPSHOT_ID = 0;
71     private static final int SNAPSHOT_TITLE = 1;
72     private static final int SNAPSHOT_VIEWSTATE_SIZE = 2;
73     private static final int SNAPSHOT_THUMBNAIL = 3;
74     private static final int SNAPSHOT_FAVICON = 4;
75     private static final int SNAPSHOT_URL = 5;
76     private static final int SNAPSHOT_DATE_CREATED = 6;
77 
78     GridView mGrid;
79     View mEmpty;
80     SnapshotAdapter mAdapter;
81     CombinedBookmarksCallbacks mCallback;
82     long mAnimateId;
83 
84     @Override
onCreate(Bundle savedInstanceState)85     public void onCreate(Bundle savedInstanceState) {
86         super.onCreate(savedInstanceState);
87         mCallback = (CombinedBookmarksCallbacks) getActivity();
88         mAnimateId = getArguments().getLong(EXTRA_ANIMATE_ID);
89     }
90 
91     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)92     public View onCreateView(LayoutInflater inflater, ViewGroup container,
93             Bundle savedInstanceState) {
94         View view = inflater.inflate(R.layout.snapshots, container, false);
95         mEmpty = view.findViewById(android.R.id.empty);
96         mGrid = (GridView) view.findViewById(R.id.grid);
97         setupGrid(inflater);
98         getLoaderManager().initLoader(LOADER_SNAPSHOTS, null, this);
99         return view;
100     }
101 
102     @Override
onDestroyView()103     public void onDestroyView() {
104         super.onDestroyView();
105         getLoaderManager().destroyLoader(LOADER_SNAPSHOTS);
106         if (mAdapter != null) {
107             mAdapter.changeCursor(null);
108             mAdapter = null;
109         }
110     }
111 
setupGrid(LayoutInflater inflater)112     void setupGrid(LayoutInflater inflater) {
113         View item = inflater.inflate(R.layout.snapshot_item, mGrid, false);
114         int mspec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
115         item.measure(mspec, mspec);
116         int width = item.getMeasuredWidth();
117         mGrid.setColumnWidth(width);
118         mGrid.setOnItemClickListener(this);
119         mGrid.setOnCreateContextMenuListener(this);
120     }
121 
122     @Override
onCreateLoader(int id, Bundle args)123     public Loader<Cursor> onCreateLoader(int id, Bundle args) {
124         if (id == LOADER_SNAPSHOTS) {
125             return new CursorLoader(getActivity(),
126                     Snapshots.CONTENT_URI, PROJECTION,
127                     null, null, Snapshots.DATE_CREATED + " DESC");
128         }
129         return null;
130     }
131 
132     @Override
onLoadFinished(Loader<Cursor> loader, Cursor data)133     public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
134         if (loader.getId() == LOADER_SNAPSHOTS) {
135             if (mAdapter == null) {
136                 mAdapter = new SnapshotAdapter(getActivity(), data);
137                 mGrid.setAdapter(mAdapter);
138             } else {
139                 mAdapter.changeCursor(data);
140             }
141             if (mAnimateId > 0) {
142                 mAdapter.animateIn(mAnimateId);
143                 mAnimateId = 0;
144                 getArguments().remove(EXTRA_ANIMATE_ID);
145             }
146             boolean empty = mAdapter.isEmpty();
147             mGrid.setVisibility(empty ? View.GONE : View.VISIBLE);
148             mEmpty.setVisibility(empty ? View.VISIBLE : View.GONE);
149         }
150     }
151 
152     @Override
onLoaderReset(Loader<Cursor> loader)153     public void onLoaderReset(Loader<Cursor> loader) {
154     }
155 
156     @Override
onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)157     public void onCreateContextMenu(ContextMenu menu, View v,
158             ContextMenuInfo menuInfo) {
159         MenuInflater inflater = getActivity().getMenuInflater();
160         inflater.inflate(R.menu.snapshots_context, menu);
161         // Create the header, re-use BookmarkItem (has the layout we want)
162         BookmarkItem header = new BookmarkItem(getActivity());
163         header.setEnableScrolling(true);
164         AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
165         populateBookmarkItem(mAdapter.getItem(info.position), header);
166         menu.setHeaderView(header);
167     }
168 
populateBookmarkItem(Cursor cursor, BookmarkItem item)169     private void populateBookmarkItem(Cursor cursor, BookmarkItem item) {
170         item.setName(cursor.getString(SNAPSHOT_TITLE));
171         item.setUrl(cursor.getString(SNAPSHOT_URL));
172         item.setFavicon(getBitmap(cursor, SNAPSHOT_FAVICON));
173     }
174 
getBitmap(Cursor cursor, int columnIndex)175     static Bitmap getBitmap(Cursor cursor, int columnIndex) {
176         byte[] data = cursor.getBlob(columnIndex);
177         if (data == null) {
178             return null;
179         }
180         return BitmapFactory.decodeByteArray(data, 0, data.length);
181     }
182 
183     @Override
onContextItemSelected(MenuItem item)184     public boolean onContextItemSelected(MenuItem item) {
185         if (item.getItemId() == R.id.delete_context_menu_id) {
186             AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
187             deleteSnapshot(info.id);
188             return true;
189         }
190         return super.onContextItemSelected(item);
191     }
192 
deleteSnapshot(long id)193     void deleteSnapshot(long id) {
194         final Uri uri = ContentUris.withAppendedId(Snapshots.CONTENT_URI, id);
195         final ContentResolver cr = getActivity().getContentResolver();
196         new Thread() {
197             @Override
198             public void run() {
199                 cr.delete(uri, null, null);
200             }
201         }.start();
202 
203     }
204 
205     @Override
onItemClick(AdapterView<?> parent, View view, int position, long id)206     public void onItemClick(AdapterView<?> parent, View view, int position,
207             long id) {
208         mCallback.openSnapshot(id);
209     }
210 
211     private static class SnapshotAdapter extends ResourceCursorAdapter {
212         private long mAnimateId;
213         private AnimatorSet mAnimation;
214         private View mAnimationTarget;
215 
SnapshotAdapter(Context context, Cursor c)216         public SnapshotAdapter(Context context, Cursor c) {
217             super(context, R.layout.snapshot_item, c, 0);
218             mAnimation = new AnimatorSet();
219             mAnimation.playTogether(
220                     ObjectAnimator.ofFloat(null, View.SCALE_X, 0f, 1f),
221                     ObjectAnimator.ofFloat(null, View.SCALE_Y, 0f, 1f));
222             mAnimation.setStartDelay(100);
223             mAnimation.setDuration(400);
224             mAnimation.addListener(new AnimatorListener() {
225 
226                 @Override
227                 public void onAnimationStart(Animator animation) {
228                 }
229 
230                 @Override
231                 public void onAnimationRepeat(Animator animation) {
232                 }
233 
234                 @Override
235                 public void onAnimationEnd(Animator animation) {
236                     mAnimateId = 0;
237                     mAnimationTarget = null;
238                 }
239 
240                 @Override
241                 public void onAnimationCancel(Animator animation) {
242                 }
243             });
244         }
245 
animateIn(long id)246         public void animateIn(long id) {
247             mAnimateId = id;
248         }
249 
250         @Override
bindView(View view, Context context, Cursor cursor)251         public void bindView(View view, Context context, Cursor cursor) {
252             long id = cursor.getLong(SNAPSHOT_ID);
253             if (id == mAnimateId) {
254                 if (mAnimationTarget != view) {
255                     float scale = 0f;
256                     if (mAnimationTarget != null) {
257                         scale = mAnimationTarget.getScaleX();
258                         mAnimationTarget.setScaleX(1f);
259                         mAnimationTarget.setScaleY(1f);
260                     }
261                     view.setScaleX(scale);
262                     view.setScaleY(scale);
263                 }
264                 mAnimation.setTarget(view);
265                 mAnimationTarget = view;
266                 if (!mAnimation.isRunning()) {
267                     mAnimation.start();
268                 }
269 
270             }
271             ImageView thumbnail = (ImageView) view.findViewById(R.id.thumb);
272             byte[] thumbBlob = cursor.getBlob(SNAPSHOT_THUMBNAIL);
273             if (thumbBlob == null) {
274                 thumbnail.setImageResource(R.drawable.browser_thumbnail);
275             } else {
276                 Bitmap thumbBitmap = BitmapFactory.decodeByteArray(
277                         thumbBlob, 0, thumbBlob.length);
278                 thumbnail.setImageBitmap(thumbBitmap);
279             }
280             TextView title = (TextView) view.findViewById(R.id.title);
281             title.setText(cursor.getString(SNAPSHOT_TITLE));
282             TextView size = (TextView) view.findViewById(R.id.size);
283             if (size != null) {
284                 int stateLen = cursor.getInt(SNAPSHOT_VIEWSTATE_SIZE);
285                 size.setText(String.format("%.2fMB", stateLen / 1024f / 1024f));
286             }
287             long timestamp = cursor.getLong(SNAPSHOT_DATE_CREATED);
288             TextView date = (TextView) view.findViewById(R.id.date);
289             DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT);
290             date.setText(dateFormat.format(new Date(timestamp)));
291         }
292 
293         @Override
getItem(int position)294         public Cursor getItem(int position) {
295             return (Cursor) super.getItem(position);
296         }
297     }
298 
299 }
300