Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(465)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/ntp/ContextMenuManager.java

Issue 2459033002: 📰 Add a context menu to remove status items (Closed)
Patch Set: fix test Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.chrome.browser.ntp;
6
7 import android.support.annotation.IntDef;
8 import android.view.ContextMenu;
9 import android.view.Menu;
10 import android.view.MenuItem;
11 import android.view.MenuItem.OnMenuItemClickListener;
12 import android.view.View;
13
14 import org.chromium.base.Callback;
15 import org.chromium.chrome.R;
16 import org.chromium.chrome.browser.ChromeActivity;
17 import org.chromium.chrome.browser.ntp.NewTabPageView.NewTabPageManager;
18 import org.chromium.chrome.browser.ntp.snippets.SnippetsConfig;
19 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
20 import org.chromium.ui.mojom.WindowOpenDisposition;
21
22 import java.lang.annotation.Retention;
23 import java.lang.annotation.RetentionPolicy;
24 import java.util.Set;
25
26 /**
27 * Takes care of creating, closing a context menu and triaging the item clicks.
28 */
29 public class ContextMenuManager {
30 @IntDef({ID_OPEN_IN_NEW_WINDOW, ID_OPEN_IN_NEW_TAB, ID_OPEN_IN_INCOGNITO_TAB , ID_REMOVE,
31 ID_SAVE_FOR_OFFLINE})
32 @Retention(RetentionPolicy.SOURCE)
33 public @interface ContextMenuItemId {}
34 public static final int ID_OPEN_IN_NEW_WINDOW = 0;
35 public static final int ID_OPEN_IN_NEW_TAB = 1;
36 public static final int ID_OPEN_IN_INCOGNITO_TAB = 2;
37 public static final int ID_REMOVE = 3;
38 public static final int ID_SAVE_FOR_OFFLINE = 4;
39
40 private final NewTabPageManager mManager;
41 private final ChromeActivity mActivity;
42 private final TouchDisableableView mOuterView;
43
44 /** Defines callback to configure the context menu and respond to user inter action. */
45 public interface Delegate {
46 /** Opens the current item the way specified by {@code windowDisposition }. */
47 void openItem(int windowDisposition);
48
49 /** Remove the current item. */
50 void removeItem();
51
52 /** @return whether the current item can be saved offline. */
53 String getUrl();
54
55 /** @return IDs of the menu items that are supported. */
56 Set<Integer> getSupportedMenuItems();
57 }
58
59 /** Interface for a view that can be set to stop responding to touches. */
60 public interface TouchDisableableView { void setTouchEnabled(boolean enabled ); }
61
62 public ContextMenuManager(NewTabPageManager newTabPageManager, ChromeActivit y activity,
63 TouchDisableableView outerView) {
64 mManager = newTabPageManager;
65 mActivity = activity;
66 mOuterView = outerView;
67 }
68
69 /**
70 * Populates the context menu.
71 * @param menu The menu to populate.
72 * @param associatedView The view that requested a context menu.
73 * @param delegate Delegate that defines the configuration of the menu and w hat to do when items
74 * are tapped.
75 */
76 public void createContextMenu(ContextMenu menu, View associatedView, Delegat e delegate) {
77 OnMenuItemClickListener listener = new ItemClickListener(delegate);
78 Set<Integer> supportedItems = delegate.getSupportedMenuItems();
79 boolean hasItems = false;
80
81 if (shouldShowItem(ID_OPEN_IN_NEW_WINDOW, delegate, supportedItems)) {
82 hasItems = true;
83 addContextMenuItem(menu, ID_OPEN_IN_NEW_WINDOW,
84 R.string.contextmenu_open_in_other_window, listener);
85 }
86
87 if (shouldShowItem(ID_OPEN_IN_NEW_TAB, delegate, supportedItems)) {
88 hasItems = true;
89 addContextMenuItem(
90 menu, ID_OPEN_IN_NEW_TAB, R.string.contextmenu_open_in_new_t ab, listener);
91 }
92
93 if (shouldShowItem(ID_OPEN_IN_INCOGNITO_TAB, delegate, supportedItems)) {
94 hasItems = true;
95 addContextMenuItem(menu, ID_OPEN_IN_INCOGNITO_TAB,
96 R.string.contextmenu_open_in_incognito_tab, listener);
97 }
98
99 if (shouldShowItem(ID_SAVE_FOR_OFFLINE, delegate, supportedItems)) {
100 hasItems = true;
101 addContextMenuItem(menu, ID_SAVE_FOR_OFFLINE, R.string.contextmenu_s ave_link, listener);
102 }
103
104 if (shouldShowItem(ID_REMOVE, delegate, supportedItems)) {
105 hasItems = true;
106 addContextMenuItem(menu, ID_REMOVE, R.string.remove, listener);
107 }
108
109 // No item added. We won't show the menu, so we can skip the rest.
110 if (!hasItems) return;
111
112 associatedView.addOnAttachStateChangeListener(new View.OnAttachStateChan geListener() {
113 @Override
114 public void onViewAttachedToWindow(View view) {}
115
116 @Override
117 public void onViewDetachedFromWindow(View view) {
118 closeContextMenu();
119 view.removeOnAttachStateChangeListener(this);
120 }
121 });
122
123 // Disable touch events on the outer view while the context menu is open . This is to
124 // prevent the user long pressing to get the context menu then on the sa me press scrolling
125 // or swiping to dismiss an item (eg. https://crbug.com/638854, https:// crbug.com/638555,
126 // https://crbug.com/636296)
127 mOuterView.setTouchEnabled(false);
128
129 mActivity.addContextMenuCloseCallback(new Callback<Menu>() {
130 @Override
131 public void onResult(Menu result) {
132 mOuterView.setTouchEnabled(true);
133 mActivity.removeContextMenuCloseCallback(this);
134 }
135 });
136 }
137
138 /** Closes the context menu, if open. */
139 public void closeContextMenu() {
140 mActivity.closeContextMenu();
141 }
142
143 private boolean shouldShowItem(
144 @ContextMenuItemId int itemId, Delegate delegate, Set<Integer> suppo rtedItems) {
145 if (!supportedItems.contains(itemId)) return false;
146
147 switch (itemId) {
148 case ID_OPEN_IN_NEW_WINDOW:
149 return mManager.isOpenInNewWindowEnabled();
150 case ID_OPEN_IN_NEW_TAB:
151 return true;
152 case ID_OPEN_IN_INCOGNITO_TAB:
153 return mManager.isOpenInIncognitoEnabled();
154 case ID_SAVE_FOR_OFFLINE: {
155 if (!SnippetsConfig.isSaveToOfflineEnabled()) return false;
156 String itemUrl = delegate.getUrl();
157 return itemUrl != null && OfflinePageBridge.canSavePage(itemUrl) ;
158 }
159 case ID_REMOVE:
160 return true;
161
162 default:
163 assert false;
164 return false;
165 }
166 }
167
168 /**
169 * Convenience method to reduce multi-line function call to single line.
170 */
171 private void addContextMenuItem(ContextMenu menu, @ContextMenuItemId int id, int resourceId,
172 OnMenuItemClickListener listener) {
173 menu.add(Menu.NONE, id, Menu.NONE, resourceId).setOnMenuItemClickListene r(listener);
174 }
175
176 private static class ItemClickListener implements OnMenuItemClickListener {
177 private final Delegate mDelegate;
178
179 ItemClickListener(Delegate delegate) {
180 mDelegate = delegate;
181 }
182
183 @Override
184 public boolean onMenuItemClick(MenuItem item) {
185 switch (item.getItemId()) {
186 case ID_OPEN_IN_NEW_WINDOW:
187 mDelegate.openItem(WindowOpenDisposition.NEW_WINDOW);
188 return true;
189 case ID_OPEN_IN_NEW_TAB:
190 mDelegate.openItem(WindowOpenDisposition.NEW_FOREGROUND_TAB) ;
191 return true;
192 case ID_OPEN_IN_INCOGNITO_TAB:
193 mDelegate.openItem(WindowOpenDisposition.OFF_THE_RECORD);
194 return true;
195 case ID_SAVE_FOR_OFFLINE:
196 mDelegate.openItem(WindowOpenDisposition.SAVE_TO_DISK);
197 return true;
198 case ID_REMOVE:
199 mDelegate.removeItem();
200 return true;
201 default:
202 return false;
203 }
204 }
205 }
206 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698