BrowserSnapshotPage.java revision 2d963a2899afbe000d1ab498f94de87f25e33184
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 */
16package com.android.browser;
17
18import android.app.Fragment;
19import android.app.LoaderManager.LoaderCallbacks;
20import android.content.ContentResolver;
21import android.content.ContentUris;
22import android.content.Context;
23import android.content.CursorLoader;
24import android.content.Loader;
25import android.database.Cursor;
26import android.graphics.Bitmap;
27import android.graphics.BitmapFactory;
28import android.net.Uri;
29import android.os.Bundle;
30import android.view.ContextMenu;
31import android.view.ContextMenu.ContextMenuInfo;
32import android.view.LayoutInflater;
33import android.view.MenuInflater;
34import android.view.MenuItem;
35import android.view.View;
36import android.view.View.MeasureSpec;
37import android.view.ViewGroup;
38import android.widget.AdapterView;
39import android.widget.AdapterView.AdapterContextMenuInfo;
40import android.widget.AdapterView.OnItemClickListener;
41import android.widget.GridView;
42import android.widget.ImageView;
43import android.widget.ResourceCursorAdapter;
44import android.widget.TextView;
45
46import com.android.browser.provider.SnapshotProvider.Snapshots;
47
48import java.text.DateFormat;
49import java.util.Date;
50
51public class BrowserSnapshotPage extends Fragment implements
52        LoaderCallbacks<Cursor>, OnItemClickListener {
53
54    public static final String EXTRA_ANIMATE_ID = "animate_id";
55
56    private static final int LOADER_SNAPSHOTS = 1;
57    private static final String[] PROJECTION = new String[] {
58        Snapshots._ID,
59        Snapshots.TITLE,
60        "length(" + Snapshots.VIEWSTATE + ")",
61        Snapshots.THUMBNAIL,
62        Snapshots.FAVICON,
63        Snapshots.URL,
64        Snapshots.DATE_CREATED,
65    };
66    private static final int SNAPSHOT_TITLE = 1;
67    private static final int SNAPSHOT_VIEWSTATE_LENGTH = 2;
68    private static final int SNAPSHOT_THUMBNAIL = 3;
69    private static final int SNAPSHOT_FAVICON = 4;
70    private static final int SNAPSHOT_URL = 5;
71    private static final int SNAPSHOT_DATE_CREATED = 6;
72
73    GridView mGrid;
74    View mEmpty;
75    SnapshotAdapter mAdapter;
76    CombinedBookmarksCallbacks mCallback;
77
78    @Override
79    public void onCreate(Bundle savedInstanceState) {
80        super.onCreate(savedInstanceState);
81        mCallback = (CombinedBookmarksCallbacks) getActivity();
82    }
83
84    @Override
85    public View onCreateView(LayoutInflater inflater, ViewGroup container,
86            Bundle savedInstanceState) {
87        View view = inflater.inflate(R.layout.snapshots, container, false);
88        mEmpty = view.findViewById(android.R.id.empty);
89        mGrid = (GridView) view.findViewById(R.id.grid);
90        setupGrid(inflater);
91        getLoaderManager().initLoader(LOADER_SNAPSHOTS, null, this);
92        return view;
93    }
94
95    @Override
96    public void onDestroyView() {
97        super.onDestroyView();
98        getLoaderManager().destroyLoader(LOADER_SNAPSHOTS);
99        if (mAdapter != null) {
100            mAdapter.changeCursor(null);
101            mAdapter = null;
102        }
103    }
104
105    void setupGrid(LayoutInflater inflater) {
106        View item = inflater.inflate(R.layout.snapshot_item, mGrid, false);
107        int mspec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
108        item.measure(mspec, mspec);
109        int width = item.getMeasuredWidth();
110        mGrid.setColumnWidth(width);
111        mGrid.setOnItemClickListener(this);
112        mGrid.setOnCreateContextMenuListener(this);
113    }
114
115    @Override
116    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
117        if (id == LOADER_SNAPSHOTS) {
118            return new CursorLoader(getActivity(),
119                    Snapshots.CONTENT_URI, PROJECTION,
120                    null, null, Snapshots.DATE_CREATED + " DESC");
121        }
122        return null;
123    }
124
125    @Override
126    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
127        if (loader.getId() == LOADER_SNAPSHOTS) {
128            if (mAdapter == null) {
129                mAdapter = new SnapshotAdapter(getActivity(), data);
130                mGrid.setAdapter(mAdapter);
131            } else {
132                mAdapter.changeCursor(data);
133            }
134            boolean empty = mAdapter.isEmpty();
135            mGrid.setVisibility(empty ? View.GONE : View.VISIBLE);
136            mEmpty.setVisibility(empty ? View.VISIBLE : View.GONE);
137        }
138    }
139
140    @Override
141    public void onLoaderReset(Loader<Cursor> loader) {
142    }
143
144    @Override
145    public void onCreateContextMenu(ContextMenu menu, View v,
146            ContextMenuInfo menuInfo) {
147        MenuInflater inflater = getActivity().getMenuInflater();
148        inflater.inflate(R.menu.snapshots_context, menu);
149        // Create the header, re-use BookmarkItem (has the layout we want)
150        BookmarkItem header = new BookmarkItem(getActivity());
151        AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
152        populateBookmarkItem(mAdapter.getItem(info.position), header);
153        menu.setHeaderView(header);
154    }
155
156    private void populateBookmarkItem(Cursor cursor, BookmarkItem item) {
157        item.setName(cursor.getString(SNAPSHOT_TITLE));
158        item.setUrl(cursor.getString(SNAPSHOT_URL));
159        item.setFavicon(getBitmap(cursor, SNAPSHOT_FAVICON));
160    }
161
162    static Bitmap getBitmap(Cursor cursor, int columnIndex) {
163        byte[] data = cursor.getBlob(columnIndex);
164        if (data == null) {
165            return null;
166        }
167        return BitmapFactory.decodeByteArray(data, 0, data.length);
168    }
169
170    @Override
171    public boolean onContextItemSelected(MenuItem item) {
172        if (item.getItemId() == R.id.delete_context_menu_id) {
173            AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
174            deleteSnapshot(info.id);
175            return true;
176        }
177        return super.onContextItemSelected(item);
178    }
179
180    void deleteSnapshot(long id) {
181        final Uri uri = ContentUris.withAppendedId(Snapshots.CONTENT_URI, id);
182        final ContentResolver cr = getActivity().getContentResolver();
183        new Thread() {
184            @Override
185            public void run() {
186                cr.delete(uri, null, null);
187            }
188        }.start();
189
190    }
191
192    @Override
193    public void onItemClick(AdapterView<?> parent, View view, int position,
194            long id) {
195        mCallback.openSnapshot(id);
196    }
197
198    private static class SnapshotAdapter extends ResourceCursorAdapter {
199
200        public SnapshotAdapter(Context context, Cursor c) {
201            super(context, R.layout.snapshot_item, c, 0);
202        }
203
204        @Override
205        public void bindView(View view, Context context, Cursor cursor) {
206            ImageView thumbnail = (ImageView) view.findViewById(R.id.thumb);
207            byte[] thumbBlob = cursor.getBlob(SNAPSHOT_THUMBNAIL);
208            if (thumbBlob == null) {
209                thumbnail.setImageResource(R.drawable.browser_thumbnail);
210            } else {
211                Bitmap thumbBitmap = BitmapFactory.decodeByteArray(
212                        thumbBlob, 0, thumbBlob.length);
213                thumbnail.setImageBitmap(thumbBitmap);
214            }
215            TextView title = (TextView) view.findViewById(R.id.title);
216            title.setText(cursor.getString(SNAPSHOT_TITLE));
217            TextView size = (TextView) view.findViewById(R.id.size);
218            if (size != null) {
219                int stateLen = cursor.getInt(SNAPSHOT_VIEWSTATE_LENGTH);
220                size.setText(String.format("%.2fMB", stateLen / 1024f / 1024f));
221            }
222            long timestamp = cursor.getLong(SNAPSHOT_DATE_CREATED);
223            TextView date = (TextView) view.findViewById(R.id.date);
224            DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT);
225            date.setText(dateFormat.format(new Date(timestamp)));
226        }
227
228        @Override
229        public Cursor getItem(int position) {
230            return (Cursor) super.getItem(position);
231        }
232    }
233
234}
235