1d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/*
2d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Copyright (C) 2015 The Android Open Source Project
3d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd *
4d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Licensed under the Apache License, Version 2.0 (the "License");
5d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * you may not use this file except in compliance with the License.
6d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * You may obtain a copy of the License at
7d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd *
8d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd *      http://www.apache.org/licenses/LICENSE-2.0
9d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd *
10d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Unless required by applicable law or agreed to in writing, software
11d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * distributed under the License is distributed on an "AS IS" BASIS,
12d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * See the License for the specific language governing permissions and
14d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * limitations under the License.
15d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */
16d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpackage com.android.messaging.ui.mediapicker;
17d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
18d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.Context;
19d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.database.Cursor;
20d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.graphics.Rect;
21d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.util.AttributeSet;
22d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.MotionEvent;
23d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.TouchDelegate;
24d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.View;
25d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.widget.CheckBox;
26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.widget.FrameLayout;
27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.widget.ImageView.ScaleType;
28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.R;
30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DataModel;
31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.GalleryGridItemData;
32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.ui.AsyncImageView;
33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.ui.ConversationDrawables;
34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.google.common.annotations.VisibleForTesting;
35d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.concurrent.TimeUnit;
37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/**
39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Shows an item in the gallery picker grid view. Hosts an FileImageView with a checkbox.
40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */
41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpublic class GalleryGridItemView extends FrameLayout {
42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * Implemented by the owner of this GalleryGridItemView instance to communicate on media
44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * picking and selection events.
45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public interface HostInterface {
47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        void onItemClicked(View view, GalleryGridItemData data, boolean longClick);
48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        boolean isItemSelected(GalleryGridItemData data);
49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        boolean isMultiSelectEnabled();
50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @VisibleForTesting
53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    GalleryGridItemData mData;
54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private AsyncImageView mImageView;
55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private CheckBox mCheckBox;
56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private HostInterface mHostInterface;
57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private final OnClickListener mOnClickListener = new OnClickListener() {
58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        @Override
59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        public void onClick(final View v) {
60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mHostInterface.onItemClicked(GalleryGridItemView.this, mData, false /*longClick*/);
61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    };
63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public GalleryGridItemView(final Context context, final AttributeSet attrs) {
65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        super(context, attrs);
66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mData = DataModel.get().createGalleryGridItemData();
67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
69d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
70d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    protected void onFinishInflate() {
71d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        super.onFinishInflate();
72d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mImageView = (AsyncImageView) findViewById(R.id.image);
73d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mCheckBox = (CheckBox) findViewById(R.id.checkbox);
74d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mCheckBox.setOnClickListener(mOnClickListener);
75d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        setOnClickListener(mOnClickListener);
76d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final OnLongClickListener longClickListener = new OnLongClickListener() {
77d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            @Override
78d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            public boolean onLongClick(final View v) {
79d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                mHostInterface.onItemClicked(v, mData, true /* longClick */);
80d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                return true;
81d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
82d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        };
83d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        setOnLongClickListener(longClickListener);
84d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mCheckBox.setOnLongClickListener(longClickListener);
85d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        addOnLayoutChangeListener(new OnLayoutChangeListener() {
86d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            @Override
87d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            public void onLayoutChange(View v, int left, int top, int right, int bottom,
88d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    int oldLeft, int oldTop, int oldRight, int oldBottom) {
89d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                // Enlarge the clickable region for the checkbox to fill the entire view.
90d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                final Rect region = new Rect(0, 0, getWidth(), getHeight());
91d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                setTouchDelegate(new TouchDelegate(region, mCheckBox) {
92d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    @Override
93d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    public boolean onTouchEvent(MotionEvent event) {
94d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        switch (event.getAction()) {
95d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                            case MotionEvent.ACTION_DOWN:
96d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                                setPressed(true);
97d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                                break;
98d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                            case MotionEvent.ACTION_UP:
99d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                            case MotionEvent.ACTION_CANCEL:
100d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                                setPressed(false);
101d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                                break;
102d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        }
103d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        return super.onTouchEvent(event);
104d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    }
105d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                });
106d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
107d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        });
108d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
109d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
110d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    @Override
111d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
112d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // The grid view auto-fit the columns, so we want to let the height match the width
113d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // to make the image square.
114d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        super.onMeasure(widthMeasureSpec, widthMeasureSpec);
115d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
116d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
117d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void bind(final Cursor cursor, final HostInterface hostInterface) {
118d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final int desiredSize = getResources()
119d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                .getDimensionPixelSize(R.dimen.gallery_image_cell_size);
120d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mData.bind(cursor, desiredSize, desiredSize);
121d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mHostInterface = hostInterface;
122d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        updateViewState();
123d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
124d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
125d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private void updateViewState() {
126d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        updateImageView();
127d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (mHostInterface.isMultiSelectEnabled() && !mData.isDocumentPickerItem()) {
128d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mCheckBox.setVisibility(VISIBLE);
129d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mCheckBox.setClickable(true);
130d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mCheckBox.setChecked(mHostInterface.isItemSelected(mData));
131d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        } else {
132d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mCheckBox.setVisibility(GONE);
133d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mCheckBox.setClickable(false);
134d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
135d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
136d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
137d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private void updateImageView() {
138d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (mData.isDocumentPickerItem()) {
139d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mImageView.setScaleType(ScaleType.CENTER);
140d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            setBackgroundColor(ConversationDrawables.get().getConversationThemeColor());
141d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mImageView.setImageResourceId(null);
142d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mImageView.setImageResource(R.drawable.ic_photo_library_light);
143d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mImageView.setContentDescription(getResources().getString(
144d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    R.string.pick_image_from_document_library_content_description));
145d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        } else {
146d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mImageView.setScaleType(ScaleType.CENTER_CROP);
147d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            setBackgroundColor(getResources().getColor(R.color.gallery_image_default_background));
148d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mImageView.setImageResourceId(mData.getImageRequestDescriptor());
149d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final long dateSeconds = mData.getDateSeconds();
150d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final boolean isValidDate = (dateSeconds > 0);
151d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final int templateId = isValidDate ?
152d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    R.string.mediapicker_gallery_image_item_description :
153d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    R.string.mediapicker_gallery_image_item_description_no_date;
154d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            String contentDescription = String.format(getResources().getString(templateId),
155d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    dateSeconds * TimeUnit.SECONDS.toMillis(1));
156d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mImageView.setContentDescription(contentDescription);
157d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
158d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
159d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd}
160