1 // Copyright 2019 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.chrome.browser.tasks.tab_management; 6 7 import android.content.Context; 8 import android.graphics.Bitmap; 9 import android.graphics.BitmapFactory; 10 import android.graphics.drawable.Drawable; 11 import android.util.AttributeSet; 12 import android.widget.LinearLayout; 13 14 import org.chromium.base.ApiCompatibilityUtils; 15 import org.chromium.chrome.tab_ui.R; 16 import org.chromium.components.browser_ui.widget.text.TemplatePreservingTextView; 17 import org.chromium.ui.widget.ButtonCompat; 18 import org.chromium.ui.widget.ChromeImageView; 19 20 import java.lang.ref.WeakReference; 21 22 /** 23 * Represents a secondary card view in Grid Tab Switcher. The view contains an icon, a description, 24 * an action button for acceptance, and a close button for dismissal. 25 */ 26 class MessageCardView extends LinearLayout { 27 private static WeakReference<Bitmap> sCloseButtonBitmapWeakRef; 28 29 /** 30 * An interface to get the icon to be shown inside the message card. 31 */ getIconDrawable()32 public interface IconProvider { Drawable getIconDrawable(); } 33 34 /** 35 * An interface to handle the review action. 36 */ review()37 public interface ReviewActionProvider { void review(); } 38 39 /** 40 * An interface to handle the dismiss action. 41 */ 42 public interface DismissActionProvider { dismiss(@essageService.MessageType int messageType)43 void dismiss(@MessageService.MessageType int messageType); 44 } 45 46 private ChromeImageView mIcon; 47 private TemplatePreservingTextView mDescription; 48 private ButtonCompat mActionButton; 49 private ChromeImageView mCloseButton; 50 MessageCardView(Context context, AttributeSet attrs)51 public MessageCardView(Context context, AttributeSet attrs) { 52 super(context, attrs); 53 } 54 55 @Override onFinishInflate()56 protected void onFinishInflate() { 57 super.onFinishInflate(); 58 59 mIcon = findViewById(R.id.icon); 60 mDescription = findViewById(R.id.description); 61 mActionButton = findViewById(R.id.action_button); 62 mCloseButton = findViewById(R.id.close_button); 63 64 if (sCloseButtonBitmapWeakRef == null || sCloseButtonBitmapWeakRef.get() == null) { 65 int closeButtonSize = 66 (int) getResources().getDimension(R.dimen.tab_grid_close_button_size); 67 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.btn_close); 68 sCloseButtonBitmapWeakRef = new WeakReference<>( 69 Bitmap.createScaledBitmap(bitmap, closeButtonSize, closeButtonSize, true)); 70 } 71 mCloseButton.setImageBitmap(sCloseButtonBitmapWeakRef.get()); 72 } 73 74 /** 75 * @see TemplatePreservingTextView#setTemplate(String), setDescriptionText() must be called 76 * after calling this method for the new template text to take effect. 77 */ setDescriptionTextTemplate(String template)78 void setDescriptionTextTemplate(String template) { 79 mDescription.setTemplate(template); 80 } 81 82 /** 83 * @see TemplatePreservingTextView#setText(CharSequence). 84 */ setDescriptionText(CharSequence text)85 void setDescriptionText(CharSequence text) { 86 mDescription.setText(text); 87 } 88 89 /** 90 * Set action text for the action button. 91 * @param actionText Text to be displayed. 92 */ setActionText(String actionText)93 void setActionText(String actionText) { 94 mActionButton.setText(actionText); 95 } 96 97 /** 98 * Set icon drawable. 99 * @param iconDrawable Drawable to be shown. 100 */ setIcon(Drawable iconDrawable)101 void setIcon(Drawable iconDrawable) { 102 mIcon.setImageDrawable(iconDrawable); 103 } 104 105 /** 106 * Set click listener for the action button. 107 * @param listener {@link android.view.View.OnClickListener} for the action button. 108 */ setActionButtonOnClickListener(OnClickListener listener)109 void setActionButtonOnClickListener(OnClickListener listener) { 110 mActionButton.setOnClickListener(listener); 111 } 112 113 /** 114 * Set content description for dismiss button. 115 * @param description The content description. 116 */ setDismissButtonContentDescription(String description)117 void setDismissButtonContentDescription(String description) { 118 mCloseButton.setContentDescription(description); 119 } 120 121 /** 122 * Set {@link android.view.View.OnClickListener} for dismiss button. 123 * @param listener {@link android.view.View.OnClickListener} to set. 124 */ setDismissButtonOnClickListener(OnClickListener listener)125 void setDismissButtonOnClickListener(OnClickListener listener) { 126 mCloseButton.setOnClickListener(listener); 127 } 128 129 /** 130 * Modify the view based on the visibility of the icon. For messages that doesn't have an icon, 131 * remove the icon and update the margin of the description text field. 132 * @param visible Whether icon is visible. 133 */ setIconVisibility(boolean visible)134 void setIconVisibility(boolean visible) { 135 MarginLayoutParams params = (MarginLayoutParams) mDescription.getLayoutParams(); 136 if (visible) { 137 if (indexOfChild(mIcon) == -1) { 138 addView(mIcon, 0); 139 params.setMargins(0, 0, 0, 0); 140 } 141 } else { 142 int margin = (int) getContext().getResources().getDimension( 143 R.dimen.tab_grid_iph_item_description_margin); 144 removeView(mIcon); 145 params.setMargins(margin, 0, 0, 0); 146 } 147 } 148 149 /** 150 * Set background resource. 151 * @param isIncognito Whether the resource is used for incognito mode. 152 */ setBackground(boolean isIncognito)153 private void setBackground(boolean isIncognito) { 154 setBackgroundResource(TabUiColorProvider.getMessageCardBackgroundResourceId(isIncognito)); 155 } 156 157 /** 158 * Set text appearance for description. 159 * @param isIncognito Whether the text appearance is used for incognito mode. 160 */ setDescriptionTextAppearance(boolean isIncognito)161 private void setDescriptionTextAppearance(boolean isIncognito) { 162 ApiCompatibilityUtils.setTextAppearance(mDescription, 163 TabUiColorProvider.getMessageCardDescriptionTextAppearance(isIncognito)); 164 } 165 166 /** 167 * Set text appearance for action button. 168 * @param isIncognito Whether the text appearance is used for incognito mode. 169 */ setActionButtonTextAppearance(boolean isIncognito)170 private void setActionButtonTextAppearance(boolean isIncognito) { 171 ApiCompatibilityUtils.setTextAppearance(mActionButton, 172 TabUiColorProvider.getMessageCardActionButtonTextAppearance(isIncognito)); 173 } 174 175 /** 176 * Set tint for close button. 177 * @param isIncognito Whether the tint is used for incognito mode. 178 */ setCloseButtonTint(boolean isIncognito)179 private void setCloseButtonTint(boolean isIncognito) { 180 ApiCompatibilityUtils.setImageTintList(mCloseButton, 181 TabUiColorProvider.getMessageCardCloseButtonTintList( 182 mCloseButton.getContext(), isIncognito)); 183 } 184 185 /** 186 * Update Message Card when switching between normal mode and incognito mode. 187 * @param isIncognito Whether it is in the incognito mode. 188 */ updateMessageCardColor(boolean isIncognito)189 void updateMessageCardColor(boolean isIncognito) { 190 setBackground(isIncognito); 191 setDescriptionTextAppearance(isIncognito); 192 setActionButtonTextAppearance(isIncognito); 193 // TODO(crbug.com/1139194): Set action button ripple color. 194 setCloseButtonTint(isIncognito); 195 } 196 } 197