13efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang/*
23efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * Copyright (C) 2015 The Android Open Source Project
33efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang *
43efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * Licensed under the Apache License, Version 2.0 (the "License");
53efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * you may not use this file except in compliance with the License.
63efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * You may obtain a copy of the License at
73efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang *
83efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang *      http://www.apache.org/licenses/LICENSE-2.0
93efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang *
103efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * Unless required by applicable law or agreed to in writing, software
113efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * distributed under the License is distributed on an "AS IS" BASIS,
123efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * See the License for the specific language governing permissions and
143efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang * limitations under the License.
153efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang */
163efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
173efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jangpackage com.android.contacts.editor;
183efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
193efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jangimport android.content.Context;
203efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jangimport android.graphics.Bitmap;
213efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jangimport android.net.Uri;
223efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jangimport android.provider.ContactsContract;
233efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jangimport android.util.AttributeSet;
241044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jangimport android.util.TypedValue;
253efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jangimport android.view.View;
261044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jangimport android.view.ViewGroup;
27ff16eea0e4d18cf2964667ce8e597780797e2b69Walter Jangimport android.widget.RelativeLayout;
283efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
290a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.ContactPhotoManager;
3065971d0f87dbee0b5ff93a7d64cdaab0940f56f5Gary Maiimport com.android.contacts.R;
3169c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.ValuesDelta;
3269c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.util.MaterialColorMapUtils.MaterialPalette;
3365971d0f87dbee0b5ff93a7d64cdaab0940f56f5Gary Maiimport com.android.contacts.util.SchedulingUtils;
3465971d0f87dbee0b5ff93a7d64cdaab0940f56f5Gary Maiimport com.android.contacts.widget.QuickContactImageView;
3565971d0f87dbee0b5ff93a7d64cdaab0940f56f5Gary Mai
363efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang/**
3731a74ad969b650eb733e536569254ed3978c4f54Walter Jang * Displays a photo and calls the host back when the user clicks it.
383efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang */
39363af60ea23e5a3b945005712a16564ab69db18bGary Maipublic class PhotoEditorView extends RelativeLayout implements View.OnClickListener {
403efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
4131a74ad969b650eb733e536569254ed3978c4f54Walter Jang    /**
4231a74ad969b650eb733e536569254ed3978c4f54Walter Jang     * Callbacks for the host of this view.
4331a74ad969b650eb733e536569254ed3978c4f54Walter Jang     */
4431a74ad969b650eb733e536569254ed3978c4f54Walter Jang    public interface Listener {
4531a74ad969b650eb733e536569254ed3978c4f54Walter Jang
4631a74ad969b650eb733e536569254ed3978c4f54Walter Jang        /**
4731a74ad969b650eb733e536569254ed3978c4f54Walter Jang         * Invoked when the user wants to change their photo.
4831a74ad969b650eb733e536569254ed3978c4f54Walter Jang         */
4931a74ad969b650eb733e536569254ed3978c4f54Walter Jang        void onPhotoEditorViewClicked();
5031a74ad969b650eb733e536569254ed3978c4f54Walter Jang    }
513efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
5231a74ad969b650eb733e536569254ed3978c4f54Walter Jang    private Listener mListener;
533efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
541044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang    private final float mLandscapePhotoRatio;
559d8f37e77052543c4ae07cbf8329e4ff0ddef66bWalter Jang    private final float mPortraitPhotoRatio;
561044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang    private final boolean mIsTwoPanel;
571044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang
58f46abd89a3386cbdadff99e96df826bb27f987e9Walter Jang    private QuickContactImageView mPhotoImageView;
59ab50e6f5cf14e1bdb6cd3598372fefc2fa6b0b83Walter Jang    private View mPhotoIcon;
604a268d3dc9eb0fa067b1e408199ec7c969f34a25Walter Jang    private View mPhotoIconOverlay;
61ab50e6f5cf14e1bdb6cd3598372fefc2fa6b0b83Walter Jang    private View mPhotoTouchInterceptOverlay;
6218724188d3abe065b0a030fb2d9d5557dcb6163eGary Mai    private MaterialPalette mMaterialPalette;
633efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
6431a74ad969b650eb733e536569254ed3978c4f54Walter Jang    private boolean mReadOnly;
6531a74ad969b650eb733e536569254ed3978c4f54Walter Jang    private boolean mIsNonDefaultPhotoBound;
6631a74ad969b650eb733e536569254ed3978c4f54Walter Jang
67363af60ea23e5a3b945005712a16564ab69db18bGary Mai    public PhotoEditorView(Context context) {
681044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang        this(context, null);
693efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    }
703efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
71363af60ea23e5a3b945005712a16564ab69db18bGary Mai    public PhotoEditorView(Context context, AttributeSet attrs) {
723efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang        super(context, attrs);
7331a74ad969b650eb733e536569254ed3978c4f54Walter Jang
74261e106d87056d0c9727dd9ae436d5aadadd0762Walter Jang        mLandscapePhotoRatio = getTypedFloat(R.dimen.quickcontact_landscape_photo_ratio);
759d8f37e77052543c4ae07cbf8329e4ff0ddef66bWalter Jang        mPortraitPhotoRatio = getTypedFloat(R.dimen.editor_portrait_photo_ratio);
76caf26197087343fdc18739e20e217236ff26831eWenyi Wang        mIsTwoPanel = getResources().getBoolean(R.bool.contacteditor_two_panel);
773efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    }
783efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
79261e106d87056d0c9727dd9ae436d5aadadd0762Walter Jang    private float getTypedFloat(int resourceId) {
80261e106d87056d0c9727dd9ae436d5aadadd0762Walter Jang        final TypedValue typedValue = new TypedValue();
81261e106d87056d0c9727dd9ae436d5aadadd0762Walter Jang        getResources().getValue(resourceId, typedValue, /* resolveRefs =*/ true);
82261e106d87056d0c9727dd9ae436d5aadadd0762Walter Jang        return typedValue.getFloat();
83261e106d87056d0c9727dd9ae436d5aadadd0762Walter Jang    }
84261e106d87056d0c9727dd9ae436d5aadadd0762Walter Jang
853efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    @Override
863efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    protected void onFinishInflate() {
873efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang        super.onFinishInflate();
88f46abd89a3386cbdadff99e96df826bb27f987e9Walter Jang        mPhotoImageView = (QuickContactImageView) findViewById(R.id.photo);
89ab50e6f5cf14e1bdb6cd3598372fefc2fa6b0b83Walter Jang        mPhotoIcon = findViewById(R.id.photo_icon);
904a268d3dc9eb0fa067b1e408199ec7c969f34a25Walter Jang        mPhotoIconOverlay = findViewById(R.id.photo_icon_overlay);
91ab50e6f5cf14e1bdb6cd3598372fefc2fa6b0b83Walter Jang        mPhotoTouchInterceptOverlay = findViewById(R.id.photo_touch_intercept_overlay);
92eec6992932cc1b650211402a30650c5842cc8ad8Gary Mai
933efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    }
943efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
9531a74ad969b650eb733e536569254ed3978c4f54Walter Jang    public void setListener(Listener listener) {
9631a74ad969b650eb733e536569254ed3978c4f54Walter Jang        mListener = listener;
9731a74ad969b650eb733e536569254ed3978c4f54Walter Jang    }
983efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
9931a74ad969b650eb733e536569254ed3978c4f54Walter Jang    public void setReadOnly(boolean readOnly) {
10031a74ad969b650eb733e536569254ed3978c4f54Walter Jang        mReadOnly = readOnly;
101ab50e6f5cf14e1bdb6cd3598372fefc2fa6b0b83Walter Jang        if (mReadOnly) {
102ab50e6f5cf14e1bdb6cd3598372fefc2fa6b0b83Walter Jang            mPhotoIcon.setVisibility(View.GONE);
103ab50e6f5cf14e1bdb6cd3598372fefc2fa6b0b83Walter Jang            mPhotoIconOverlay.setVisibility(View.GONE);
1044ceabed629c43cb247fd4a0faa36c09bd5ec999aGary Mai            mPhotoTouchInterceptOverlay.setClickable(false);
10534047d2d076f5501ff958f0ef041b4e25c65bbedGary Mai            mPhotoTouchInterceptOverlay.setContentDescription(getContext().getString(
10634047d2d076f5501ff958f0ef041b4e25c65bbedGary Mai                    R.string.editor_contact_photo_content_description));
107ab50e6f5cf14e1bdb6cd3598372fefc2fa6b0b83Walter Jang        } else {
1084ceabed629c43cb247fd4a0faa36c09bd5ec999aGary Mai            mPhotoIcon.setVisibility(View.VISIBLE);
1094ceabed629c43cb247fd4a0faa36c09bd5ec999aGary Mai            mPhotoIconOverlay.setVisibility(View.VISIBLE);
110ab50e6f5cf14e1bdb6cd3598372fefc2fa6b0b83Walter Jang            mPhotoTouchInterceptOverlay.setOnClickListener(this);
111ef6ceb2714641eb70dcedddf6a18e6344fd7cbccGary Mai            updatePhotoDescription();
112ab50e6f5cf14e1bdb6cd3598372fefc2fa6b0b83Walter Jang        }
113fa127a1c0ca95139664771edc3d5d97331c93b19Walter Jang    }
114fa127a1c0ca95139664771edc3d5d97331c93b19Walter Jang
11518724188d3abe065b0a030fb2d9d5557dcb6163eGary Mai    public void setPalette(MaterialPalette palette) {
11618724188d3abe065b0a030fb2d9d5557dcb6163eGary Mai        mMaterialPalette = palette;
11718724188d3abe065b0a030fb2d9d5557dcb6163eGary Mai    }
11818724188d3abe065b0a030fb2d9d5557dcb6163eGary Mai
119fa127a1c0ca95139664771edc3d5d97331c93b19Walter Jang    /**
12031a74ad969b650eb733e536569254ed3978c4f54Walter Jang     * Tries to bind a full size photo or a bitmap loaded from the given ValuesDelta,
12131a74ad969b650eb733e536569254ed3978c4f54Walter Jang     * and falls back to the default avatar, tinted using the given MaterialPalette (if it's not
12231a74ad969b650eb733e536569254ed3978c4f54Walter Jang     * null);
123fa127a1c0ca95139664771edc3d5d97331c93b19Walter Jang     */
12418724188d3abe065b0a030fb2d9d5557dcb6163eGary Mai    public void setPhoto(ValuesDelta valuesDelta) {
12531a74ad969b650eb733e536569254ed3978c4f54Walter Jang        // Check if we can update to the full size photo immediately
12631a74ad969b650eb733e536569254ed3978c4f54Walter Jang        final Long photoFileId = EditorUiUtils.getPhotoFileId(valuesDelta);
12731a74ad969b650eb733e536569254ed3978c4f54Walter Jang        if (photoFileId != null) {
12831a74ad969b650eb733e536569254ed3978c4f54Walter Jang            final Uri photoUri = ContactsContract.DisplayPhoto.CONTENT_URI.buildUpon()
12931a74ad969b650eb733e536569254ed3978c4f54Walter Jang                    .appendPath(photoFileId.toString()).build();
13031a74ad969b650eb733e536569254ed3978c4f54Walter Jang            setFullSizedPhoto(photoUri);
13131a74ad969b650eb733e536569254ed3978c4f54Walter Jang            adjustDimensions();
13231a74ad969b650eb733e536569254ed3978c4f54Walter Jang            return;
1333efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang        }
1341044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang
13531a74ad969b650eb733e536569254ed3978c4f54Walter Jang        // Use the bitmap image from the values delta
13631a74ad969b650eb733e536569254ed3978c4f54Walter Jang        final Bitmap bitmap = EditorUiUtils.getPhotoBitmap(valuesDelta);
13731a74ad969b650eb733e536569254ed3978c4f54Walter Jang        if (bitmap != null) {
13831a74ad969b650eb733e536569254ed3978c4f54Walter Jang            setPhoto(bitmap);
13931a74ad969b650eb733e536569254ed3978c4f54Walter Jang            adjustDimensions();
14031a74ad969b650eb733e536569254ed3978c4f54Walter Jang            return;
141f46abd89a3386cbdadff99e96df826bb27f987e9Walter Jang        }
142f46abd89a3386cbdadff99e96df826bb27f987e9Walter Jang
14318724188d3abe065b0a030fb2d9d5557dcb6163eGary Mai        setDefaultPhoto(mMaterialPalette);
14431a74ad969b650eb733e536569254ed3978c4f54Walter Jang        adjustDimensions();
14531a74ad969b650eb733e536569254ed3978c4f54Walter Jang    }
14631a74ad969b650eb733e536569254ed3978c4f54Walter Jang
14731a74ad969b650eb733e536569254ed3978c4f54Walter Jang    private void adjustDimensions() {
14831a74ad969b650eb733e536569254ed3978c4f54Walter Jang        // Follow the same logic as MultiShrinkScroll.initialize
1491044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang        SchedulingUtils.doOnPreDraw(this, /* drawNextFrame =*/ false, new Runnable() {
1501044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang            @Override
1511044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang            public void run() {
152a5e4bb287ea08f895c84d5de56fcc2483386b306Walter Jang                final int photoHeight, photoWidth;
153a5e4bb287ea08f895c84d5de56fcc2483386b306Walter Jang                if (mIsTwoPanel) {
154eec6992932cc1b650211402a30650c5842cc8ad8Gary Mai                    photoHeight = getHeight();
155a5e4bb287ea08f895c84d5de56fcc2483386b306Walter Jang                    photoWidth = (int) (photoHeight * mLandscapePhotoRatio);
156a5e4bb287ea08f895c84d5de56fcc2483386b306Walter Jang                } else {
1579d8f37e77052543c4ae07cbf8329e4ff0ddef66bWalter Jang                    // Make the photo slightly shorter that it is wide
158eec6992932cc1b650211402a30650c5842cc8ad8Gary Mai                    photoWidth = getWidth();
1599d8f37e77052543c4ae07cbf8329e4ff0ddef66bWalter Jang                    photoHeight = (int) (photoWidth / mPortraitPhotoRatio);
160a5e4bb287ea08f895c84d5de56fcc2483386b306Walter Jang                }
1611044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang                final ViewGroup.LayoutParams layoutParams = getLayoutParams();
1621044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang                layoutParams.height = photoHeight;
163a5e4bb287ea08f895c84d5de56fcc2483386b306Walter Jang                layoutParams.width = photoWidth;
1641044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang                setLayoutParams(layoutParams);
1651044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang            }
1661044645b9c2050436f4f0e0c7e5b8da2931879baWalter Jang        });
1673efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    }
1683efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
1693efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    /**
17031a74ad969b650eb733e536569254ed3978c4f54Walter Jang     * Whether a removable, non-default photo is bound to this view.
1713efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang     */
1723efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    public boolean isWritablePhotoSet() {
17331a74ad969b650eb733e536569254ed3978c4f54Walter Jang        return !mReadOnly && mIsNonDefaultPhotoBound;
1743efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    }
1753efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
1763efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    /**
17731a74ad969b650eb733e536569254ed3978c4f54Walter Jang     * Binds the given bitmap.
1783efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang     */
17931a74ad969b650eb733e536569254ed3978c4f54Walter Jang    private void setPhoto(Bitmap bitmap) {
18031a74ad969b650eb733e536569254ed3978c4f54Walter Jang        mPhotoImageView.setImageBitmap(bitmap);
18131a74ad969b650eb733e536569254ed3978c4f54Walter Jang        mIsNonDefaultPhotoBound = true;
182ef6ceb2714641eb70dcedddf6a18e6344fd7cbccGary Mai        updatePhotoDescription();
18331a74ad969b650eb733e536569254ed3978c4f54Walter Jang    }
1843efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
18531a74ad969b650eb733e536569254ed3978c4f54Walter Jang    private void setDefaultPhoto(MaterialPalette materialPalette) {
186da20b47c2b85390a2c3772379e71203c5aab513cGary Mai        mIsNonDefaultPhotoBound = false;
187ef6ceb2714641eb70dcedddf6a18e6344fd7cbccGary Mai        updatePhotoDescription();
18831a74ad969b650eb733e536569254ed3978c4f54Walter Jang        EditorUiUtils.setDefaultPhoto(mPhotoImageView, getResources(), materialPalette);
1893efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    }
1903efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
191ef6ceb2714641eb70dcedddf6a18e6344fd7cbccGary Mai    private void updatePhotoDescription() {
192ef6ceb2714641eb70dcedddf6a18e6344fd7cbccGary Mai        mPhotoTouchInterceptOverlay.setContentDescription(getContext().getString(
193ef6ceb2714641eb70dcedddf6a18e6344fd7cbccGary Mai                mIsNonDefaultPhotoBound
194ef6ceb2714641eb70dcedddf6a18e6344fd7cbccGary Mai                        ? R.string.editor_change_photo_content_description
195ef6ceb2714641eb70dcedddf6a18e6344fd7cbccGary Mai                        : R.string.editor_add_photo_content_description));
196ef6ceb2714641eb70dcedddf6a18e6344fd7cbccGary Mai    }
1973efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    /**
19831a74ad969b650eb733e536569254ed3978c4f54Walter Jang     * Binds a full size photo loaded from the given Uri.
1993efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang     */
20031a74ad969b650eb733e536569254ed3978c4f54Walter Jang    public void setFullSizedPhoto(Uri photoUri) {
20131a74ad969b650eb733e536569254ed3978c4f54Walter Jang        EditorUiUtils.loadPhoto(ContactPhotoManager.getInstance(getContext()),
20231a74ad969b650eb733e536569254ed3978c4f54Walter Jang                mPhotoImageView, photoUri);
20331a74ad969b650eb733e536569254ed3978c4f54Walter Jang        mIsNonDefaultPhotoBound = true;
204ef6ceb2714641eb70dcedddf6a18e6344fd7cbccGary Mai        updatePhotoDescription();
2051573aa697284e6627c7bb74eae4c350f56780c33Walter Jang    }
2061573aa697284e6627c7bb74eae4c350f56780c33Walter Jang
2073efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    /**
20831a74ad969b650eb733e536569254ed3978c4f54Walter Jang     * Removes the current bound photo bitmap.
2093efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang     */
21031a74ad969b650eb733e536569254ed3978c4f54Walter Jang    public void removePhoto() {
21118724188d3abe065b0a030fb2d9d5557dcb6163eGary Mai        setDefaultPhoto(mMaterialPalette);
2123efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    }
2133efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
2143efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    @Override
2153efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    public void onClick(View view) {
21631a74ad969b650eb733e536569254ed3978c4f54Walter Jang        if (mListener != null) {
21731a74ad969b650eb733e536569254ed3978c4f54Walter Jang            mListener.onPhotoEditorViewClicked();
2183efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang        }
2193efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    }
2203efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang}
221