1 /* 2 * Copyright (C) 2018 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.documentsui.dirlist; 18 19 import static com.android.documentsui.DevicePolicyResources.Drawables.Style.SOLID_NOT_COLORED; 20 import static com.android.documentsui.DevicePolicyResources.Drawables.WORK_PROFILE_ICON; 21 import static com.android.documentsui.base.DocumentInfo.getCursorInt; 22 import static com.android.documentsui.base.DocumentInfo.getCursorLong; 23 import static com.android.documentsui.base.DocumentInfo.getCursorString; 24 25 import android.app.admin.DevicePolicyManager; 26 import android.content.Context; 27 import android.database.Cursor; 28 import android.graphics.drawable.Drawable; 29 import android.os.Build; 30 import android.provider.DocumentsContract.Document; 31 import android.text.format.Formatter; 32 import android.view.MotionEvent; 33 import android.view.View; 34 import android.view.ViewGroup; 35 import android.widget.ImageView; 36 37 import androidx.annotation.RequiresApi; 38 39 import com.android.documentsui.R; 40 import com.android.documentsui.base.DocumentInfo; 41 import com.android.documentsui.base.Shared; 42 import com.android.documentsui.base.UserId; 43 import com.android.documentsui.roots.RootCursorWrapper; 44 import com.android.documentsui.ui.Views; 45 import com.android.modules.utils.build.SdkLevel; 46 47 import java.util.function.Function; 48 49 final class GridPhotoHolder extends DocumentHolder { 50 51 private final ImageView mIconMimeLg; 52 private final ImageView mIconThumb; 53 private final ImageView mIconCheck; 54 private final IconHelper mIconHelper; 55 private final View mPreviewIcon; 56 private final View mIconBriefcase; 57 58 // This is used in as a convenience in our bind method. 59 private final DocumentInfo mDoc = new DocumentInfo(); 60 GridPhotoHolder(Context context, ViewGroup parent, IconHelper iconHelper)61 public GridPhotoHolder(Context context, ViewGroup parent, IconHelper iconHelper) { 62 super(context, parent, R.layout.item_photo_grid); 63 64 mIconMimeLg = (ImageView) itemView.findViewById(R.id.icon_mime_lg); 65 mIconThumb = (ImageView) itemView.findViewById(R.id.icon_thumb); 66 mIconCheck = (ImageView) itemView.findViewById(R.id.icon_check); 67 mIconBriefcase = itemView.findViewById(R.id.icon_briefcase); 68 mPreviewIcon = itemView.findViewById(R.id.preview_icon); 69 70 mIconHelper = iconHelper; 71 72 if (SdkLevel.isAtLeastT()) { 73 setUpdatableWorkProfileIcon(context); 74 } 75 } 76 77 @RequiresApi(Build.VERSION_CODES.TIRAMISU) setUpdatableWorkProfileIcon(Context context)78 private void setUpdatableWorkProfileIcon(Context context) { 79 DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 80 Drawable drawable = dpm.getResources().getDrawable( 81 WORK_PROFILE_ICON, SOLID_NOT_COLORED, () -> 82 context.getDrawable(R.drawable.ic_briefcase)); 83 ImageView icon = (ImageView) mIconBriefcase.findViewById(R.id.icon_id); 84 85 icon.setImageDrawable(drawable); 86 } 87 88 @Override setSelected(boolean selected, boolean animate)89 public void setSelected(boolean selected, boolean animate) { 90 // We always want to make sure our check box disappears if we're not selected, 91 // even if the item is disabled. This is because this object can be reused 92 // and this method will be called to setup initial state. 93 float checkAlpha = selected ? 1f : 0f; 94 if (animate) { 95 fade(mIconCheck, checkAlpha).start(); 96 } else { 97 mIconCheck.setAlpha(checkAlpha); 98 } 99 100 // But it should be an error to be set to selected && be disabled. 101 if (!itemView.isEnabled()) { 102 assert (!selected); 103 return; 104 } 105 106 super.setSelected(selected, animate); 107 } 108 109 @Override setEnabled(boolean enabled)110 public void setEnabled(boolean enabled) { 111 super.setEnabled(enabled); 112 113 float imgAlpha = enabled ? 1f : DISABLED_ALPHA; 114 115 mIconMimeLg.setAlpha(imgAlpha); 116 mIconThumb.setAlpha(imgAlpha); 117 } 118 119 @Override bindPreviewIcon(boolean show, Function<View, Boolean> clickCallback)120 public void bindPreviewIcon(boolean show, Function<View, Boolean> clickCallback) { 121 mPreviewIcon.setVisibility(show ? View.VISIBLE : View.GONE); 122 if (show) { 123 mPreviewIcon.setContentDescription( 124 getPreviewIconContentDescription( 125 mIconHelper.shouldShowBadge(mDoc.userId.getIdentifier()), 126 mDoc.displayName)); 127 mPreviewIcon.setAccessibilityDelegate(new PreviewAccessibilityDelegate(clickCallback)); 128 } 129 } 130 131 @Override bindBriefcaseIcon(boolean show)132 public void bindBriefcaseIcon(boolean show) { 133 mIconBriefcase.setVisibility(show ? View.VISIBLE : View.GONE); 134 } 135 136 @Override inDragRegion(MotionEvent event)137 public boolean inDragRegion(MotionEvent event) { 138 // Entire grid box should be draggable 139 return true; 140 } 141 142 @Override inSelectRegion(MotionEvent event)143 public boolean inSelectRegion(MotionEvent event) { 144 // Photo gird should not have any select region. 145 return false; 146 } 147 148 @Override inPreviewIconRegion(MotionEvent event)149 public boolean inPreviewIconRegion(MotionEvent event) { 150 return Views.isEventOver(event, itemView.getParent(), mPreviewIcon); 151 } 152 153 /** 154 * Bind this view to the given document for display. 155 * @param cursor Pointing to the item to be bound. 156 * @param modelId The model ID of the item. 157 */ 158 @Override bind(Cursor cursor, String modelId)159 public void bind(Cursor cursor, String modelId) { 160 assert (cursor != null); 161 162 mModelId = modelId; 163 164 mDoc.updateFromCursor(cursor, 165 UserId.of(getCursorInt(cursor, RootCursorWrapper.COLUMN_USER_ID)), 166 getCursorString(cursor, RootCursorWrapper.COLUMN_AUTHORITY)); 167 168 mIconHelper.stopLoading(mIconThumb); 169 170 mIconMimeLg.animate().cancel(); 171 mIconMimeLg.setAlpha(1f); 172 mIconThumb.animate().cancel(); 173 mIconThumb.setAlpha(0f); 174 175 mIconHelper.load(mDoc, mIconThumb, mIconMimeLg, null); 176 177 final String docSize = 178 Formatter.formatFileSize(mContext, getCursorLong(cursor, Document.COLUMN_SIZE)); 179 final String docDate = Shared.formatTime(mContext, mDoc.lastModified); 180 if (mIconHelper.shouldShowBadge(mDoc.userId.getIdentifier())) { 181 itemView.setContentDescription((mContext.getText(R.string.a11y_work) + ", ") 182 + mDoc.displayName + ", " + docSize + ", " + docDate); 183 } else { 184 itemView.setContentDescription(mDoc.displayName + ", " + docSize + ", " + docDate); 185 } 186 } 187 } 188