blob: 3b5ce87ebfb07688216398278e23418d9a1b0a25 [file] [log] [blame]
Ben Kwad8391492015-12-17 10:37:00 -08001/*
2 * Copyright (C) 2015 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
17package com.android.documentsui.dirlist;
18
Ben Kwad8391492015-12-17 10:37:00 -080019import android.content.Context;
20import android.database.Cursor;
Ben Kwa0436a752016-01-15 10:43:24 -080021import android.graphics.Rect;
Ben Kwad8391492015-12-17 10:37:00 -080022import android.support.annotation.Nullable;
23import android.support.v7.widget.RecyclerView;
24import android.view.KeyEvent;
25import android.view.LayoutInflater;
Ben Kwa0436a752016-01-15 10:43:24 -080026import android.view.MotionEvent;
Ben Kwad8391492015-12-17 10:37:00 -080027import android.view.View;
28import android.view.ViewGroup;
29
Ben Kwa0436a752016-01-15 10:43:24 -080030import com.android.documentsui.Events;
Ben Kwad8391492015-12-17 10:37:00 -080031import com.android.documentsui.R;
32import com.android.documentsui.State;
33
34public abstract class DocumentHolder
35 extends RecyclerView.ViewHolder
36 implements View.OnKeyListener {
37
38 public @Nullable String modelId;
39
40 final int mSelectedItemColor;
41 final int mDefaultItemColor;
42 final boolean mAlwaysShowSummary;
43 final Context mContext;
Ben Kwad8391492015-12-17 10:37:00 -080044
Ben Kwa0436a752016-01-15 10:43:24 -080045 DocumentHolder.EventListener mEventListener;
Ben Kwad8391492015-12-17 10:37:00 -080046 private View.OnKeyListener mKeyListener;
Ben Kwa0436a752016-01-15 10:43:24 -080047 private View mSelectionHotspot;
Ben Kwad8391492015-12-17 10:37:00 -080048
Ben Kwaf8a51f62015-12-22 14:03:30 -080049 public DocumentHolder(Context context, ViewGroup parent, int layout) {
50 this(context, inflateLayout(context, parent, layout));
Ben Kwad8391492015-12-17 10:37:00 -080051 }
52
Ben Kwaf8a51f62015-12-22 14:03:30 -080053 public DocumentHolder(Context context, View item) {
Ben Kwad8391492015-12-17 10:37:00 -080054 super(item);
55
56 itemView.setOnKeyListener(this);
57
58 mContext = context;
59
60 mDefaultItemColor = context.getColor(R.color.item_doc_background);
61 mSelectedItemColor = context.getColor(R.color.item_doc_background_selected);
62 mAlwaysShowSummary = context.getResources().getBoolean(R.bool.always_show_summary);
Ben Kwa0436a752016-01-15 10:43:24 -080063
64 mSelectionHotspot = itemView.findViewById(R.id.icon_check);
Ben Kwad8391492015-12-17 10:37:00 -080065 }
66
67 /**
68 * Binds the view to the given item data.
69 * @param cursor
70 * @param modelId
71 * @param state
72 */
73 public abstract void bind(Cursor cursor, String modelId, State state);
74
Ben Kwae3dfebf2016-02-18 16:45:45 -080075 /**
76 * Makes the associated item view appear selected. Note that this merely affects the appearance
77 * of the view, it doesn't actually select the item.
78 *
79 * @param selected
80 */
Ben Kwad8391492015-12-17 10:37:00 -080081 public void setSelected(boolean selected) {
82 itemView.setActivated(selected);
83 itemView.setBackgroundColor(selected ? mSelectedItemColor : mDefaultItemColor);
84 }
85
Ben Kwae3dfebf2016-02-18 16:45:45 -080086 /**
87 * Highlights the associated item view.
88 * @param highlighted
89 */
90 public void setHighlighted(boolean highlighted) {
91 itemView.setBackgroundColor(highlighted ? mSelectedItemColor : mDefaultItemColor);
92 }
93
Ben Kwad8391492015-12-17 10:37:00 -080094 @Override
95 public boolean onKey(View v, int keyCode, KeyEvent event) {
Ben Kwa0436a752016-01-15 10:43:24 -080096 // Event listener should always be set.
Steve McKaya1f76802016-02-25 13:34:03 -080097 assert(mEventListener != null);
98
Ben Kwa67924892016-01-27 09:58:36 -080099 return mEventListener.onKey(this, keyCode, event);
Ben Kwad8391492015-12-17 10:37:00 -0800100 }
101
Ben Kwa0436a752016-01-15 10:43:24 -0800102 public void addEventListener(DocumentHolder.EventListener listener) {
Ben Kwad8391492015-12-17 10:37:00 -0800103 // Just handle one for now; switch to a list if necessary.
Steve McKaya1f76802016-02-25 13:34:03 -0800104 assert(mEventListener == null);
Ben Kwa0436a752016-01-15 10:43:24 -0800105 mEventListener = listener;
Ben Kwad8391492015-12-17 10:37:00 -0800106 }
107
108 public void addOnKeyListener(View.OnKeyListener listener) {
109 // Just handle one for now; switch to a list if necessary.
Steve McKaya1f76802016-02-25 13:34:03 -0800110 assert(mKeyListener == null);
Ben Kwad8391492015-12-17 10:37:00 -0800111 mKeyListener = listener;
112 }
113
114 public void setEnabled(boolean enabled) {
115 setEnabledRecursive(itemView, enabled);
116 }
117
Ben Kwa0436a752016-01-15 10:43:24 -0800118 public boolean onSingleTapUp(MotionEvent event) {
119 if (Events.isMouseEvent(event)) {
120 // Mouse clicks select.
121 // TODO: && input.isPrimaryButtonPressed(), but it is returning false.
122 if (mEventListener != null) {
123 return mEventListener.onSelect(this);
124 }
125 } else if (Events.isTouchEvent(event)) {
126 // Touch events select if they occur in the selection hotspot, otherwise they activate.
127 if (mEventListener == null) {
128 return false;
129 }
130
131 // Do everything in global coordinates - it makes things simpler.
132 Rect rect = new Rect();
133 mSelectionHotspot.getGlobalVisibleRect(rect);
134
135 // If the tap occurred within the icon rect, consider it a selection.
136 if (rect.contains((int)event.getRawX(), (int)event.getRawY())) {
137 return mEventListener.onSelect(this);
138 } else {
139 return mEventListener.onActivate(this);
140 }
141 }
142 return false;
143 }
144
Ben Kwad8391492015-12-17 10:37:00 -0800145 static void setEnabledRecursive(View itemView, boolean enabled) {
146 if (itemView == null) return;
147 if (itemView.isEnabled() == enabled) return;
148 itemView.setEnabled(enabled);
149
150 if (itemView instanceof ViewGroup) {
151 final ViewGroup vg = (ViewGroup) itemView;
152 for (int i = vg.getChildCount() - 1; i >= 0; i--) {
153 setEnabledRecursive(vg.getChildAt(i), enabled);
154 }
155 }
156 }
157
158 private static View inflateLayout(Context context, ViewGroup parent, int layout) {
159 final LayoutInflater inflater = LayoutInflater.from(context);
160 return inflater.inflate(layout, parent, false);
161 }
162
Ben Kwa0436a752016-01-15 10:43:24 -0800163 /**
164 * Implement this in order to be able to respond to events coming from DocumentHolders.
165 */
166 interface EventListener {
167 /**
Ben Kwa67924892016-01-27 09:58:36 -0800168 * Handles activation events on the document holder.
169 *
Ben Kwa0436a752016-01-15 10:43:24 -0800170 * @param doc The target DocumentHolder
171 * @return Whether the event was handled.
172 */
173 public boolean onActivate(DocumentHolder doc);
174
175 /**
Ben Kwa67924892016-01-27 09:58:36 -0800176 * Handles selection events on the document holder.
177 *
Ben Kwa0436a752016-01-15 10:43:24 -0800178 * @param doc The target DocumentHolder
179 * @return Whether the event was handled.
180 */
181 public boolean onSelect(DocumentHolder doc);
Ben Kwa67924892016-01-27 09:58:36 -0800182
183 /**
184 * Handles key events on the document holder.
185 *
186 * @param doc The target DocumentHolder.
187 * @param keyCode Key code for the event.
188 * @param event KeyEvent for the event.
189 * @return Whether the event was handled.
190 */
191 public boolean onKey(DocumentHolder doc, int keyCode, KeyEvent event);
Ben Kwad8391492015-12-17 10:37:00 -0800192 }
193}