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
17package com.android.contacts.editor;
18
19import com.android.contacts.R;
20import com.android.contacts.model.DataKind;
21import com.android.contacts.model.EntityDelta;
22import com.android.contacts.model.EntityDelta.ValuesDelta;
23
24import android.content.Context;
25import android.graphics.Bitmap;
26import android.graphics.BitmapFactory;
27import android.provider.ContactsContract.CommonDataKinds.Photo;
28import android.util.AttributeSet;
29import android.util.Log;
30import android.view.View;
31import android.widget.FrameLayout;
32import android.widget.ImageView;
33
34import java.io.ByteArrayOutputStream;
35import java.io.IOException;
36
37/**
38 * Simple editor for {@link Photo}.
39 */
40public class PhotoEditorView extends FrameLayout implements Editor {
41    private static final String TAG = "PhotoEditorView";
42
43    private ImageView mPhotoImageView;
44    private View mFrameView;
45
46    private ValuesDelta mEntry;
47    private EditorListener mListener;
48
49    private boolean mHasSetPhoto = false;
50    private boolean mReadOnly;
51
52    public PhotoEditorView(Context context) {
53        super(context);
54    }
55
56    public PhotoEditorView(Context context, AttributeSet attrs) {
57        super(context, attrs);
58    }
59
60    @Override
61    public void setEnabled(boolean enabled) {
62        super.setEnabled(enabled);
63        mFrameView.setEnabled(enabled);
64    }
65
66    /** {@inheritDoc} */
67    @Override
68    protected void onFinishInflate() {
69        super.onFinishInflate();
70        mPhotoImageView = (ImageView) findViewById(R.id.photo);
71        mFrameView = findViewById(R.id.frame);
72        mFrameView.setOnClickListener(new OnClickListener() {
73            @Override
74            public void onClick(View v) {
75                if (mListener != null) {
76                    mListener.onRequest(EditorListener.REQUEST_PICK_PHOTO);
77                }
78            }
79        });
80    }
81
82    /** {@inheritDoc} */
83    @Override
84    public void onFieldChanged(String column, String value) {
85        throw new UnsupportedOperationException("Photos don't support direct field changes");
86    }
87
88    /** {@inheritDoc} */
89    @Override
90    public void setValues(DataKind kind, ValuesDelta values, EntityDelta state, boolean readOnly,
91            ViewIdGenerator vig) {
92        mEntry = values;
93        mReadOnly = readOnly;
94
95        setId(vig.getId(state, kind, values, 0));
96
97        if (values != null) {
98            // Try decoding photo if actual entry
99            final byte[] photoBytes = values.getAsByteArray(Photo.PHOTO);
100            if (photoBytes != null) {
101                final Bitmap photo = BitmapFactory.decodeByteArray(photoBytes, 0,
102                        photoBytes.length);
103
104                mPhotoImageView.setImageBitmap(photo);
105                mFrameView.setEnabled(isEnabled());
106                mHasSetPhoto = true;
107                mEntry.setFromTemplate(false);
108            } else {
109                resetDefault();
110            }
111        } else {
112            resetDefault();
113        }
114    }
115
116    /**
117     * Return true if a valid {@link Photo} has been set.
118     */
119    public boolean hasSetPhoto() {
120        return mHasSetPhoto;
121    }
122
123    /**
124     * Assign the given {@link Bitmap} as the new value, updating UI and
125     * readying for persisting through {@link ValuesDelta}.
126     */
127    public void setPhotoBitmap(Bitmap photo) {
128        if (photo == null) {
129            // Clear any existing photo and return
130            mEntry.put(Photo.PHOTO, (byte[])null);
131            resetDefault();
132            return;
133        }
134
135        final int size = photo.getWidth() * photo.getHeight() * 4;
136        final ByteArrayOutputStream out = new ByteArrayOutputStream(size);
137
138        try {
139            photo.compress(Bitmap.CompressFormat.PNG, 100, out);
140            out.flush();
141            out.close();
142
143            mEntry.put(Photo.PHOTO, out.toByteArray());
144            mPhotoImageView.setImageBitmap(photo);
145            mFrameView.setEnabled(isEnabled());
146            mHasSetPhoto = true;
147            mEntry.setFromTemplate(false);
148
149            // When the user chooses a new photo mark it as super primary
150            mEntry.put(Photo.IS_SUPER_PRIMARY, 1);
151        } catch (IOException e) {
152            Log.w(TAG, "Unable to serialize photo: " + e.toString());
153        }
154    }
155
156    /**
157     * Set the super primary bit on the photo.
158     */
159    public void setSuperPrimary(boolean superPrimary) {
160        mEntry.put(Photo.IS_SUPER_PRIMARY, superPrimary ? 1 : 0);
161    }
162
163    protected void resetDefault() {
164        // Invalid photo, show default "add photo" place-holder
165        mPhotoImageView.setImageResource(R.drawable.ic_contact_picture_holo_light);
166        mFrameView.setEnabled(!mReadOnly && isEnabled());
167        mHasSetPhoto = false;
168        mEntry.setFromTemplate(true);
169    }
170
171    /** {@inheritDoc} */
172    @Override
173    public void setEditorListener(EditorListener listener) {
174        mListener = listener;
175    }
176
177    @Override
178    public void setDeletable(boolean deletable) {
179        // Photo is not deletable
180    }
181
182    @Override
183    public boolean isEmpty() {
184        return !mHasSetPhoto;
185    }
186
187    @Override
188    public void deleteEditor() {
189        // Photo is not deletable
190    }
191
192    @Override
193    public void clearAllFields() {
194        resetDefault();
195    }
196}
197