/** * Wire * Copyright (C) 2016 Wire Swiss GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.waz.zclient.views.chathead; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Typeface; import android.os.Build; import android.util.AttributeSet; import android.util.TypedValue; import android.view.Gravity; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageView; import com.waz.api.BitmapCallback; import com.waz.api.ImageAsset; import com.waz.api.LoadHandle; import com.waz.api.UpdateListener; import com.waz.api.User; import com.waz.zclient.R; import com.waz.zclient.ui.text.TypefaceTextView; import com.waz.zclient.ui.utils.ResourceUtils; import com.waz.zclient.ui.utils.TypefaceUtils; import timber.log.Timber; public class ChatheadImageView extends FrameLayout implements UpdateListener { public static final String TAG = ChatheadImageView.class.getName(); private static final int DEFAULT_COLOR = Color.TRANSPARENT; private enum ChatHeadState { IDLE, ERROR, BITMAP_NOT_LOADED_YET, BITMAP_LOADED } private ImageView imageView; private TypefaceTextView typefaceTextView; private ImageAsset imageAsset; private LoadHandle handle; private User user; private Paint paint; private ChatHeadState chatHeadState; public ChatheadImageView(Context context) { this(context, null); } public ChatheadImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public ChatheadImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } public void setUser(User user) { // user is empty if (user == null) { removeOldUser(); setState(ChatHeadState.ERROR); return; } // same user if (this.user != null && this.user.getId().equals(user.getId())) { updated(); return; } removeOldUser(); // connect new user this.user = user; this.user.addUpdateListener(this); imageAsset = this.user.getPicture(); if (imageAsset != null) { imageAsset.addUpdateListener(this); } setState(ChatHeadState.BITMAP_NOT_LOADED_YET); updated(); } public User getUser() { return user; } private void removeOldUser() { if (user != null) { user.removeUpdateListener(this); user = null; } if (imageAsset != null) { imageAsset.removeUpdateListener(this); imageAsset = null; } if (handle != null) { handle.cancel(); handle = null; } imageView.setImageBitmap(null); } private void setState(ChatHeadState chatHeadState) { switch (chatHeadState) { case IDLE: break; case ERROR: paint.setColor(DEFAULT_COLOR); break; case BITMAP_NOT_LOADED_YET: typefaceTextView.setText(user.getInitials()); paint.setColor(user.getAccent().getColor()); break; case BITMAP_LOADED: typefaceTextView.setText(""); paint.setColor(user.getAccent().getColor()); break; } this.chatHeadState = chatHeadState; } private void init() { chatHeadState = ChatHeadState.IDLE; imageView = new ImageView(getContext()); typefaceTextView = new TypefaceTextView(getContext()); addView(imageView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); addView(typefaceTextView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); paint = new Paint(Paint.ANTI_ALIAS_FLAG); } private void initTextView() { int fontColor; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { //noinspection deprecation fontColor = getResources().getColor(R.color.chathead__user_initials__font_color); } else { fontColor = getResources().getColor(R.color.chathead__user_initials__font_color, getContext().getTheme()); } Typeface initialsTypeface = TypefaceUtils.getTypeface(getResources().getString(R.string.chathead__user_initials__font)); int fontSize = (int) (getMeasuredWidth() * ResourceUtils.getResourceFloat(getResources(), R.dimen.notifications__incoming_call__chathead__font_proportion)); typefaceTextView.setTextColor(fontColor); typefaceTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize); typefaceTextView.setTypeface(initialsTypeface); typefaceTextView.setGravity(Gravity.CENTER); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); updated(); } @Override protected void dispatchDraw(Canvas canvas) { switch (chatHeadState) { case ERROR: case BITMAP_NOT_LOADED_YET: case BITMAP_LOADED: canvas.drawCircle(canvas.getWidth() / 2, canvas.getHeight() / 2, canvas.getWidth() / 2, paint); break; } super.dispatchDraw(canvas); } @Override public void updated() { initTextView(); setState(chatHeadState); if (imageAsset != null) { imageAsset.removeUpdateListener(this); imageAsset = null; } if (user != null) { imageAsset = user.getPicture(); } if (imageAsset == null) { return; } imageAsset.addUpdateListener(this); if (handle != null) { handle.cancel(); } handle = imageAsset.getRoundBitmap(imageView.getMeasuredWidth(), 0, DEFAULT_COLOR, new BitmapCallback() { @Override public void onBitmapLoaded(Bitmap bitmap) { setState(ChatHeadState.BITMAP_LOADED); imageView.setImageBitmap(bitmap); } @Override public void onBitmapLoadingFailed(BitmapLoadingFailed reason) { Timber.e("Loading of bitmap in failed: %s", reason); } }); } }