Home | History | Annotate | Download | only in views
      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 package com.android.launcher3.views;
     17 
     18 import static com.android.launcher3.BaseDraggingActivity.INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION;
     19 import static com.android.launcher3.Utilities.EXTRA_WALLPAPER_OFFSET;
     20 
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.graphics.Rect;
     24 import android.graphics.RectF;
     25 import android.text.TextUtils;
     26 import android.util.ArrayMap;
     27 import android.util.AttributeSet;
     28 import android.view.MotionEvent;
     29 import android.view.View;
     30 import android.view.View.OnClickListener;
     31 import android.view.View.OnLongClickListener;
     32 import android.widget.Toast;
     33 
     34 import com.android.launcher3.Launcher;
     35 import com.android.launcher3.R;
     36 import com.android.launcher3.Utilities;
     37 import com.android.launcher3.popup.ArrowPopup;
     38 import com.android.launcher3.shortcuts.DeepShortcutView;
     39 import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
     40 import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
     41 import com.android.launcher3.widget.WidgetsFullSheet;
     42 
     43 import java.util.ArrayList;
     44 import java.util.List;
     45 
     46 /**
     47  * Popup shown on long pressing an empty space in launcher
     48  */
     49 public class OptionsPopupView extends ArrowPopup
     50         implements OnClickListener, OnLongClickListener {
     51 
     52     private final ArrayMap<View, OptionItem> mItemMap = new ArrayMap<>();
     53     private RectF mTargetRect;
     54 
     55     public OptionsPopupView(Context context, AttributeSet attrs) {
     56         this(context, attrs, 0);
     57     }
     58 
     59     public OptionsPopupView(Context context, AttributeSet attrs, int defStyleAttr) {
     60         super(context, attrs, defStyleAttr);
     61     }
     62 
     63     @Override
     64     public void onClick(View view) {
     65         handleViewClick(view, Action.Touch.TAP);
     66     }
     67 
     68     @Override
     69     public boolean onLongClick(View view) {
     70         return handleViewClick(view, Action.Touch.LONGPRESS);
     71     }
     72 
     73     private boolean handleViewClick(View view, int action) {
     74         OptionItem item = mItemMap.get(view);
     75         if (item == null) {
     76             return false;
     77         }
     78         if (item.mControlTypeForLog > 0) {
     79             logTap(action, item.mControlTypeForLog);
     80         }
     81         if (item.mClickListener.onLongClick(view)) {
     82             close(true);
     83             return true;
     84         }
     85         return false;
     86     }
     87 
     88     private void logTap(int action, int controlType) {
     89         mLauncher.getUserEventDispatcher().logActionOnControl(action, controlType);
     90     }
     91 
     92     @Override
     93     public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
     94         if (ev.getAction() != MotionEvent.ACTION_DOWN) {
     95             return false;
     96         }
     97         if (mLauncher.getDragLayer().isEventOverView(this, ev)) {
     98             return false;
     99         }
    100         close(true);
    101         return true;
    102     }
    103 
    104     @Override
    105     public void logActionCommand(int command) {
    106         // TODO:
    107     }
    108 
    109     @Override
    110     protected boolean isOfType(int type) {
    111         return (type & TYPE_OPTIONS_POPUP) != 0;
    112     }
    113 
    114     @Override
    115     protected void getTargetObjectLocation(Rect outPos) {
    116         mTargetRect.roundOut(outPos);
    117     }
    118 
    119     public static void show(Launcher launcher, RectF targetRect, List<OptionItem> items) {
    120         OptionsPopupView popup = (OptionsPopupView) launcher.getLayoutInflater()
    121                 .inflate(R.layout.longpress_options_menu, launcher.getDragLayer(), false);
    122         popup.mTargetRect = targetRect;
    123 
    124         for (OptionItem item : items) {
    125             DeepShortcutView view = popup.inflateAndAdd(R.layout.system_shortcut, popup);
    126             view.getIconView().setBackgroundResource(item.mIconRes);
    127             view.getBubbleText().setText(item.mLabelRes);
    128             view.setDividerVisibility(View.INVISIBLE);
    129             view.setOnClickListener(popup);
    130             view.setOnLongClickListener(popup);
    131             popup.mItemMap.put(view, item);
    132         }
    133         popup.reorderAndShow(popup.getChildCount());
    134     }
    135 
    136     public static void showDefaultOptions(Launcher launcher, float x, float y) {
    137         float halfSize = launcher.getResources().getDimension(R.dimen.options_menu_thumb_size) / 2;
    138         if (x < 0 || y < 0) {
    139             x = launcher.getDragLayer().getWidth() / 2;
    140             y = launcher.getDragLayer().getHeight() / 2;
    141         }
    142         RectF target = new RectF(x - halfSize, y - halfSize, x + halfSize, y + halfSize);
    143 
    144         ArrayList<OptionItem> options = new ArrayList<>();
    145         options.add(new OptionItem(R.string.wallpaper_button_text, R.drawable.ic_wallpaper,
    146                 ControlType.WALLPAPER_BUTTON, OptionsPopupView::startWallpaperPicker));
    147         options.add(new OptionItem(R.string.widget_button_text, R.drawable.ic_widget,
    148                 ControlType.WIDGETS_BUTTON, OptionsPopupView::onWidgetsClicked));
    149         options.add(new OptionItem(R.string.settings_button_text, R.drawable.ic_setting,
    150                 ControlType.SETTINGS_BUTTON, OptionsPopupView::startSettings));
    151 
    152         show(launcher, target, options);
    153     }
    154 
    155     public static boolean onWidgetsClicked(View view) {
    156         Launcher launcher = Launcher.getLauncher(view.getContext());
    157         if (launcher.getPackageManager().isSafeMode()) {
    158             Toast.makeText(launcher, R.string.safemode_widget_error, Toast.LENGTH_SHORT).show();
    159             return false;
    160         } else {
    161             WidgetsFullSheet.show(launcher, true /* animated */);
    162             return true;
    163         }
    164     }
    165 
    166     public static boolean startSettings(View view) {
    167         Launcher launcher = Launcher.getLauncher(view.getContext());
    168         launcher.startActivity(new Intent(Intent.ACTION_APPLICATION_PREFERENCES)
    169                 .setPackage(launcher.getPackageName())
    170                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
    171         return true;
    172     }
    173 
    174     /**
    175      * Event handler for the wallpaper picker button that appears after a long press
    176      * on the home screen.
    177      */
    178     public static boolean startWallpaperPicker(View v) {
    179         Launcher launcher = Launcher.getLauncher(v.getContext());
    180         if (!Utilities.isWallpaperAllowed(launcher)) {
    181             Toast.makeText(launcher, R.string.msg_disabled_by_admin, Toast.LENGTH_SHORT).show();
    182             return false;
    183         }
    184         Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER)
    185                 .putExtra(EXTRA_WALLPAPER_OFFSET,
    186                         launcher.getWorkspace().getWallpaperOffsetForCenterPage());
    187         intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
    188 
    189         String pickerPackage = launcher.getString(R.string.wallpaper_picker_package);
    190         if (!TextUtils.isEmpty(pickerPackage)) {
    191             intent.setPackage(pickerPackage);
    192         } else {
    193             // If there is no target package, use the default intent chooser animation
    194             intent.putExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION, true);
    195         }
    196         return launcher.startActivitySafely(v, intent, null);
    197     }
    198 
    199     public static class OptionItem {
    200 
    201         private final int mLabelRes;
    202         private final int mIconRes;
    203         private final int mControlTypeForLog;
    204         private final OnLongClickListener mClickListener;
    205 
    206         public OptionItem(int labelRes, int iconRes, int controlTypeForLog,
    207                 OnLongClickListener clickListener) {
    208             mLabelRes = labelRes;
    209             mIconRes = iconRes;
    210             mControlTypeForLog = controlTypeForLog;
    211             mClickListener = clickListener;
    212         }
    213     }
    214 }
    215