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

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

Issue 2459033002: 📰 Add a context menu to remove status items (Closed)
Patch Set: close the menu when the view is detached 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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chrome.browser.ntp; 5 package org.chromium.chrome.browser.ntp;
6 6
7 import android.support.annotation.IntDef; 7 import android.support.annotation.IntDef;
8 import android.support.v4.view.ViewCompat; 8 import android.support.v4.view.ViewCompat;
9 import android.view.ContextMenu; 9 import android.view.ContextMenu;
10 import android.view.Menu; 10 import android.view.Menu;
11 import android.view.MenuItem; 11 import android.view.MenuItem;
12 import android.view.MenuItem.OnMenuItemClickListener; 12 import android.view.MenuItem.OnMenuItemClickListener;
13 import android.view.View; 13 import android.view.View;
14 14
15 import org.chromium.base.Callback; 15 import org.chromium.base.Callback;
16 import org.chromium.chrome.R; 16 import org.chromium.chrome.R;
17 import org.chromium.chrome.browser.ntp.NewTabPageView.NewTabPageManager; 17 import org.chromium.chrome.browser.ntp.NewTabPageView.NewTabPageManager;
18 import org.chromium.ui.mojom.WindowOpenDisposition; 18 import org.chromium.ui.mojom.WindowOpenDisposition;
19 19
20 import java.lang.annotation.Retention; 20 import java.lang.annotation.Retention;
21 import java.lang.annotation.RetentionPolicy; 21 import java.lang.annotation.RetentionPolicy;
22 22
23 /** 23 /**
24 * Takes care of creating a context menu and triaging the time clicks. 24 * Takes care of creating a context menu and triaging the time clicks.
25 */ 25 */
26 public class ContextMenuHandler implements OnMenuItemClickListener { 26 public class ContextMenuHandler implements OnMenuItemClickListener {
27 @IntDef({ID_OPEN_IN_NEW_WINDOW, ID_OPEN_IN_NEW_TAB, ID_OPEN_IN_INCOGNITO_TAB , ID_REMOVE, 27 @IntDef({ID_OPEN_IN_NEW_WINDOW, ID_OPEN_IN_NEW_TAB, ID_OPEN_IN_INCOGNITO_TAB , ID_REMOVE,
28 ID_SAVE_FOR_OFFLINE}) 28 ID_SAVE_FOR_OFFLINE})
29 @Retention(RetentionPolicy.SOURCE) 29 @Retention(RetentionPolicy.SOURCE)
30 @interface ContextMenuItemId {} 30 public @interface ContextMenuItemId {}
31 static final int ID_OPEN_IN_NEW_WINDOW = 0; 31 public static final int ID_OPEN_IN_NEW_WINDOW = 0;
32 static final int ID_OPEN_IN_NEW_TAB = 1; 32 public static final int ID_OPEN_IN_NEW_TAB = 1;
33 static final int ID_OPEN_IN_INCOGNITO_TAB = 2; 33 public static final int ID_OPEN_IN_INCOGNITO_TAB = 2;
34 static final int ID_REMOVE = 3; 34 public static final int ID_REMOVE = 3;
35 static final int ID_SAVE_FOR_OFFLINE = 4; 35 public static final int ID_SAVE_FOR_OFFLINE = 4;
36 36
37 private final NewTabPageManager mManager; 37 private final NewTabPageManager mManager;
38 private final Delegate mDelegate; 38 private final Delegate mDelegate;
39 private final TouchDisableableView mOuterView; 39 private final TouchDisableableView mOuterView;
40 40
41 /** Defines callback to configure the context menu and respond to user inter action. */ 41 /** Defines callback to configure the context menu and respond to user inter action. */
42 public interface Delegate { 42 public interface Delegate {
43 /** Opens the current item the way specified by {@code windowDisposition }. */ 43 /** Opens the current item the way specified by {@code windowDisposition }. */
44 void openItem(int windowDisposition); 44 void openItem(int windowDisposition);
45 45
46 /** Removed the current item. */ 46 /** Removed the current item. */
47 void removeItem(); 47 void removeItem();
48 48
49 /** @return whether the current item can be saved offline. */ 49 /** @return whether the current item can be saved offline. */
50 boolean canBeSavedOffline(); 50 boolean canBeSavedOffline();
51 } 51 }
52 52
53 /** Interface for a view that can be set to stop responding to touches. */ 53 /** Interface for a view that can be set to stop responding to touches. */
54 public interface TouchDisableableView { 54 public interface TouchDisableableView {
55 void setTouchEnabled(boolean enabled); 55 void setTouchEnabled(boolean enabled);
56 View asView(); 56 View asView();
57 } 57 }
58 58
59 public ContextMenuHandler(NewTabPageManager newTabPageManager, TouchDisablea bleView outerView, 59 public ContextMenuHandler(NewTabPageManager newTabPageManager, TouchDisablea bleView outerView,
60 Delegate delegate) { 60 Delegate delegate) {
61 assert outerView instanceof View;
62 mManager = newTabPageManager; 61 mManager = newTabPageManager;
63 mOuterView = outerView; 62 mOuterView = outerView;
64 mDelegate = delegate; 63 mDelegate = delegate;
65 } 64 }
66 65
67 public boolean showItem(@ContextMenuItemId int itemId) { 66 public boolean showItem(@ContextMenuItemId int itemId) {
68 switch (itemId) { 67 switch (itemId) {
69 case ID_OPEN_IN_NEW_WINDOW: 68 case ID_OPEN_IN_NEW_WINDOW:
70 return mManager.isOpenInNewWindowEnabled(); 69 return mManager.isOpenInNewWindowEnabled();
71 case ID_OPEN_IN_NEW_TAB: 70 case ID_OPEN_IN_NEW_TAB:
72 return true; 71 return true;
73 case ID_OPEN_IN_INCOGNITO_TAB: 72 case ID_OPEN_IN_INCOGNITO_TAB:
74 return mManager.isOpenInIncognitoEnabled(); 73 return mManager.isOpenInIncognitoEnabled();
75 case ID_SAVE_FOR_OFFLINE: 74 case ID_SAVE_FOR_OFFLINE:
76 return mDelegate.canBeSavedOffline(); 75 return mDelegate.canBeSavedOffline();
77 case ID_REMOVE: 76 case ID_REMOVE:
78 return true; 77 return true;
79 78
80 default: 79 default:
81 return false; 80 return false;
82 } 81 }
83 } 82 }
84 83
85 public void onCreateContextMenu(ContextMenu menu) { 84 public void onCreateContextMenu(ContextMenu menu, final View associatedView) {
86 if (showItem(ID_OPEN_IN_NEW_WINDOW)) { 85 if (showItem(ID_OPEN_IN_NEW_WINDOW)) {
87 addContextMenuItem( 86 addContextMenuItem(
88 menu, ID_OPEN_IN_NEW_WINDOW, R.string.contextmenu_open_in_ot her_window); 87 menu, ID_OPEN_IN_NEW_WINDOW, R.string.contextmenu_open_in_ot her_window);
89 } 88 }
90 89
91 if (showItem(ID_OPEN_IN_NEW_TAB)) { 90 if (showItem(ID_OPEN_IN_NEW_TAB)) {
92 addContextMenuItem(menu, ID_OPEN_IN_NEW_TAB, R.string.contextmenu_op en_in_new_tab); 91 addContextMenuItem(menu, ID_OPEN_IN_NEW_TAB, R.string.contextmenu_op en_in_new_tab);
93 } 92 }
94 93
95 if (showItem(ID_OPEN_IN_INCOGNITO_TAB)) { 94 if (showItem(ID_OPEN_IN_INCOGNITO_TAB)) {
96 addContextMenuItem( 95 addContextMenuItem(
97 menu, ID_OPEN_IN_INCOGNITO_TAB, R.string.contextmenu_open_in _incognito_tab); 96 menu, ID_OPEN_IN_INCOGNITO_TAB, R.string.contextmenu_open_in _incognito_tab);
98 } 97 }
99 98
100 if (showItem(ID_SAVE_FOR_OFFLINE)) { 99 if (showItem(ID_SAVE_FOR_OFFLINE)) {
101 addContextMenuItem(menu, ID_SAVE_FOR_OFFLINE, R.string.contextmenu_s ave_link); 100 addContextMenuItem(menu, ID_SAVE_FOR_OFFLINE, R.string.contextmenu_s ave_link);
102 } 101 }
103 102
104 if (showItem(ID_REMOVE)) { 103 if (showItem(ID_REMOVE)) {
105 addContextMenuItem(menu, ID_REMOVE, R.string.remove); 104 addContextMenuItem(menu, ID_REMOVE, R.string.remove);
106 } 105 }
107 106
108 // Disable touch events on the RecyclerView while the context menu is op en. This is to 107 // Disable touch events on the RecyclerView while the context menu is op en. This is to
109 // prevent the user long pressing to get the context menu then on the sa me press scrolling 108 // prevent the user long pressing to get the context menu then on the sa me press scrolling
110 // or swiping to dismiss an item (eg. https://crbug.com/638854, https:// crbug.com/638555, 109 // or swiping to dismiss an item (eg. https://crbug.com/638854, https:// crbug.com/638555,
111 // https://crbug.com/636296) 110 // https://crbug.com/636296)
112 mOuterView.setTouchEnabled(false); 111 mOuterView.setTouchEnabled(false);
113 112
113 mManager.getContextMenuLifetimeManager().onContextMenuCreated(menu, asso ciatedView);
Bernhard Bauer 2016/11/11 13:30:08 Wait, so the manager owns the LifetimeManager, whi
dgn 2016/11/14 18:34:08 Done.
114
114 mManager.addContextMenuCloseCallback(new Callback<Menu>() { 115 mManager.addContextMenuCloseCallback(new Callback<Menu>() {
115 @Override 116 @Override
116 public void onResult(Menu result) { 117 public void onResult(Menu result) {
117 mOuterView.setTouchEnabled(true); 118 mOuterView.setTouchEnabled(true);
118 mManager.removeContextMenuCloseCallback(this); 119 mManager.removeContextMenuCloseCallback(this);
120 mManager.getContextMenuLifetimeManager().onMenuClosed();
119 } 121 }
120 }); 122 });
121 } 123 }
122 124
123 @Override 125 @Override
124 public boolean onMenuItemClick(MenuItem item) { 126 public boolean onMenuItemClick(MenuItem item) {
125 // If the user clicks a snippet then immediately long presses they will create a context 127 // If the user clicks a snippet then immediately long presses they will create a context
126 // menu while the snippet's URL loads in the background. This means that when they press 128 // menu while the snippet's URL loads in the background. This means that when they press
127 // an item on context menu the NTP will not actually be open. We add thi s check here to 129 // an item on context menu the NTP will not actually be open. We add thi s check here to
128 // prevent taking any action if the user has already left the NTP. 130 // prevent taking any action if the user has already left the NTP.
(...skipping 21 matching lines...) Expand all
150 return false; 152 return false;
151 } 153 }
152 } 154 }
153 155
154 /** 156 /**
155 * Convenience method to reduce multi-line function call to single line. 157 * Convenience method to reduce multi-line function call to single line.
156 */ 158 */
157 private void addContextMenuItem(ContextMenu menu, @ContextMenuItemId int id, int resourceId) { 159 private void addContextMenuItem(ContextMenu menu, @ContextMenuItemId int id, int resourceId) {
158 menu.add(Menu.NONE, id, Menu.NONE, resourceId).setOnMenuItemClickListene r(this); 160 menu.add(Menu.NONE, id, Menu.NONE, resourceId).setOnMenuItemClickListene r(this);
159 } 161 }
162
163 /** Helps closing open context menus when the view the associated view is mo dified. */
164 public static class LifetimeManager {
165 private ContextMenu mContextMenu;
166 private View mAssociatedView;
167
168 public void onContextMenuCreated(ContextMenu c, View v) {
169 mContextMenu = c;
170 mAssociatedView = v;
171 }
172
173 public void onViewModified(View v) {
174 if (mAssociatedView == null || mAssociatedView != v) return;
Bernhard Bauer 2016/11/11 13:30:08 |mAssociatedView| would be null if either that is
dgn 2016/11/14 18:34:08 Simplified this and removed the redundant checks.
175 if (mContextMenu == null) return;
176 mContextMenu.close();
177 mContextMenu = null;
178 }
179
180 private void onMenuClosed() {
181 mContextMenu = null;
182 mAssociatedView = null;
183 }
184 }
160 } 185 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698