OSDN Git Service

Various small changes and tweaks
[android-x86/packages-apps-Taskbar.git] / app / src / main / java / com / farmerbb / taskbar / adapter / StartMenuAdapter.java
1 /* Copyright 2016 Braden Farmer
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 package com.farmerbb.taskbar.adapter;
17
18 import android.content.ComponentName;
19 import android.content.Context;
20 import android.content.Intent;
21 import android.content.SharedPreferences;
22 import android.content.pm.ActivityInfo;
23 import android.graphics.Color;
24 import android.graphics.Rect;
25 import android.graphics.Typeface;
26 import android.os.Build;
27 import android.os.Handler;
28 import android.support.annotation.NonNull;
29 import android.support.v4.content.ContextCompat;
30 import android.support.v4.content.LocalBroadcastManager;
31 import android.support.v4.graphics.ColorUtils;
32 import android.util.DisplayMetrics;
33 import android.view.LayoutInflater;
34 import android.view.MotionEvent;
35 import android.view.PointerIcon;
36 import android.view.View;
37 import android.view.ViewGroup;
38 import android.widget.ArrayAdapter;
39 import android.widget.ImageView;
40 import android.widget.LinearLayout;
41 import android.widget.SectionIndexer;
42 import android.widget.TextView;
43
44 import com.farmerbb.taskbar.R;
45 import com.farmerbb.taskbar.activity.ContextMenuActivity;
46 import com.farmerbb.taskbar.activity.dark.ContextMenuActivityDark;
47 import com.farmerbb.taskbar.util.AppEntry;
48 import com.farmerbb.taskbar.util.ApplicationType;
49 import com.farmerbb.taskbar.util.FreeformHackHelper;
50 import com.farmerbb.taskbar.util.TopApps;
51 import com.farmerbb.taskbar.util.U;
52
53 import java.util.ArrayList;
54 import java.util.Arrays;
55 import java.util.List;
56
57 public class StartMenuAdapter extends ArrayAdapter<AppEntry> implements SectionIndexer {
58
59     private boolean isGrid = false;
60     private final List<Character> sections = new ArrayList<>();
61
62     private final List<Character> lowercase = Arrays.asList(
63             'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
64             'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
65     );
66
67     private final List<Character> uppercase = Arrays.asList(
68             'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
69             'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
70     );
71
72     public StartMenuAdapter(Context context, int layout, List<AppEntry> list) {
73         super(context, layout, list);
74         isGrid = layout == R.layout.row_alt;
75
76         updateList(list, true);
77     }
78
79     @Override
80     public @NonNull View getView(int position, View convertView, final @NonNull ViewGroup parent) {
81         // Check if an existing view is being reused, otherwise inflate the view
82         if(convertView == null)
83             convertView = LayoutInflater.from(getContext()).inflate(isGrid ? R.layout.row_alt : R.layout.row, parent, false);
84
85         final AppEntry entry = getItem(position);
86         assert entry != null;
87
88         final SharedPreferences pref = U.getSharedPreferences(getContext());
89
90         TextView textView = U.findViewById(convertView, R.id.name);
91         textView.setText(entry.getLabel());
92         textView.setTypeface(null, isTopApp(entry) ? Typeface.BOLD : Typeface.NORMAL);
93
94         switch(pref.getString("theme", "light")) {
95             case "light":
96                 textView.setTextColor(ContextCompat.getColor(getContext(), R.color.text_color));
97                 break;
98             case "dark":
99                 textView.setTextColor(ContextCompat.getColor(getContext(), R.color.text_color_dark));
100                 break;
101         }
102
103         ImageView imageView = U.findViewById(convertView, R.id.icon);
104         imageView.setImageDrawable(entry.getIcon(getContext()));
105
106         LinearLayout layout = U.findViewById(convertView, R.id.entry);
107         layout.setOnClickListener(view -> {
108             LocalBroadcastManager.getInstance(getContext()).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_START_MENU"));
109             U.launchApp(getContext(), entry.getPackageName(), entry.getComponentName(), entry.getUserId(getContext()), null, false, false);
110         });
111
112         layout.setOnLongClickListener(view -> {
113             int[] location = new int[2];
114             view.getLocationOnScreen(location);
115             openContextMenu(entry, location);
116             return true;
117         });
118
119         layout.setOnGenericMotionListener((view, motionEvent) -> {
120             int action = motionEvent.getAction();
121
122             if(action == MotionEvent.ACTION_BUTTON_PRESS
123                     && motionEvent.getButtonState() == MotionEvent.BUTTON_SECONDARY) {
124                 int[] location = new int[2];
125                 view.getLocationOnScreen(location);
126                 openContextMenu(entry, location);
127             }
128
129             if(action == MotionEvent.ACTION_SCROLL && U.visualFeedbackEnabled(getContext()))
130                 view.setBackgroundColor(0);
131
132             return false;
133         });
134
135         if(U.visualFeedbackEnabled(getContext())) {
136             layout.setOnHoverListener((v, event) -> {
137                 if(event.getAction() == MotionEvent.ACTION_HOVER_ENTER) {
138                     int backgroundTint = pref.getBoolean("transparent_start_menu", false)
139                             ? U.getAccentColor(getContext())
140                             : U.getBackgroundTint(getContext());
141
142                     //noinspection ResourceAsColor
143                     backgroundTint = ColorUtils.setAlphaComponent(backgroundTint, Color.alpha(backgroundTint) / 2);
144                     v.setBackgroundColor(backgroundTint);
145                 }
146
147                 if(event.getAction() == MotionEvent.ACTION_HOVER_EXIT)
148                     v.setBackgroundColor(0);
149
150                 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
151                     v.setPointerIcon(PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT));
152
153                 return false;
154             });
155         }
156
157         if(pref.getBoolean("visual_feedback", true)) {
158             layout.setOnTouchListener((v, event) -> {
159                 v.setAlpha(event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE ? 0.5f : 1);
160                 return false;
161             });
162         }
163
164         return convertView;
165     }
166
167     private boolean isTopApp(AppEntry entry) {
168         Intent intent = new Intent();
169         intent.setComponent(ComponentName.unflattenFromString(entry.getComponentName()));
170         ActivityInfo activityInfo = intent.resolveActivityInfo(getContext().getPackageManager(), 0);
171
172         if(activityInfo != null) {
173             TopApps topApps = TopApps.getInstance(getContext());
174             return topApps.isTopApp(activityInfo.packageName + "/" + activityInfo.name) || topApps.isTopApp(activityInfo.name);
175         }
176
177         return false;
178     }
179
180     @SuppressWarnings("deprecation")
181     private void openContextMenu(final AppEntry entry, final int[] location) {
182         LocalBroadcastManager.getInstance(getContext()).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_START_MENU_NO_RESET"));
183
184         new Handler().postDelayed(() -> {
185             SharedPreferences pref = U.getSharedPreferences(getContext());
186             Intent intent = null;
187
188             switch(pref.getString("theme", "light")) {
189                 case "light":
190                     intent = new Intent(getContext(), ContextMenuActivity.class);
191                     break;
192                 case "dark":
193                     intent = new Intent(getContext(), ContextMenuActivityDark.class);
194                     break;
195             }
196
197             if(intent != null) {
198                 intent.putExtra("package_name", entry.getPackageName());
199                 intent.putExtra("app_name", entry.getLabel());
200                 intent.putExtra("component_name", entry.getComponentName());
201                 intent.putExtra("user_id", entry.getUserId(getContext()));
202                 intent.putExtra("launched_from_start_menu", true);
203                 intent.putExtra("x", location[0]);
204                 intent.putExtra("y", location[1]);
205                 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
206             }
207
208             if(U.hasFreeformSupport(getContext()) && FreeformHackHelper.getInstance().isInFreeformWorkspace()) {
209                 DisplayMetrics metrics = U.getRealDisplayMetrics(getContext());
210
211                 if(intent != null && U.hasBrokenSetLaunchBoundsApi())
212                     intent.putExtra("context_menu_fix", true);
213
214                 getContext().startActivity(intent, U.getActivityOptions(ApplicationType.CONTEXT_MENU).setLaunchBounds(new Rect(0, 0, metrics.widthPixels, metrics.heightPixels)).toBundle());
215             } else
216                 getContext().startActivity(intent);
217         }, shouldDelay() ? 100 : 0);
218     }
219
220     private boolean shouldDelay() {
221         SharedPreferences pref = U.getSharedPreferences(getContext());
222         return U.hasFreeformSupport(getContext())
223                 && pref.getBoolean("freeform_hack", false)
224                 && !FreeformHackHelper.getInstance().isFreeformHackActive();
225     }
226
227     public void updateList(List<AppEntry> list) {
228         updateList(list, false);
229     }
230
231     private void updateList(List<AppEntry> list, boolean firstUpdate) {
232         if(!firstUpdate) {
233             clear();
234             sections.clear();
235
236             addAll(list);
237         }
238
239         SharedPreferences pref = U.getSharedPreferences(getContext());
240         if(pref.getBoolean("scrollbar", false)) {
241             for(AppEntry entry : list) {
242                 char firstLetter = getSectionForAppEntry(entry);
243                 if(!sections.contains(firstLetter))
244                     sections.add(firstLetter);
245             }
246         }
247     }
248
249     private char getSectionForAppEntry(AppEntry entry) {
250         if(isTopApp(entry))
251             return '\u2605';
252
253         char origChar = entry.getLabel().charAt(0);
254         if(uppercase.contains(origChar))
255             return origChar;
256
257         if(lowercase.contains(origChar))
258             return uppercase.get(lowercase.indexOf(origChar));
259
260         return '#';
261     }
262
263     @Override
264     public int getPositionForSection(int section) {
265         for(int i = 0; i < getCount(); i++) {
266             if(sections.get(section) == getSectionForAppEntry(getItem(i)))
267                 return i;
268         }
269
270         return 0;
271     }
272
273     @Override
274     public int getSectionForPosition(int position) {
275         for(int i = 0; i < sections.size(); i++) {
276             if(sections.get(i) == getSectionForAppEntry(getItem(position)))
277                 return i;
278         }
279
280         return 0;
281     }
282
283     @Override
284     public Object[] getSections() {
285         return sections.toArray();
286     }
287 }