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