1 /* 2 * Copyright (C) 2021 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 17 package com.android.car.qc; 18 19 import android.app.PendingIntent; 20 import android.graphics.drawable.Icon; 21 import android.os.Parcel; 22 23 import androidx.annotation.NonNull; 24 import androidx.annotation.Nullable; 25 26 import java.util.ArrayList; 27 import java.util.Collections; 28 import java.util.List; 29 30 /** 31 * Quick Control Row Element 32 * ------------------------------------ 33 * | | Title | | 34 * | StartItems | Subtitle | EndItems | 35 * | | Sliders | | 36 * ------------------------------------ 37 */ 38 public class QCRow extends QCItem { 39 private final String mTitle; 40 private final String mSubtitle; 41 private final Icon mStartIcon; 42 private final boolean mIsStartIconTintable; 43 private final QCSlider mSlider; 44 private final List<QCActionItem> mStartItems; 45 private final List<QCActionItem> mEndItems; 46 private final PendingIntent mPrimaryAction; 47 private PendingIntent mDisabledClickAction; 48 QCRow(@ullable String title, @Nullable String subtitle, boolean isEnabled, boolean isClickableWhileDisabled, @Nullable PendingIntent primaryAction, @Nullable PendingIntent disabledClickAction, @Nullable Icon startIcon, boolean isIconTintable, @Nullable QCSlider slider, @NonNull List<QCActionItem> startItems, @NonNull List<QCActionItem> endItems)49 public QCRow(@Nullable String title, @Nullable String subtitle, boolean isEnabled, 50 boolean isClickableWhileDisabled, @Nullable PendingIntent primaryAction, 51 @Nullable PendingIntent disabledClickAction, @Nullable Icon startIcon, 52 boolean isIconTintable, @Nullable QCSlider slider, 53 @NonNull List<QCActionItem> startItems, @NonNull List<QCActionItem> endItems) { 54 super(QC_TYPE_ROW, isEnabled, isClickableWhileDisabled); 55 mTitle = title; 56 mSubtitle = subtitle; 57 mPrimaryAction = primaryAction; 58 mDisabledClickAction = disabledClickAction; 59 mStartIcon = startIcon; 60 mIsStartIconTintable = isIconTintable; 61 mSlider = slider; 62 mStartItems = Collections.unmodifiableList(startItems); 63 mEndItems = Collections.unmodifiableList(endItems); 64 } 65 QCRow(@onNull Parcel in)66 public QCRow(@NonNull Parcel in) { 67 super(in); 68 mTitle = in.readString(); 69 mSubtitle = in.readString(); 70 boolean hasIcon = in.readBoolean(); 71 if (hasIcon) { 72 mStartIcon = Icon.CREATOR.createFromParcel(in); 73 } else { 74 mStartIcon = null; 75 } 76 mIsStartIconTintable = in.readBoolean(); 77 boolean hasSlider = in.readBoolean(); 78 if (hasSlider) { 79 mSlider = QCSlider.CREATOR.createFromParcel(in); 80 } else { 81 mSlider = null; 82 } 83 List<QCActionItem> startItems = new ArrayList<>(); 84 int startItemCount = in.readInt(); 85 for (int i = 0; i < startItemCount; i++) { 86 startItems.add(QCActionItem.CREATOR.createFromParcel(in)); 87 } 88 mStartItems = Collections.unmodifiableList(startItems); 89 List<QCActionItem> endItems = new ArrayList<>(); 90 int endItemCount = in.readInt(); 91 for (int i = 0; i < endItemCount; i++) { 92 endItems.add(QCActionItem.CREATOR.createFromParcel(in)); 93 } 94 mEndItems = Collections.unmodifiableList(endItems); 95 boolean hasPrimaryAction = in.readBoolean(); 96 if (hasPrimaryAction) { 97 mPrimaryAction = PendingIntent.CREATOR.createFromParcel(in); 98 } else { 99 mPrimaryAction = null; 100 } 101 boolean hasDisabledClickAction = in.readBoolean(); 102 if (hasDisabledClickAction) { 103 mDisabledClickAction = PendingIntent.CREATOR.createFromParcel(in); 104 } else { 105 mDisabledClickAction = null; 106 } 107 } 108 109 @Override writeToParcel(Parcel dest, int flags)110 public void writeToParcel(Parcel dest, int flags) { 111 super.writeToParcel(dest, flags); 112 dest.writeString(mTitle); 113 dest.writeString(mSubtitle); 114 boolean hasStartIcon = mStartIcon != null; 115 dest.writeBoolean(hasStartIcon); 116 if (hasStartIcon) { 117 mStartIcon.writeToParcel(dest, flags); 118 } 119 dest.writeBoolean(mIsStartIconTintable); 120 boolean hasSlider = mSlider != null; 121 dest.writeBoolean(hasSlider); 122 if (hasSlider) { 123 mSlider.writeToParcel(dest, flags); 124 } 125 dest.writeInt(mStartItems.size()); 126 for (QCActionItem startItem : mStartItems) { 127 startItem.writeToParcel(dest, flags); 128 } 129 dest.writeInt(mEndItems.size()); 130 for (QCActionItem endItem : mEndItems) { 131 endItem.writeToParcel(dest, flags); 132 } 133 boolean hasPrimaryAction = mPrimaryAction != null; 134 dest.writeBoolean(hasPrimaryAction); 135 if (hasPrimaryAction) { 136 mPrimaryAction.writeToParcel(dest, flags); 137 } 138 boolean hasDisabledClickAction = mDisabledClickAction != null; 139 dest.writeBoolean(hasDisabledClickAction); 140 if (hasDisabledClickAction) { 141 mDisabledClickAction.writeToParcel(dest, flags); 142 } 143 } 144 145 @Override getPrimaryAction()146 public PendingIntent getPrimaryAction() { 147 return mPrimaryAction; 148 } 149 150 @Override getDisabledClickAction()151 public PendingIntent getDisabledClickAction() { 152 return mDisabledClickAction; 153 } 154 155 @Nullable getTitle()156 public String getTitle() { 157 return mTitle; 158 } 159 160 @Nullable getSubtitle()161 public String getSubtitle() { 162 return mSubtitle; 163 } 164 165 @Nullable getStartIcon()166 public Icon getStartIcon() { 167 return mStartIcon; 168 } 169 isStartIconTintable()170 public boolean isStartIconTintable() { 171 return mIsStartIconTintable; 172 } 173 174 @Nullable getSlider()175 public QCSlider getSlider() { 176 return mSlider; 177 } 178 179 @NonNull getStartItems()180 public List<QCActionItem> getStartItems() { 181 return mStartItems; 182 } 183 184 @NonNull getEndItems()185 public List<QCActionItem> getEndItems() { 186 return mEndItems; 187 } 188 189 public static Creator<QCRow> CREATOR = new Creator<QCRow>() { 190 @Override 191 public QCRow createFromParcel(Parcel source) { 192 return new QCRow(source); 193 } 194 195 @Override 196 public QCRow[] newArray(int size) { 197 return new QCRow[size]; 198 } 199 }; 200 201 /** 202 * Builder for {@link QCRow}. 203 */ 204 public static class Builder { 205 private final List<QCActionItem> mStartItems = new ArrayList<>(); 206 private final List<QCActionItem> mEndItems = new ArrayList<>(); 207 private Icon mStartIcon; 208 private boolean mIsStartIconTintable = true; 209 private String mTitle; 210 private String mSubtitle; 211 private boolean mIsEnabled = true; 212 private boolean mIsClickableWhileDisabled = false; 213 private QCSlider mSlider; 214 private PendingIntent mPrimaryAction; 215 private PendingIntent mDisabledClickAction; 216 217 /** 218 * Sets the row title. 219 */ setTitle(@ullable String title)220 public Builder setTitle(@Nullable String title) { 221 mTitle = title; 222 return this; 223 } 224 225 /** 226 * Sets the row subtitle. 227 */ setSubtitle(@ullable String subtitle)228 public Builder setSubtitle(@Nullable String subtitle) { 229 mSubtitle = subtitle; 230 return this; 231 } 232 233 /** 234 * Sets whether or not the row is enabled. Note that this only affects the main row area, 235 * not the action items contained within the row. 236 */ setEnabled(boolean enabled)237 public Builder setEnabled(boolean enabled) { 238 mIsEnabled = enabled; 239 return this; 240 } 241 242 /** 243 * Sets whether or not the row should be clickable while disabled. 244 */ setClickableWhileDisabled(boolean clickable)245 public Builder setClickableWhileDisabled(boolean clickable) { 246 mIsClickableWhileDisabled = clickable; 247 return this; 248 } 249 250 /** 251 * Sets the row icon. 252 */ setIcon(@ullable Icon icon)253 public Builder setIcon(@Nullable Icon icon) { 254 mStartIcon = icon; 255 return this; 256 } 257 258 /** 259 * Sets whether or not the row icon is tintable. 260 */ setIconTintable(boolean tintable)261 public Builder setIconTintable(boolean tintable) { 262 mIsStartIconTintable = tintable; 263 return this; 264 } 265 266 /** 267 * Adds a {@link QCSlider} to the slider area. 268 */ addSlider(@ullable QCSlider slider)269 public Builder addSlider(@Nullable QCSlider slider) { 270 mSlider = slider; 271 return this; 272 } 273 274 /** 275 * Sets the PendingIntent to be sent when the row is clicked. 276 */ setPrimaryAction(@ullable PendingIntent action)277 public Builder setPrimaryAction(@Nullable PendingIntent action) { 278 mPrimaryAction = action; 279 return this; 280 } 281 282 /** 283 * Sets the PendingIntent to be sent when the action item is clicked while disabled. 284 */ setDisabledClickAction(@ullable PendingIntent action)285 public Builder setDisabledClickAction(@Nullable PendingIntent action) { 286 mDisabledClickAction = action; 287 return this; 288 } 289 290 /** 291 * Adds a {@link QCActionItem} to the start items area. 292 */ addStartItem(@onNull QCActionItem item)293 public Builder addStartItem(@NonNull QCActionItem item) { 294 mStartItems.add(item); 295 return this; 296 } 297 298 /** 299 * Adds a {@link QCActionItem} to the end items area. 300 */ addEndItem(@onNull QCActionItem item)301 public Builder addEndItem(@NonNull QCActionItem item) { 302 mEndItems.add(item); 303 return this; 304 } 305 306 /** 307 * Builds the final {@link QCRow}. 308 */ build()309 public QCRow build() { 310 return new QCRow(mTitle, mSubtitle, mIsEnabled, mIsClickableWhileDisabled, 311 mPrimaryAction, mDisabledClickAction, mStartIcon, mIsStartIconTintable, 312 mSlider, mStartItems, mEndItems); 313 } 314 } 315 } 316