Home | History | Annotate | Download | only in attachmentchooser
      1 /*
      2  * Copyright (C) 2015 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.messaging.ui.attachmentchooser;
     17 
     18 import android.content.Context;
     19 import android.graphics.Rect;
     20 import android.net.Uri;
     21 import android.os.Parcel;
     22 import android.os.Parcelable;
     23 import android.util.AttributeSet;
     24 import android.widget.GridView;
     25 
     26 import com.android.messaging.datamodel.data.MessagePartData;
     27 import com.android.messaging.ui.attachmentchooser.AttachmentChooserFragment.AttachmentGridAdapter;
     28 import com.android.messaging.util.Assert;
     29 import com.android.messaging.util.UiUtils;
     30 
     31 import java.util.Collections;
     32 import java.util.HashSet;
     33 import java.util.Set;
     34 
     35 /**
     36  * Displays a grid of attachment previews for the user to choose which to select/unselect
     37  */
     38 public class AttachmentGridView extends GridView implements
     39         AttachmentGridItemView.HostInterface {
     40     public interface AttachmentGridHost {
     41         void displayPhoto(final Rect viewRect, final Uri photoUri);
     42         void updateSelectionCount(final int count);
     43     }
     44 
     45     // By default everything is selected so only need to keep track of the unselected set.
     46     private final Set<MessagePartData> mUnselectedSet;
     47     private AttachmentGridHost mHost;
     48 
     49     public AttachmentGridView(final Context context, final AttributeSet attrs) {
     50         super(context, attrs);
     51         mUnselectedSet = new HashSet<>();
     52     }
     53 
     54     public void setHost(final AttachmentGridHost host) {
     55         mHost = host;
     56     }
     57 
     58     @Override
     59     public boolean isItemSelected(final MessagePartData attachment) {
     60         return !mUnselectedSet.contains(attachment);
     61     }
     62 
     63     @Override
     64     public void onItemClicked(final AttachmentGridItemView view, final MessagePartData attachment) {
     65         // If the item is an image, show the photo viewer. All the other types (video, audio,
     66         // vcard) have internal click handling for showing previews so we don't need to handle them
     67         if (attachment.isImage()) {
     68             mHost.displayPhoto(UiUtils.getMeasuredBoundsOnScreen(view), attachment.getContentUri());
     69         }
     70     }
     71 
     72     @Override
     73     public void onItemCheckedChanged(AttachmentGridItemView view, MessagePartData attachment) {
     74         // Toggle selection.
     75         if (isItemSelected(attachment)) {
     76             mUnselectedSet.add(attachment);
     77         } else {
     78             mUnselectedSet.remove(attachment);
     79         }
     80         view.updateSelectedState();
     81         updateSelectionCount();
     82     }
     83 
     84     public Set<MessagePartData> getUnselectedAttachments() {
     85         return Collections.unmodifiableSet(mUnselectedSet);
     86     }
     87 
     88     private void updateSelectionCount() {
     89         final int count = getAdapter().getCount() - mUnselectedSet.size();
     90         Assert.isTrue(count >= 0);
     91         mHost.updateSelectionCount(count);
     92     }
     93 
     94     private void refreshViews() {
     95         if (getAdapter() instanceof AttachmentGridAdapter) {
     96             ((AttachmentGridAdapter) getAdapter()).notifyDataSetChanged();
     97         }
     98     }
     99 
    100     @Override
    101     public Parcelable onSaveInstanceState() {
    102         final Parcelable superState = super.onSaveInstanceState();
    103         final SavedState savedState = new SavedState(superState);
    104         savedState.unselectedParts = mUnselectedSet
    105                 .toArray(new MessagePartData[mUnselectedSet.size()]);
    106         return savedState;
    107     }
    108 
    109     @Override
    110     public void onRestoreInstanceState(final Parcelable state) {
    111         if (!(state instanceof SavedState)) {
    112             super.onRestoreInstanceState(state);
    113             return;
    114         }
    115 
    116         final SavedState savedState = (SavedState) state;
    117         super.onRestoreInstanceState(savedState.getSuperState());
    118         mUnselectedSet.clear();
    119         for (int i = 0; i < savedState.unselectedParts.length; i++) {
    120             final MessagePartData unselectedPart = savedState.unselectedParts[i];
    121             mUnselectedSet.add(unselectedPart);
    122         }
    123         refreshViews();
    124     }
    125 
    126     /**
    127      * Persists the item selection state to saved instance state so we can restore on activity
    128      * recreation
    129      */
    130     public static class SavedState extends BaseSavedState {
    131         MessagePartData[] unselectedParts;
    132 
    133         SavedState(final Parcelable superState) {
    134             super(superState);
    135         }
    136 
    137         private SavedState(final Parcel in) {
    138             super(in);
    139 
    140             // Read parts
    141             final int partCount = in.readInt();
    142             unselectedParts = new MessagePartData[partCount];
    143             for (int i = 0; i < partCount; i++) {
    144                 unselectedParts[i] = ((MessagePartData) in.readParcelable(
    145                         MessagePartData.class.getClassLoader()));
    146             }
    147         }
    148 
    149         @Override
    150         public void writeToParcel(final Parcel out, final int flags) {
    151             super.writeToParcel(out, flags);
    152 
    153             // Write parts
    154             out.writeInt(unselectedParts.length);
    155             for (final MessagePartData image : unselectedParts) {
    156                 out.writeParcelable(image, flags);
    157             }
    158         }
    159 
    160         public static final Parcelable.Creator<SavedState> CREATOR =
    161                 new Parcelable.Creator<SavedState>() {
    162             @Override
    163             public SavedState createFromParcel(final Parcel in) {
    164                 return new SavedState(in);
    165             }
    166             @Override
    167             public SavedState[] newArray(final int size) {
    168                 return new SavedState[size];
    169             }
    170         };
    171     }
    172 }
    173