/**
* 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.menus;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.support.annotation.DrawableRes;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.waz.zclient.R;
import com.waz.zclient.controllers.confirmation.ConfirmationCallback;
import com.waz.zclient.controllers.confirmation.ConfirmationRequest;
import com.waz.zclient.ui.animation.interpolators.penner.Expo;
import com.waz.zclient.ui.animation.interpolators.penner.Quart;
import com.waz.zclient.ui.text.GlyphTextView;
import com.waz.zclient.ui.theme.OptionsTheme;
import com.waz.zclient.ui.utils.ColorUtils;
import com.waz.zclient.ui.views.ZetaButton;
import com.waz.zclient.utils.LayoutSpec;
import com.waz.zclient.utils.ViewUtils;
import com.waz.zclient.views.CheckBoxView;
public class ConfirmationMenu extends LinearLayout {
private static final int DEFAULT_COLOR = Color.BLUE;
private String header;
private String text;
private String positiveButtonText;
private String negativeButtonText;
private boolean cancelVisible;
private String checkboxLabelText;
private boolean checkboxSelectedByDefault;
private int headerIconRes;
private int backgroundImage;
private TextView headerTextView;
private TextView contentTextView;
private ZetaButton positiveButton;
private GlyphTextView cancelButton;
private ZetaButton negativeButton;
private CheckBoxView checkBoxView;
private ImageView headerIconView;
private ImageView backgroundImageView;
private View backgroundView;
private View messageContainerView;
private boolean confirmed;
private boolean cancelled;
private ConfirmationCallback callback;
private OptionsTheme optionsTheme;
private boolean noRoundBackground;
public void setNoRoundBackground() {
noRoundBackground = true;
}
private final OnClickListener onClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
if (callback == null) {
return;
}
switch (v.getId()) {
case R.id.positive:
confirmed = true;
boolean checkboxIsSelected = checkBoxView.getVisibility() == VISIBLE && checkBoxView.isSelected();
animateToShow(false);
callback.positiveButtonClicked(checkboxIsSelected);
break;
case R.id.negative:
callback.negativeButtonClicked();
animateToShow(false);
break;
case R.id.cancel:
cancelled = true;
callback.canceled();
animateToShow(false);
default:
break;
}
}
};
public ConfirmationMenu(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initAttributes(attrs);
if (!isInEditMode()) {
initViews();
}
}
public ConfirmationMenu(Context context, AttributeSet attrs) {
super(context, attrs);
initAttributes(attrs);
if (!isInEditMode()) {
initViews();
}
}
private void initAttributes(AttributeSet attrs) {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ConfirmationMenu);
header = a.getString(R.styleable.ConfirmationMenu_header);
text = a.getString(R.styleable.ConfirmationMenu_text);
negativeButtonText = a.getString(R.styleable.ConfirmationMenu_negative);
positiveButtonText = a.getString(R.styleable.ConfirmationMenu_positive);
cancelVisible = a.getBoolean(R.styleable.ConfirmationMenu_cancelVisible, false);
checkboxLabelText = a.getString(R.styleable.ConfirmationMenu_checkboxLabel);
checkboxSelectedByDefault = a.getBoolean(R.styleable.ConfirmationMenu_checkboxIsSelected, false);
headerIconRes = a.getResourceId(R.styleable.ConfirmationMenu_headerIcon, 0);
backgroundImage = a.getResourceId(R.styleable.ConfirmationMenu_backgroundImage, 0);
a.recycle();
}
public void setHeader(String text) {
updateText(headerTextView, text);
}
public void setText(String text) {
updateText(contentTextView, text);
}
public void setNegativeButton(String text) {
updateText(negativeButton, text);
if (negativeButton.getVisibility() == GONE) {
ViewUtils.setMarginLeft(positiveButton, 0);
}
}
public void setCancelVisible(boolean visible) {
cancelVisible = visible;
cancelButton.setVisibility(cancelVisible ? VISIBLE : GONE);
}
public void setPositiveButton(String text) {
updateText(positiveButton, text);
}
public void setCheckBox(String label, boolean selectedByDefault) {
checkboxLabelText = label;
checkboxSelectedByDefault = selectedByDefault;
if (TextUtils.isEmpty(checkboxLabelText)) {
checkBoxView.setVisibility(GONE);
} else {
checkBoxView.setVisibility(VISIBLE);
checkBoxView.setLabelText(checkboxLabelText);
checkBoxView.setSelected(checkboxSelectedByDefault);
}
}
private void updateText(TextView view, String text) {
view.setText(text);
if (!TextUtils.isEmpty(text)) {
view.setVisibility(VISIBLE);
} else {
view.setVisibility(GONE);
}
}
public void setButtonColor(int color) {
positiveButton.setIsFilled(true);
positiveButton.setAccentColor(color);
negativeButton.setIsFilled(false);
negativeButton.setAccentColor(color);
if (optionsTheme != null && optionsTheme.getType() == OptionsTheme.Type.LIGHT) {
negativeButton.setTextColor(color);
}
backgroundImageView.setColorFilter(ColorUtils.injectAlpha(0.1f, color));
}
public void useModalBackground(boolean show) {
backgroundView.setVisibility(show ? VISIBLE : GONE);
}
public void setIcon(@DrawableRes int icon) {
this.headerIconRes = icon;
headerIconView.setVisibility(icon == 0 ? GONE : VISIBLE);
headerIconView.setImageResource(icon);
}
public void setBackgroundImage(@DrawableRes int imageId) {
this.backgroundImage = imageId;
if (imageId != 0) {
backgroundImageView.setImageDrawable(ContextCompat.getDrawable(getContext(), imageId));
backgroundImageView.setVisibility(VISIBLE);
} else {
backgroundImageView.setVisibility(GONE);
}
}
public void animateToShow(boolean show) {
if (show) {
confirmed = false;
cancelled = false;
// Init views and post animations to get measured height of message container
backgroundView.setAlpha(0);
messageContainerView.setVisibility(INVISIBLE);
setVisibility(VISIBLE);
messageContainerView.post(new Runnable() {
@Override
public void run() {
ObjectAnimator showBackgroundAnimator = ObjectAnimator.ofFloat(backgroundView,
View.ALPHA,
0,
1);
showBackgroundAnimator.setInterpolator(new Quart.EaseOut());
showBackgroundAnimator.setDuration(getResources().getInteger(R.integer.framework_animation_duration_short));
ObjectAnimator showMessageAnimator = ObjectAnimator.ofFloat(messageContainerView,
View.TRANSLATION_Y,
messageContainerView.getMeasuredHeight(),
0);
showMessageAnimator.setInterpolator(new Expo.EaseOut());
showMessageAnimator.setDuration(getResources().getInteger(R.integer.framework_animation_duration_medium));
showMessageAnimator.setStartDelay(getResources().getInteger(R.integer.framework_animation__confirmation_menu__show_message_delay));
showMessageAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
messageContainerView.setVisibility(VISIBLE);
}
});
AnimatorSet showSet = new AnimatorSet();
showSet.playTogether(showBackgroundAnimator, showMessageAnimator);
showSet.setDuration(getResources().getInteger(R.integer.background_accent_color_transition_animation_duration));
showSet.start();
}
});
} else {
ObjectAnimator hideBackgroundAnimator = ObjectAnimator.ofFloat(backgroundView,
View.ALPHA,
1,
0);
hideBackgroundAnimator.setInterpolator(new Quart.EaseOut());
hideBackgroundAnimator.setDuration(getResources().getInteger(R.integer.framework_animation_duration_short));
hideBackgroundAnimator.setStartDelay(getResources().getInteger(R.integer.framework_animation__confirmation_menu__hide_background_delay));
hideBackgroundAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
setVisibility(GONE);
boolean checkboxIsSelected = checkBoxView.getVisibility() == VISIBLE && checkBoxView.isSelected();
if (callback != null) {
callback.onHideAnimationEnd(confirmed, cancelled, checkboxIsSelected);
}
}
});
ObjectAnimator hideMessageAnimator = ObjectAnimator.ofFloat(messageContainerView,
View.TRANSLATION_Y,
0,
messageContainerView.getMeasuredHeight());
hideMessageAnimator.setInterpolator(new Expo.EaseIn());
hideMessageAnimator.setDuration(getResources().getInteger(R.integer.framework_animation_duration_medium));
AnimatorSet hideSet = new AnimatorSet();
hideSet.playTogether(hideMessageAnimator, hideBackgroundAnimator);
hideSet.start();
}
}
private void initViews() {
LayoutInflater.from(getContext()).inflate(R.layout.confirmation_menu_light, this, true);
backgroundView = ViewUtils.getView(this, R.id.fl__confirmation_dialog__background);
messageContainerView = ViewUtils.getView(this, R.id.ll__confirmation_dialog__message_container);
setVisibility(GONE);
// header
headerTextView = ViewUtils.getView(this, R.id.header);
headerTextView.setText(header);
if (header != null) {
headerTextView.setVisibility(View.VISIBLE);
}
// text
contentTextView = ViewUtils.getView(this, R.id.text);
contentTextView.setText(text);
if (text != null) {
contentTextView.setVisibility(View.VISIBLE);
}
// Checkbox
checkBoxView = ViewUtils.getView(this, R.id.ll_confirmation_menu__checkbox_container);
if (TextUtils.isEmpty(checkboxLabelText)) {
checkBoxView.setVisibility(GONE);
} else {
checkBoxView.setVisibility(VISIBLE);
checkBoxView.setLabelText(checkboxLabelText);
checkBoxView.setSelected(checkboxSelectedByDefault);
}
// buttons
positiveButton = ViewUtils.getView(this, R.id.positive);
positiveButton.setText(positiveButtonText);
positiveButton.setOnClickListener(onClickListener);
negativeButton = ViewUtils.getView(this, R.id.negative);
negativeButton.setText(negativeButtonText);
negativeButton.setOnClickListener(onClickListener);
cancelButton = ViewUtils.getView(this, R.id.cancel);
cancelButton.setVisibility(cancelVisible ? VISIBLE : GONE);
cancelButton.setOnClickListener(onClickListener);
headerIconView = ViewUtils.getView(this, R.id.icon);
headerIconView.setVisibility(headerIconRes == 0 ? GONE : VISIBLE);
headerIconView.setImageResource(headerIconRes);
backgroundImageView = ViewUtils.getView(this, R.id.backgroundImage);
setBackgroundImage(backgroundImage);
// Consume all touch events
setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return true;
}
});
setButtonColor(DEFAULT_COLOR);
}
public void setWireTheme(OptionsTheme optionsTheme) {
this.optionsTheme = optionsTheme;
headerTextView.setTextColor(optionsTheme.getTextColorPrimary());
contentTextView.setTextColor(optionsTheme.getTextColorPrimary());
cancelButton.setTextColor(optionsTheme.getIconButtonTextColor());
cancelButton.setBackground(optionsTheme.getIconButtonBackground());
checkBoxView.setOptionsTheme(optionsTheme);
if (optionsTheme.getType() == OptionsTheme.Type.DARK) {
negativeButton.setTextColor(optionsTheme.getTextColorPrimary());
}
setBackground(optionsTheme.getOverlayColor());
}
public void setBackground(int color) {
if (LayoutSpec.isPhone(getContext())) {
backgroundView.setBackgroundColor(color);
} else {
if (!noRoundBackground) {
Drawable backgroundDrawable = ViewUtils.getRoundedRect(getContext().getResources().getDimensionPixelSize(R.dimen.background__picture__corner_radius),
color);
backgroundView.setBackground(backgroundDrawable);
} else {
backgroundView.setBackgroundColor(color);
}
}
}
public void onRequestConfirmation(ConfirmationRequest confirmationRequest) {
setWireTheme(confirmationRequest.optionsTheme);
callback = confirmationRequest.callback;
setHeader(confirmationRequest.header);
setText(confirmationRequest.message);
setPositiveButton(confirmationRequest.positiveButton);
setNegativeButton(confirmationRequest.negativeButton);
setCancelVisible(confirmationRequest.cancelVisible);
setIcon(confirmationRequest.headerIconRes);
setBackgroundImage(confirmationRequest.backgroundImage);
setCheckBox(confirmationRequest.checkboxLabel, confirmationRequest.checkboxSelectedByDefault);
animateToShow(true);
}
public void setCallback(ConfirmationCallback callback) {
this.callback = callback;
}
public void adjustLayout() {
int topPadding = getResources().getDimensionPixelSize(R.dimen.framework_confirmation_menu_padding_top);
int bottomPadding = getResources().getDimensionPixelSize(R.dimen.framework_confirmation_menu_padding_bottom);
int horizontalPadding = getResources().getDimensionPixelSize(R.dimen.framework_confirmation_menu_horizontal_padding);
messageContainerView.setPadding(horizontalPadding, topPadding, horizontalPadding, bottomPadding);
}
public void resetFullScreenPadding() {
int padding = getResources().getDimensionPixelSize(R.dimen.wire__padding__big);
messageContainerView.setPadding(padding, padding, padding, padding);
}
}