Home | History | Annotate | Download | only in editor
      1 /*
      2  * Copyright (C) 2009 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 
     17 package com.android.contacts.editor;
     18 
     19 import com.android.contacts.ContactsUtils;
     20 import com.android.contacts.R;
     21 import com.android.contacts.model.DataKind;
     22 import com.android.contacts.model.EntityDelta;
     23 import com.android.contacts.model.EntityDelta.ValuesDelta;
     24 import com.android.contacts.util.ContactPhotoUtils;
     25 
     26 import android.content.Context;
     27 import android.graphics.Bitmap;
     28 import android.graphics.BitmapFactory;
     29 import android.provider.ContactsContract.CommonDataKinds.Photo;
     30 import android.util.AttributeSet;
     31 import android.view.View;
     32 import android.widget.ImageView;
     33 import android.widget.LinearLayout;
     34 
     35 /**
     36  * Simple editor for {@link Photo}.
     37  */
     38 public class PhotoEditorView extends LinearLayout implements Editor {
     39 
     40     private ImageView mPhotoImageView;
     41     private View mFrameView;
     42 
     43     private ValuesDelta mEntry;
     44     private EditorListener mListener;
     45     private View mTriangleAffordance;
     46 
     47     private boolean mHasSetPhoto = false;
     48     private boolean mReadOnly;
     49 
     50     public PhotoEditorView(Context context) {
     51         super(context);
     52     }
     53 
     54     public PhotoEditorView(Context context, AttributeSet attrs) {
     55         super(context, attrs);
     56     }
     57 
     58     @Override
     59     public void setEnabled(boolean enabled) {
     60         super.setEnabled(enabled);
     61         mFrameView.setEnabled(enabled);
     62     }
     63 
     64     @Override
     65     public void editNewlyAddedField() {
     66         // Never called, since the user never adds a new photo-editor;
     67         // you can only change the picture in an existing editor.
     68     }
     69 
     70     /** {@inheritDoc} */
     71     @Override
     72     protected void onFinishInflate() {
     73         super.onFinishInflate();
     74         mTriangleAffordance = findViewById(R.id.photo_triangle_affordance);
     75         mPhotoImageView = (ImageView) findViewById(R.id.photo);
     76         mFrameView = findViewById(R.id.frame);
     77         mFrameView.setOnClickListener(new OnClickListener() {
     78             @Override
     79             public void onClick(View v) {
     80                 if (mListener != null) {
     81                     mListener.onRequest(EditorListener.REQUEST_PICK_PHOTO);
     82                 }
     83             }
     84         });
     85     }
     86 
     87     /** {@inheritDoc} */
     88     @Override
     89     public void onFieldChanged(String column, String value) {
     90         throw new UnsupportedOperationException("Photos don't support direct field changes");
     91     }
     92 
     93     /** {@inheritDoc} */
     94     @Override
     95     public void setValues(DataKind kind, ValuesDelta values, EntityDelta state, boolean readOnly,
     96             ViewIdGenerator vig) {
     97         mEntry = values;
     98         mReadOnly = readOnly;
     99 
    100         setId(vig.getId(state, kind, values, 0));
    101 
    102         if (values != null) {
    103             // Try decoding photo if actual entry
    104             final byte[] photoBytes = values.getAsByteArray(Photo.PHOTO);
    105             if (photoBytes != null) {
    106                 final Bitmap photo = BitmapFactory.decodeByteArray(photoBytes, 0,
    107                         photoBytes.length);
    108 
    109                 mPhotoImageView.setImageBitmap(photo);
    110                 mFrameView.setEnabled(isEnabled());
    111                 mHasSetPhoto = true;
    112                 mEntry.setFromTemplate(false);
    113             } else {
    114                 resetDefault();
    115             }
    116         } else {
    117             resetDefault();
    118         }
    119     }
    120 
    121     /**
    122      * Return true if a valid {@link Photo} has been set.
    123      */
    124     public boolean hasSetPhoto() {
    125         return mHasSetPhoto;
    126     }
    127 
    128     /**
    129      * Assign the given {@link Bitmap} as the new value, updating UI and
    130      * readying for persisting through {@link ValuesDelta}.
    131      */
    132     public void setPhotoBitmap(Bitmap photo) {
    133         if (photo == null) {
    134             // Clear any existing photo and return
    135             mEntry.put(Photo.PHOTO, (byte[])null);
    136             resetDefault();
    137             return;
    138         }
    139 
    140         mPhotoImageView.setImageBitmap(photo);
    141         mFrameView.setEnabled(isEnabled());
    142         mHasSetPhoto = true;
    143         mEntry.setFromTemplate(false);
    144 
    145         // When the user chooses a new photo mark it as super primary
    146         mEntry.put(Photo.IS_SUPER_PRIMARY, 1);
    147 
    148         // Even though high-res photos cannot be saved by passing them via
    149         // an EntityDeltaList (since they cause the Bundle size limit to be
    150         // exceeded), we still pass a low-res thumbnail. This simplifies
    151         // code all over the place, because we don't have to test whether
    152         // there is a change in EITHER the delta-list OR a changed photo...
    153         // this way, there is always a change in the delta-list.
    154         final int size = ContactsUtils.getThumbnailSize(getContext());
    155         final Bitmap scaled = Bitmap.createScaledBitmap(photo, size, size, false);
    156         final byte[] compressed = ContactPhotoUtils.compressBitmap(scaled);
    157         if (compressed != null) mEntry.put(Photo.PHOTO, compressed);
    158     }
    159 
    160     /**
    161      * Set the super primary bit on the photo.
    162      */
    163     public void setSuperPrimary(boolean superPrimary) {
    164         mEntry.put(Photo.IS_SUPER_PRIMARY, superPrimary ? 1 : 0);
    165     }
    166 
    167     protected void resetDefault() {
    168         // Invalid photo, show default "add photo" place-holder
    169         mPhotoImageView.setImageResource(R.drawable.ic_contact_picture_holo_light);
    170         mFrameView.setEnabled(!mReadOnly && isEnabled());
    171         mHasSetPhoto = false;
    172         mEntry.setFromTemplate(true);
    173     }
    174 
    175     /** {@inheritDoc} */
    176     @Override
    177     public void setEditorListener(EditorListener listener) {
    178         mListener = listener;
    179 
    180         final boolean isPushable = listener != null;
    181         mTriangleAffordance.setVisibility(isPushable ? View.VISIBLE : View.INVISIBLE);
    182         mFrameView.setVisibility(isPushable ? View.VISIBLE : View.INVISIBLE);
    183     }
    184 
    185     @Override
    186     public void setDeletable(boolean deletable) {
    187         // Photo is not deletable
    188     }
    189 
    190     @Override
    191     public boolean isEmpty() {
    192         return !mHasSetPhoto;
    193     }
    194 
    195     @Override
    196     public void deleteEditor() {
    197         // Photo is not deletable
    198     }
    199 
    200     @Override
    201     public void clearAllFields() {
    202         resetDefault();
    203     }
    204 }
    205