OSDN Git Service

Extract context_menu_fix to constant
[android-x86/packages-apps-Taskbar.git] / app / src / main / java / com / farmerbb / taskbar / ui / DashboardController.java
1 /* Based on code by Leonardo Fischer
2  * See https://github.com/lgfischer/WidgetHostExample
3  *
4  * Copyright 2016 Braden Farmer
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 package com.farmerbb.taskbar.ui;
20
21 import android.animation.Animator;
22 import android.animation.AnimatorListenerAdapter;
23 import android.annotation.SuppressLint;
24 import android.annotation.TargetApi;
25 import android.appwidget.AppWidgetHost;
26 import android.appwidget.AppWidgetHostView;
27 import android.appwidget.AppWidgetManager;
28 import android.appwidget.AppWidgetProviderInfo;
29 import android.content.BroadcastReceiver;
30 import android.content.ComponentName;
31 import android.content.Context;
32 import android.content.Intent;
33 import android.content.SharedPreferences;
34 import android.content.pm.PackageManager;
35 import android.content.res.Configuration;
36 import android.graphics.Color;
37 import android.graphics.ColorMatrix;
38 import android.graphics.ColorMatrixColorFilter;
39 import android.graphics.drawable.Drawable;
40 import android.os.Build;
41 import android.os.Bundle;
42 import android.os.Handler;
43 import android.os.Process;
44
45 import androidx.annotation.NonNull;
46 import androidx.annotation.VisibleForTesting;
47 import androidx.core.graphics.ColorUtils;
48 import android.util.SparseArray;
49 import android.view.MotionEvent;
50 import android.view.PointerIcon;
51 import android.view.View;
52 import android.view.ViewGroup;
53 import android.view.WindowManager;
54 import android.widget.FrameLayout;
55 import android.widget.ImageView;
56 import android.widget.LinearLayout;
57 import android.widget.TextView;
58 import android.widget.Toast;
59
60 import com.farmerbb.taskbar.R;
61 import com.farmerbb.taskbar.activity.DashboardActivity;
62 import com.farmerbb.taskbar.helper.LauncherHelper;
63 import com.farmerbb.taskbar.util.Constants;
64 import com.farmerbb.taskbar.util.TaskbarPosition;
65 import com.farmerbb.taskbar.helper.DashboardHelper;
66 import com.farmerbb.taskbar.widget.DashboardCell;
67 import com.farmerbb.taskbar.helper.FreeformHackHelper;
68 import com.farmerbb.taskbar.util.U;
69
70 import java.util.List;
71
72 import static com.farmerbb.taskbar.util.Constants.*;
73
74 public class DashboardController extends UIController {
75
76     private AppWidgetManager mAppWidgetManager;
77     private AppWidgetHost mAppWidgetHost;
78
79     private LinearLayout layout;
80
81     private SparseArray<DashboardCell> cells = new SparseArray<>();
82     private SparseArray<AppWidgetHostView> widgets = new SparseArray<>();
83
84     private final int APPWIDGET_HOST_ID = 123;
85
86     private int columns;
87     private int rows;
88     private int maxSize;
89     private int previouslySelectedCell = -1;
90
91     private View.OnClickListener ocl = view -> toggleDashboard();
92
93     private View.OnClickListener cellOcl = view -> cellClick(view, true);
94
95     private View.OnHoverListener cellOhl = (v, event) -> {
96         cellClick(v, false);
97
98         if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
99             v.setPointerIcon(PointerIcon.getSystemIcon(context, PointerIcon.TYPE_DEFAULT));
100
101         return false;
102     };
103
104     private View.OnLongClickListener olcl = v -> {
105         cellLongClick(v);
106         return true;
107     };
108
109     private View.OnGenericMotionListener ogml = (view, motionEvent) -> {
110         if(motionEvent.getAction() == MotionEvent.ACTION_BUTTON_PRESS
111                 && motionEvent.getButtonState() == MotionEvent.BUTTON_SECONDARY)
112             cellLongClick(view);
113
114         return false;
115     };
116
117     private DashboardCell.OnInterceptedLongPressListener listener = this::cellLongClick;
118
119     private BroadcastReceiver toggleReceiver = new BroadcastReceiver() {
120         @Override
121         public void onReceive(Context context, Intent intent) {
122             toggleDashboard();
123         }
124     };
125
126     private BroadcastReceiver addWidgetReceiver = new BroadcastReceiver() {
127         @Override
128         public void onReceive(Context context, Intent intent) {
129             fadeIn();
130             addWidget(intent);
131         }
132     };
133
134     private BroadcastReceiver removeWidgetReceiver = new BroadcastReceiver() {
135         @Override
136         public void onReceive(Context context, Intent intent) {
137             fadeIn();
138
139             if(intent.hasExtra(EXTRA_CELL_ID)) {
140                 int cellId = intent.getExtras().getInt(EXTRA_CELL_ID, -1);
141
142                 removeWidget(cellId, false);
143             }
144         }
145     };
146
147     private BroadcastReceiver hideReceiver = new BroadcastReceiver() {
148         @Override
149         public void onReceive(Context context, Intent intent) {
150             hideDashboard();
151         }
152     };
153
154     public DashboardController(Context context) {
155         super(context);
156     }
157
158     @TargetApi(Build.VERSION_CODES.M)
159     @Override
160     public void onCreateHost(UIHost host) {
161         if(U.getBooleanPrefWithDefault(context, PREF_DASHBOARD))
162             init(context, host, () -> drawDashboard(host));
163         else
164             host.terminate();
165     }
166
167     @SuppressLint("RtlHardcoded")
168     private void drawDashboard(UIHost host) {
169         final ViewParams params = new ViewParams(
170                 WindowManager.LayoutParams.MATCH_PARENT,
171                 WindowManager.LayoutParams.MATCH_PARENT,
172                 -1,
173                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
174                 getBottomMargin(context, host)
175         );
176
177         // Initialize views
178         layout = new LinearLayout(context);
179         layout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
180         layout.setVisibility(View.GONE);
181         layout.setAlpha(0);
182
183         SharedPreferences pref = U.getSharedPreferences(context);
184         int width = U.getIntPrefWithDefault(context, PREF_DASHBOARD_WIDTH);
185         int height = U.getIntPrefWithDefault(context, PREF_DASHBOARD_HEIGHT);
186
187         int orientation = U.getDisplayOrientation(context);
188         boolean isPortrait = orientation == Configuration.ORIENTATION_PORTRAIT;
189         boolean isLandscape = orientation == Configuration.ORIENTATION_LANDSCAPE;
190
191         if(isPortrait) {
192             columns = height;
193             rows = width;
194         }
195
196         if(isLandscape) {
197             columns = width;
198             rows = height;
199         }
200
201         maxSize = columns * rows;
202
203         int backgroundTint = U.getBackgroundTint(context);
204         int accentColor = U.getAccentColor(context);
205         int accentColorAlt = accentColor;
206         accentColorAlt = ColorUtils.setAlphaComponent(accentColorAlt, Color.alpha(accentColorAlt) / 3);
207
208         int cellCount = 0;
209
210         for(int i = 0; i < columns; i++) {
211             LinearLayout layout2 = new LinearLayout(context);
212             layout2.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 1));
213             layout2.setOrientation(LinearLayout.VERTICAL);
214
215             for(int j = 0; j < rows; j++) {
216                 DashboardCell cellLayout = (DashboardCell) View.inflate(context, R.layout.tb_dashboard, null);
217                 cellLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 1));
218                 cellLayout.setBackgroundColor(backgroundTint);
219                 cellLayout.setOnClickListener(cellOcl);
220                 cellLayout.setOnHoverListener(cellOhl);
221                 cellLayout.setFocusable(false);
222
223                 TextView empty = cellLayout.findViewById(R.id.empty);
224                 empty.setBackgroundColor(accentColorAlt);
225                 empty.setTextColor(accentColor);
226
227                 Bundle bundle = new Bundle();
228                 bundle.putInt(EXTRA_CELL_ID, cellCount);
229
230                 cellLayout.setTag(bundle);
231                 cells.put(cellCount, cellLayout);
232                 cellCount++;
233
234                 layout2.addView(cellLayout);
235             }
236
237             layout.addView(layout2);
238         }
239
240         mAppWidgetManager = AppWidgetManager.getInstance(context);
241         mAppWidgetHost = new AppWidgetHost(context, APPWIDGET_HOST_ID);
242         mAppWidgetHost.startListening();
243
244         for(int i = 0; i < maxSize; i++) {
245             int appWidgetId = pref.getInt(PREF_DASHBOARD_WIDGET_PREFIX + i, -1);
246             if(appWidgetId != -1)
247                 addWidget(appWidgetId, i, false);
248             else if (pref.getBoolean(
249                     PREF_DASHBOARD_WIDGET_PREFIX
250                             + i
251                             + PREF_DASHBOARD_WIDGET_PLACEHOLDER_SUFFIX,
252                     false)) {
253                 addPlaceholder(i);
254             }
255         }
256
257         mAppWidgetHost.stopListening();
258
259         U.registerReceiver(context, toggleReceiver, ACTION_TOGGLE_DASHBOARD);
260         U.registerReceiver(context, addWidgetReceiver, ACTION_ADD_WIDGET_COMPLETED);
261         U.registerReceiver(context, removeWidgetReceiver, ACTION_REMOVE_WIDGET_COMPLETED);
262         U.registerReceiver(context, hideReceiver, ACTION_HIDE_DASHBOARD);
263
264         host.addView(layout, params);
265
266         new Handler().postDelayed(() ->
267                 updatePaddingSize(
268                         context,
269                         layout,
270                         TaskbarPosition.getTaskbarPosition(context)
271                 ),
272                 100
273         );
274     }
275
276     @VisibleForTesting
277     void updatePaddingSize(Context context, LinearLayout layout, String position) {
278         int paddingSize = context.getResources().getDimensionPixelSize(R.dimen.tb_icon_size);
279
280         switch(position) {
281             case POSITION_TOP_VERTICAL_LEFT:
282             case POSITION_BOTTOM_VERTICAL_LEFT:
283                 layout.setPadding(paddingSize, 0, 0, 0);
284                 break;
285             case POSITION_TOP_LEFT:
286             case POSITION_TOP_RIGHT:
287                 layout.setPadding(0, paddingSize, 0, 0);
288                 break;
289             case POSITION_TOP_VERTICAL_RIGHT:
290             case POSITION_BOTTOM_VERTICAL_RIGHT:
291                 layout.setPadding(0, 0, paddingSize, 0);
292                 break;
293             case POSITION_BOTTOM_LEFT:
294             case POSITION_BOTTOM_RIGHT:
295                 layout.setPadding(0, 0, 0, paddingSize);
296                 break;
297         }
298     }
299
300     private void toggleDashboard() {
301         if(layout.getVisibility() == View.GONE)
302             showDashboard();
303         else
304             hideDashboard();
305     }
306
307     @TargetApi(Build.VERSION_CODES.N)
308     private void showDashboard() {
309         if(layout.getVisibility() == View.GONE) {
310             layout.setOnClickListener(ocl);
311             fadeIn();
312
313             U.sendBroadcast(context, ACTION_DASHBOARD_APPEARING);
314             U.sendBroadcast(context, ACTION_HIDE_START_MENU);
315
316             boolean inFreeformMode = FreeformHackHelper.getInstance().isInFreeformWorkspace();
317
318             Intent intent = U.getThemedIntent(context, DashboardActivity.class);
319             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
320             intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
321
322             if (inFreeformMode) {
323                 if (U.hasBrokenSetLaunchBoundsApi()) {
324                     intent.putExtra(EXTRA_CONTEXT_MENU_FIX, true);
325                 }
326
327                 U.startActivityMaximized(context, intent);
328             } else {
329                 context.startActivity(intent);
330             }
331
332             for(int i = 0; i < maxSize; i++) {
333                 final DashboardCell cellLayout = cells.get(i);
334                 final AppWidgetHostView hostView = widgets.get(i);
335
336                 if(hostView != null) {
337                     try {
338                         context.getPackageManager().getApplicationInfo(hostView.getAppWidgetInfo().provider.getPackageName(), 0);
339                         hostView.post(() -> {
340                             ViewGroup.LayoutParams params = hostView.getLayoutParams();
341                             params.width = cellLayout.getWidth();
342                             params.height = cellLayout.getHeight();
343                             hostView.setLayoutParams(params);
344                             hostView.updateAppWidgetSize(null, cellLayout.getWidth(), cellLayout.getHeight(), cellLayout.getWidth(), cellLayout.getHeight());
345                         });
346                     } catch (PackageManager.NameNotFoundException e) {
347                         removeWidget(i, false);
348                     } catch (NullPointerException e) {
349                         removeWidget(i, true);
350                     }
351                 }
352             }
353
354             final SharedPreferences pref = U.getSharedPreferences(context);
355             if(!pref.getBoolean(PREF_DASHBOARD_TUTORIAL_SHOWN, false)) {
356                 U.showToastLong(context, R.string.tb_dashboard_tutorial);
357                 pref.edit().putBoolean(PREF_DASHBOARD_TUTORIAL_SHOWN, true).apply();
358             }
359         }
360     }
361
362     private void hideDashboard() {
363         if(layout.getVisibility() == View.VISIBLE) {
364             layout.setOnClickListener(null);
365             fadeOut(true);
366
367             for(int i = 0; i < maxSize; i++) {
368                 FrameLayout frameLayout = cells.get(i);
369                 frameLayout.findViewById(R.id.empty).setVisibility(View.GONE);
370             }
371
372             previouslySelectedCell = -1;
373         }
374     }
375
376     private void fadeIn() {
377         mAppWidgetHost.startListening();
378
379         DashboardHelper.getInstance().setDashboardOpen(true);
380
381         layout.setVisibility(View.VISIBLE);
382         layout.animate()
383                 .alpha(1)
384                 .setDuration(context.getResources().getInteger(android.R.integer.config_shortAnimTime))
385                 .setListener(null);
386     }
387
388     private void fadeOut(final boolean sendIntent) {
389         mAppWidgetHost.stopListening();
390
391         DashboardHelper.getInstance().setDashboardOpen(false);
392
393         layout.animate()
394                 .alpha(0)
395                 .setDuration(context.getResources().getInteger(android.R.integer.config_shortAnimTime))
396                 .setListener(new AnimatorListenerAdapter() {
397                     @Override
398                     public void onAnimationEnd(Animator animation) {
399                         layout.setVisibility(View.GONE);
400                         if(sendIntent) {
401                             U.sendBroadcast(context, ACTION_DASHBOARD_DISAPPEARING);
402                         }
403                     }
404                 });
405     }
406
407     @TargetApi(Build.VERSION_CODES.M)
408     @Override
409     public void onRecreateHost(UIHost host) {
410         if(layout != null) {
411             try {
412                 host.removeView(layout);
413             } catch (IllegalArgumentException e) { /* Gracefully fail */ }
414
415             SharedPreferences pref = U.getSharedPreferences(context);
416             if(U.canDrawOverlays(context))
417                 drawDashboard(host);
418             else {
419                 pref.edit().putBoolean(PREF_TASKBAR_ACTIVE, false).apply();
420
421                 host.terminate();
422             }
423         }
424     }
425
426     @Override
427     public void onDestroyHost(UIHost host) {
428         if(layout != null)
429             try {
430                 host.removeView(layout);
431             } catch (IllegalArgumentException e) { /* Gracefully fail */ }
432
433         U.unregisterReceiver(context, toggleReceiver);
434         U.unregisterReceiver(context, addWidgetReceiver);
435         U.unregisterReceiver(context, removeWidgetReceiver);
436         U.unregisterReceiver(context, hideReceiver);
437
438         SharedPreferences pref = U.getSharedPreferences(context);
439         if(!LauncherHelper.getInstance().isOnSecondaryHomeScreen(context)
440                 || !pref.getBoolean(PREF_DONT_STOP_DASHBOARD, false))
441             U.sendBroadcast(context, ACTION_DASHBOARD_DISAPPEARING);
442
443         pref.edit().remove(PREF_DONT_STOP_DASHBOARD).apply();
444     }
445
446     private void cellClick(View view, boolean isActualClick) {
447         Bundle bundle = (Bundle) view.getTag();
448         int cellId = bundle.getInt(EXTRA_CELL_ID);
449         int appWidgetId = bundle.getInt(EXTRA_APPWIDGET_ID, -1);
450
451         int currentlySelectedCell = appWidgetId == -1 ? cellId : -1;
452
453         SharedPreferences pref = U.getSharedPreferences(context);
454         boolean shouldShowPlaceholder =
455                 pref.getBoolean(
456                         PREF_DASHBOARD_WIDGET_PREFIX
457                                 + cellId
458                                 + PREF_DASHBOARD_WIDGET_PLACEHOLDER_SUFFIX,
459                         false
460                 );
461         if(isActualClick && ((appWidgetId == -1 && currentlySelectedCell == previouslySelectedCell) || shouldShowPlaceholder)) {
462             fadeOut(false);
463
464             FrameLayout frameLayout = cells.get(currentlySelectedCell);
465             frameLayout.findViewById(R.id.empty).setVisibility(View.GONE);
466
467             Intent intent = new Intent(ACTION_ADD_WIDGET_REQUESTED);
468             intent.putExtra(EXTRA_APPWIDGET_ID, APPWIDGET_HOST_ID);
469             intent.putExtra(EXTRA_CELL_ID, cellId);
470             U.sendBroadcast(context, intent);
471
472             if(shouldShowPlaceholder) {
473                 String providerName =
474                         pref.getString(
475                                 PREF_DASHBOARD_WIDGET_PREFIX
476                                         + cellId
477                                         + PREF_DASHBOARD_WIDGET_PROVIDER_SUFFIX,
478                                 "null"
479                         );
480                 if(!providerName.equals("null")) {
481                     ComponentName componentName = ComponentName.unflattenFromString(providerName);
482
483                     List<AppWidgetProviderInfo> providerInfoList = mAppWidgetManager.getInstalledProvidersForProfile(Process.myUserHandle());
484                     for(AppWidgetProviderInfo info : providerInfoList) {
485                         if(info.provider.equals(componentName)) {
486                             U.showToast(context, context.getString(R.string.tb_widget_restore_toast, info.loadLabel(context.getPackageManager())), Toast.LENGTH_SHORT);
487                             break;
488                         }
489                     }
490                 }
491             }
492
493             previouslySelectedCell = -1;
494         } else {
495             for(int i = 0; i < maxSize; i++) {
496                 FrameLayout frameLayout = cells.get(i);
497                 frameLayout.findViewById(R.id.empty).setVisibility(i == currentlySelectedCell && !shouldShowPlaceholder ? View.VISIBLE : View.GONE);
498             }
499
500             previouslySelectedCell = currentlySelectedCell;
501         }
502     }
503
504     private void cellLongClick(View view) {
505         fadeOut(false);
506
507         Bundle bundle = (Bundle) view.getTag();
508         int cellId = bundle.getInt(EXTRA_CELL_ID);
509
510         Intent intent = new Intent(ACTION_REMOVE_WIDGET_REQUESTED);
511         intent.putExtra(EXTRA_CELL_ID, cellId);
512         U.sendBroadcast(context, intent);
513     }
514
515     @VisibleForTesting
516     void addWidget(Intent intent) {
517         if (intent.hasExtra(EXTRA_APPWIDGET_ID) && intent.hasExtra(EXTRA_CELL_ID)) {
518             int appWidgetId = intent.getExtras().getInt(EXTRA_APPWIDGET_ID, -1);
519             int cellId = intent.getExtras().getInt(EXTRA_CELL_ID, -1);
520
521             addWidget(appWidgetId, cellId, true);
522         }
523     }
524
525     private void addWidget(int appWidgetId, int cellId, boolean shouldSave) {
526         AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
527
528         final DashboardCell cellLayout = cells.get(cellId);
529         final AppWidgetHostView hostView = mAppWidgetHost.createView(context, appWidgetId, appWidgetInfo);
530         hostView.setAppWidget(appWidgetId, appWidgetInfo);
531
532         Bundle bundle = new Bundle();
533         bundle.putInt(EXTRA_CELL_ID, cellId);
534         hostView.setTag(bundle);
535
536         cellLayout.findViewById(R.id.empty).setVisibility(View.GONE);
537         cellLayout.findViewById(R.id.placeholder).setVisibility(View.GONE);
538         cellLayout.setOnLongClickListener(olcl);
539         cellLayout.setOnGenericMotionListener(ogml);
540         cellLayout.setOnInterceptedLongPressListener(listener);
541
542         LinearLayout linearLayout = cellLayout.findViewById(R.id.dashboard);
543         linearLayout.addView(hostView);
544
545         Bundle bundle2 = (Bundle) cellLayout.getTag();
546         bundle2.putInt(EXTRA_APPWIDGET_ID, appWidgetId);
547         cellLayout.setTag(bundle2);
548
549         widgets.put(cellId, hostView);
550
551         if (shouldSave) {
552             saveWidgetInfo(context, appWidgetInfo, cellId, appWidgetId);
553         }
554
555         new Handler().post(() -> {
556             ViewGroup.LayoutParams params = hostView.getLayoutParams();
557             params.width = cellLayout.getWidth();
558             params.height = cellLayout.getHeight();
559             hostView.setLayoutParams(params);
560             hostView.updateAppWidgetSize(null, cellLayout.getWidth(), cellLayout.getHeight(), cellLayout.getWidth(), cellLayout.getHeight());
561         });
562     }
563
564     @VisibleForTesting
565     void saveWidgetInfo(Context context,
566                         AppWidgetProviderInfo appWidgetInfo,
567                         int cellId,
568                         int appWidgetId) {
569         SharedPreferences pref = U.getSharedPreferences(context);
570         SharedPreferences.Editor editor = pref.edit();
571         editor.putInt(PREF_DASHBOARD_WIDGET_PREFIX + cellId, appWidgetId);
572         editor.putString(
573                 PREF_DASHBOARD_WIDGET_PREFIX + cellId + PREF_DASHBOARD_WIDGET_PROVIDER_SUFFIX,
574                 appWidgetInfo.provider.flattenToString()
575         );
576         editor.remove(
577                 PREF_DASHBOARD_WIDGET_PREFIX
578                         + cellId
579                         + PREF_DASHBOARD_WIDGET_PLACEHOLDER_SUFFIX
580         );
581         editor.apply();
582     }
583
584     private void removeWidget(int cellId, boolean tempRemove) {
585         widgets.remove(cellId);
586
587         DashboardCell cellLayout = cells.get(cellId);
588         Bundle bundle = (Bundle) cellLayout.getTag();
589
590         mAppWidgetHost.deleteAppWidgetId(bundle.getInt(EXTRA_APPWIDGET_ID));
591         bundle.remove(EXTRA_APPWIDGET_ID);
592
593         LinearLayout linearLayout = cellLayout.findViewById(R.id.dashboard);
594         linearLayout.removeAllViews();
595
596         cellLayout.setTag(bundle);
597         cellLayout.setOnClickListener(cellOcl);
598         cellLayout.setOnHoverListener(cellOhl);
599         cellLayout.setOnLongClickListener(null);
600         cellLayout.setOnGenericMotionListener(null);
601         cellLayout.setOnInterceptedLongPressListener(null);
602
603         SharedPreferences pref = U.getSharedPreferences(context);
604         SharedPreferences.Editor editor = pref.edit();
605         editor.remove(PREF_DASHBOARD_WIDGET_PREFIX + cellId);
606
607         if (tempRemove) {
608             editor.putBoolean(
609                     PREF_DASHBOARD_WIDGET_PREFIX
610                             + cellId
611                             + PREF_DASHBOARD_WIDGET_PLACEHOLDER_SUFFIX,
612                     true
613             );
614             addPlaceholder(cellId);
615         } else {
616             editor.remove(
617                     PREF_DASHBOARD_WIDGET_PREFIX
618                             + cellId
619                             + PREF_DASHBOARD_WIDGET_PROVIDER_SUFFIX
620             );
621         }
622         editor.apply();
623     }
624
625     private void addPlaceholder(int cellId) {
626         FrameLayout placeholder = cells.get(cellId).findViewById(R.id.placeholder);
627         SharedPreferences pref = U.getSharedPreferences(context);
628         String providerName =
629                 pref.getString(
630                         PREF_DASHBOARD_WIDGET_PREFIX
631                                 + cellId
632                                 + PREF_DASHBOARD_WIDGET_PROVIDER_SUFFIX,
633                         "null"
634                 );
635
636         if(!providerName.equals("null")) {
637             ImageView imageView = placeholder.findViewById(R.id.placeholder_image);
638             ComponentName componentName = ComponentName.unflattenFromString(providerName);
639
640             List<AppWidgetProviderInfo> providerInfoList = mAppWidgetManager.getInstalledProvidersForProfile(Process.myUserHandle());
641             for(AppWidgetProviderInfo info : providerInfoList) {
642                 if(info.provider.equals(componentName)) {
643                     Drawable drawable = info.loadPreviewImage(context, -1);
644                     if(drawable == null) drawable = info.loadIcon(context, -1);
645
646                     ColorMatrix matrix = new ColorMatrix();
647                     matrix.setSaturation(0);
648
649                     imageView.setImageDrawable(drawable);
650                     imageView.setColorFilter(new ColorMatrixColorFilter(matrix));
651                     break;
652                 }
653             }
654         }
655
656         placeholder.setVisibility(View.VISIBLE);
657     }
658 }