• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
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 
17 package com.android.ide.common.api;
18 
19 import com.android.annotations.NonNull;
20 import com.android.annotations.Nullable;
21 import com.android.utils.Pair;
22 import com.google.common.annotations.Beta;
23 
24 import java.net.URL;
25 import java.util.ArrayList;
26 import java.util.List;
27 import java.util.regex.Pattern;
28 
29 /**
30  * A {@link RuleAction} represents an action provided by an {@link IViewRule}, typically
31  * shown in a context menu or in the layout actions bar.
32  * <p/>
33  * Each action should have a reasonably unique ID. This is used when multiple nodes
34  * are selected to filter the actions down to just those actions that are supported
35  * across all selected nodes. If an action does not support multiple nodes, it can
36  * return false from {@link #supportsMultipleNodes()}.
37  * <p/>
38  * Actions can be grouped into a hierarchy of sub-menus using the {@link NestedAction} class,
39  * or into a flat submenu using the {@link Choices} class.
40  * <p/>
41  * Actions (including separators) all have a "sort priority", and this is used to
42  * sort the menu items or toolbar buttons into a specific order.
43  * <p>
44  * <b>NOTE: This is not a public or final API; if you rely on this be prepared
45  * to adjust your code for the next tools release.</b>
46  * </p>
47  */
48 @Beta
49 public class RuleAction implements Comparable<RuleAction> {
50     /**
51      * Character used to split multiple checked choices.
52      * The pipe character "|" is used, to natively match Android resource flag separators.
53      */
54     public final static String CHOICE_SEP = "|"; //$NON-NLS-1$
55 
56     /**
57      * Same as {@link #CHOICE_SEP} but safe for use in regular expressions.
58      */
59     public final static String CHOICE_SEP_PATTERN = Pattern.quote(CHOICE_SEP);
60 
61     /**
62      * The unique id of the action.
63      * @see #getId()
64      */
65     private final String mId;
66     /**
67      * The UI-visible title of the action.
68      */
69     private final String mTitle;
70 
71     /** A URL pointing to an icon, or null */
72     private URL mIconUrl;
73 
74     /**
75      * A callback executed when the action is selected in the context menu.
76      */
77     private final IMenuCallback mCallback;
78 
79     /**
80      * The sorting priority of this item; actions can be sorted according to these
81      */
82     protected final int mSortPriority;
83 
84     /**
85      * Whether this action supports multiple nodes, see
86      * {@link #supportsMultipleNodes()} for details.
87      */
88     private final boolean mSupportsMultipleNodes;
89 
90     /**
91      * Special value which will insert a separator in the choices' submenu.
92      */
93     public final static String SEPARATOR = "----";
94 
95     // Factories
96 
97     /**
98      * Constructs a new separator which will be shown in places where separators
99      * are supported such as context menus
100      *
101      * @param sortPriority a priority used for sorting this action
102      * @return a new separator
103      */
104     @NonNull
createSeparator(int sortPriority)105     public static Separator createSeparator(int sortPriority) {
106         return new Separator(sortPriority, true /* supportsMultipleNodes*/);
107     }
108 
109     /**
110      * Constructs a new base {@link RuleAction} with its ID, title and action callback.
111      *
112      * @param id The unique ID of the action. Must not be null.
113      * @param title The title of the action. Must not be null.
114      * @param callback The callback executed when the action is selected.
115      *            Must not be null.
116      * @param iconUrl a URL pointing to an icon to use for this action, or null
117      * @param sortPriority a priority used for sorting this action
118      * @param supportsMultipleNodes whether this action supports multiple nodes,
119      *            see {@link #supportsMultipleNodes()} for details
120      * @return the new {@link RuleAction}
121      */
122     @NonNull
createAction( @onNull String id, @NonNull String title, @NonNull IMenuCallback callback, @Nullable URL iconUrl, int sortPriority, boolean supportsMultipleNodes)123     public static RuleAction createAction(
124             @NonNull String id,
125             @NonNull String title,
126             @NonNull IMenuCallback callback,
127             @Nullable URL iconUrl,
128             int sortPriority,
129             boolean supportsMultipleNodes) {
130         RuleAction action = new RuleAction(id, title, callback, sortPriority,
131                 supportsMultipleNodes);
132         action.setIconUrl(iconUrl);
133 
134         return action;
135     }
136 
137     /**
138      * Creates a new immutable toggle action.
139      *
140      * @param id The unique id of the action. Cannot be null.
141      * @param title The UI-visible title of the context menu item. Cannot be null.
142      * @param isChecked Whether the context menu item has a check mark.
143      * @param callback A callback to execute when the context menu item is
144      *            selected.
145      * @param iconUrl a URL pointing to an icon to use for this action, or null
146      * @param sortPriority a priority used for sorting this action
147      * @param supportsMultipleNodes whether this action supports multiple nodes,
148      *            see {@link #supportsMultipleNodes()} for details
149      * @return the new {@link Toggle}
150      */
151     @NonNull
createToggle( @onNull String id, @NonNull String title, boolean isChecked, @NonNull IMenuCallback callback, @Nullable URL iconUrl, int sortPriority, boolean supportsMultipleNodes)152     public static Toggle createToggle(
153             @NonNull String id,
154             @NonNull String title,
155             boolean isChecked,
156             @NonNull IMenuCallback callback,
157             @Nullable URL iconUrl,
158             int sortPriority,
159             boolean supportsMultipleNodes) {
160         Toggle toggle = new Toggle(id, title, isChecked, callback, sortPriority,
161                 supportsMultipleNodes);
162         toggle.setIconUrl(iconUrl);
163         return toggle;
164     }
165 
166     /**
167      * Creates a new immutable multiple-choice action with a defined ordered set
168      * of action children.
169      *
170      * @param id The unique id of the action. Cannot be null.
171      * @param title The title of the action to be displayed to the user
172      * @param provider Provides the actions to be shown as children of this
173      *            action
174      * @param callback A callback to execute when the context menu item is
175      *            selected.
176      * @param iconUrl the icon to use for the multiple choice action itself
177      * @param sortPriority the sorting priority to use for the multiple choice
178      *            action itself
179      * @param supportsMultipleNodes whether this action supports multiple nodes,
180      *            see {@link #supportsMultipleNodes()} for details
181      * @return the new {@link NestedAction}
182      */
183     @NonNull
createChoices( @onNull String id, @NonNull String title, @NonNull IMenuCallback callback, @Nullable URL iconUrl, int sortPriority, boolean supportsMultipleNodes, @NonNull ActionProvider provider)184     public static NestedAction createChoices(
185             @NonNull String id,
186             @NonNull String title,
187             @NonNull IMenuCallback callback,
188             @Nullable URL iconUrl,
189             int sortPriority,
190             boolean supportsMultipleNodes,
191             @NonNull ActionProvider provider) {
192         NestedAction choices = new NestedAction(id, title, provider, callback,
193                 sortPriority, supportsMultipleNodes);
194         choices.setIconUrl(iconUrl);
195         return choices;
196     }
197 
198     /**
199      * Creates a new immutable multiple-choice action with a defined ordered set
200      * of children.
201      *
202      * @param id The unique id of the action. Cannot be null.
203      * @param title The title of the action to be displayed to the user
204      * @param iconUrls The icon urls for the children items (may be null)
205      * @param ids The internal ids for the children
206      * @param current The id(s) of the current choice(s) that will be check
207      *            marked. Can be null. Can be an id not present in the choices
208      *            map. There can be more than one id separated by
209      *            {@link #CHOICE_SEP}.
210      * @param callback A callback to execute when the context menu item is
211      *            selected.
212      * @param titles The UI-visible titles of the children
213      * @param iconUrl the icon to use for the multiple choice action itself
214      * @param sortPriority the sorting priority to use for the multiple choice
215      *            action itself
216      * @param supportsMultipleNodes whether this action supports multiple nodes,
217      *            see {@link #supportsMultipleNodes()} for details
218      * @return the new {@link Choices}
219      */
220     @NonNull
createChoices( @onNull String id, @NonNull String title, @NonNull IMenuCallback callback, @NonNull List<String> titles, @Nullable List<URL> iconUrls, @NonNull List<String> ids, @Nullable String current, @Nullable URL iconUrl, int sortPriority, boolean supportsMultipleNodes)221     public static Choices createChoices(
222             @NonNull String id,
223             @NonNull String title,
224             @NonNull IMenuCallback callback,
225             @NonNull List<String> titles,
226             @Nullable List<URL> iconUrls,
227             @NonNull List<String> ids,
228             @Nullable String current,
229             @Nullable URL iconUrl,
230             int sortPriority,
231             boolean supportsMultipleNodes) {
232         Choices choices = new Choices(id, title, callback, titles, iconUrls,
233                 ids, current, sortPriority, supportsMultipleNodes);
234         choices.setIconUrl(iconUrl);
235 
236         return choices;
237     }
238 
239     /**
240      * Creates a new immutable multiple-choice action with a defined ordered set
241      * of children.
242      *
243      * @param id The unique id of the action. Cannot be null.
244      * @param title The title of the action to be displayed to the user
245      * @param iconUrls The icon urls for the children items (may be null)
246      * @param current The id(s) of the current choice(s) that will be check
247      *            marked. Can be null. Can be an id not present in the choices
248      *            map. There can be more than one id separated by
249      *            {@link #CHOICE_SEP}.
250      * @param callback A callback to execute when the context menu item is
251      *            selected.
252      * @param iconUrl the icon to use for the multiple choice action itself
253      * @param sortPriority the sorting priority to use for the multiple choice
254      *            action itself
255      * @param supportsMultipleNodes whether this action supports multiple nodes,
256      *            see {@link #supportsMultipleNodes()} for details
257      * @param idsAndTitles a list of pairs (of ids and titles) to use for the
258      *            menu items
259      * @return the new {@link Choices}
260      */
261     @NonNull
createChoices( @onNull String id, @NonNull String title, @NonNull IMenuCallback callback, @Nullable List<URL> iconUrls, @Nullable String current, @Nullable URL iconUrl, int sortPriority, boolean supportsMultipleNodes, @NonNull List<Pair<String, String>> idsAndTitles)262     public static Choices createChoices(
263             @NonNull String id,
264             @NonNull String title,
265             @NonNull IMenuCallback callback,
266             @Nullable List<URL> iconUrls,
267             @Nullable String current,
268             @Nullable URL iconUrl,
269             int sortPriority,
270             boolean supportsMultipleNodes,
271             @NonNull List<Pair<String, String>> idsAndTitles) {
272         int itemCount = idsAndTitles.size();
273         List<String> titles = new ArrayList<String>(itemCount);
274         List<String> ids = new ArrayList<String>(itemCount);
275         for (Pair<String, String> pair : idsAndTitles) {
276             ids.add(pair.getFirst());
277             titles.add(pair.getSecond());
278         }
279         Choices choices = new Choices(id, title, callback, titles, iconUrls,
280                 ids, current, sortPriority, supportsMultipleNodes);
281         choices.setIconUrl(iconUrl);
282         return choices;
283     }
284 
285     /**
286      * Creates a new immutable multiple-choice action with lazily computed children.
287      *
288      * @param id The unique id of the action. Cannot be null.
289      * @param title The title of the multiple-choice itself
290      * @param callback A callback to execute when the context menu item is
291      *            selected.
292      * @param provider the provider which provides choices lazily
293      * @param current The id(s) of the current choice(s) that will be check
294      *            marked. Can be null. Can be an id not present in the choice
295      *            alternatives. There can be more than one id separated by
296      *            {@link #CHOICE_SEP}.
297      * @param iconUrl the icon to use for the multiple choice action itself
298      * @param sortPriority the sorting priority to use for the multiple choice
299      *            action itself
300      * @param supportsMultipleNodes whether this action supports multiple nodes,
301      *            see {@link #supportsMultipleNodes()} for details
302      * @return the new {@link Choices}
303      */
304     @NonNull
createChoices( @onNull String id, @NonNull String title, IMenuCallback callback, @NonNull ChoiceProvider provider, @Nullable String current, @Nullable URL iconUrl, int sortPriority, boolean supportsMultipleNodes)305     public static Choices createChoices(
306             @NonNull String id,
307             @NonNull String title,
308             IMenuCallback callback,
309             @NonNull ChoiceProvider provider,
310             @Nullable String current,
311             @Nullable URL iconUrl,
312             int sortPriority,
313             boolean supportsMultipleNodes) {
314         Choices choices = new DelayedChoices(id, title, callback,
315                 current, provider, sortPriority, supportsMultipleNodes);
316         choices.setIconUrl(iconUrl);
317         return choices;
318     }
319 
320     /**
321      * Creates a new {@link RuleAction} with the given id and the given title.
322      * Actions which have the same id and the same title are deemed equivalent.
323      *
324      * @param id The unique id of the action, which must be similar for all actions that
325      *           perform the same task. Cannot be null.
326      * @param title The UI-visible title of the action.
327      * @param callback A callback to execute when the context menu item is
328      *            selected.
329      * @param sortPriority a priority used for sorting this action
330      * @param supportsMultipleNodes the new return value for
331      *            {@link #supportsMultipleNodes()}
332      */
RuleAction( @onNull String id, @NonNull String title, @NonNull IMenuCallback callback, int sortPriority, boolean supportsMultipleNodes)333     private RuleAction(
334             @NonNull String id,
335             @NonNull String title,
336             @NonNull IMenuCallback callback,
337             int sortPriority,
338             boolean supportsMultipleNodes) {
339         mId = id;
340         mTitle = title;
341         mSortPriority = sortPriority;
342         mSupportsMultipleNodes = supportsMultipleNodes;
343         mCallback = callback;
344     }
345 
346     /**
347      * Returns the unique id of the action. In the context of a multiple selection,
348      * actions which have the same id are collapsed together and must represent the same
349      * action. Cannot be null.
350      *
351      * @return the unique id of the action, never null
352      */
353     @NonNull
getId()354     public String getId() {
355         return mId;
356     }
357 
358     /**
359      * Returns the UI-visible title of the action, shown in the context menu.
360      * Cannot be null.
361      *
362      * @return the user name of the action, never null
363      */
364     @NonNull
getTitle()365     public String getTitle() {
366         return mTitle;
367     }
368 
369     /**
370      * Actions which have the same id and the same title are deemed equivalent.
371      */
372     @Override
equals(Object obj)373     public boolean equals(Object obj) {
374         if (obj instanceof RuleAction) {
375             RuleAction rhs = (RuleAction) obj;
376 
377             if (mId != rhs.mId && !(mId != null && mId.equals(rhs.mId))) return false;
378             if (mTitle != rhs.mTitle &&
379                     !(mTitle != null && mTitle.equals(rhs.mTitle))) return false;
380             return true;
381         }
382         return false;
383     }
384 
385     /**
386      * Whether this action supports multiple nodes. An action which supports
387      * multiple nodes can be applied to different nodes by passing in different
388      * nodes to its callback. Some actions are hardcoded for a specific node (typically
389      * one that isn't selected, such as an action which affects the parent of a selected
390      * node), and these actions will not be added to the context menu when more than
391      * one node is selected.
392      *
393      * @return true if this node supports multiple nodes
394      */
supportsMultipleNodes()395     public boolean supportsMultipleNodes() {
396         return mSupportsMultipleNodes;
397     }
398 
399     /**
400      * Actions which have the same id and the same title have the same hash code.
401      */
402     @Override
hashCode()403     public int hashCode() {
404         int h = mId == null ? 0 : mId.hashCode();
405         h = h ^ (mTitle == null ? 0 : mTitle.hashCode());
406         return h;
407     }
408 
409     /**
410      * Gets a URL pointing to an icon to use for this action, if any.
411      *
412      * @return a URL pointing to an icon to use for this action, or null
413      */
getIconUrl()414     public URL getIconUrl() {
415         return mIconUrl;
416     }
417 
418     /**
419      * Sets a URL pointing to an icon to use for this action, if any.
420      *
421      * @param iconUrl a URL pointing to an icon to use for this action, or null
422      * @return this action, to allow setter chaining
423      */
424     @NonNull
setIconUrl(URL iconUrl)425     public RuleAction setIconUrl(URL iconUrl) {
426         mIconUrl = iconUrl;
427 
428         return this;
429     }
430 
431     /**
432      * Return a priority used for sorting this action
433      *
434      * @return a priority used for sorting this action
435      */
getSortPriority()436     public int getSortPriority() {
437         return mSortPriority;
438     }
439 
440     /**
441      * Returns the callback executed when the action is selected in the
442      * context menu. Cannot be null.
443      *
444      * @return the callback, never null
445      */
446     @NonNull
getCallback()447     public IMenuCallback getCallback() {
448         return mCallback;
449     }
450 
451     // Implements Comparable<MenuAction>
452     @Override
compareTo(RuleAction other)453     public int compareTo(RuleAction other) {
454         if (mSortPriority != other.mSortPriority) {
455             return mSortPriority - other.mSortPriority;
456         }
457 
458         return mTitle.compareTo(other.mTitle);
459     }
460 
461     @NonNull
462     @Override
toString()463     public String toString() {
464         return "RuleAction [id=" + mId + ", title=" + mTitle + ", priority=" + mSortPriority + "]";
465     }
466 
467     /** A separator to display between actions */
468     public static class Separator extends RuleAction {
469         /** Construct using the factory {@link #createSeparator(int)} */
Separator(int sortPriority, boolean supportsMultipleNodes)470         private Separator(int sortPriority, boolean supportsMultipleNodes) {
471             super("_separator", "", IMenuCallback.NONE, sortPriority,  //$NON-NLS-1$ //$NON-NLS-2$
472                     supportsMultipleNodes);
473         }
474     }
475 
476     /**
477      * A toggle is a simple on/off action, displayed as an item in a context menu
478      * with a check mark if the item is checked.
479      * <p/>
480      * Two toggles are equal if they have the same id, title and group-id.
481      * It is expected for the checked state and action callback to be different.
482      */
483     public static class Toggle extends RuleAction {
484         /**
485          * True if the item is displayed with a check mark.
486          */
487         private final boolean mIsChecked;
488 
489         /**
490          * Creates a new immutable toggle action.
491          *
492          * @param id The unique id of the action. Cannot be null.
493          * @param title The UI-visible title of the context menu item. Cannot be null.
494          * @param isChecked Whether the context menu item has a check mark.
495          * @param callback A callback to execute when the context menu item is
496          *            selected.
497          */
Toggle( @onNull String id, @NonNull String title, boolean isChecked, @NonNull IMenuCallback callback, int sortPriority, boolean supportsMultipleNodes)498         private Toggle(
499                 @NonNull String id,
500                 @NonNull String title,
501                 boolean isChecked,
502                 @NonNull IMenuCallback callback,
503                 int sortPriority,
504                 boolean supportsMultipleNodes) {
505             super(id, title, callback, sortPriority, supportsMultipleNodes);
506             mIsChecked = isChecked;
507         }
508 
509         /**
510          * Returns true if the item is displayed with a check mark.
511          *
512          * @return true if the item is displayed with a check mark.
513          */
isChecked()514         public boolean isChecked() {
515             return mIsChecked;
516         }
517 
518         /**
519          * Two toggles are equal if they have the same id and title.
520          * It is acceptable for the checked state and action callback to be different.
521          */
522         @Override
equals(Object obj)523         public boolean equals(Object obj) {
524             return super.equals(obj);
525         }
526 
527         /**
528          * Two toggles have the same hash code if they have the same id and title.
529          */
530         @Override
hashCode()531         public int hashCode() {
532             return super.hashCode();
533         }
534     }
535 
536     /**
537      * An ordered list of choices the user can choose between. For choosing between
538      * actions, there is a {@link NestedAction} class.
539      */
540     public static class Choices extends RuleAction {
541         protected List<String> mTitles;
542         protected List<URL> mIconUrls;
543         protected List<String> mIds;
544         private boolean mRadio;
545 
546         /**
547          * One or more id for the checked choice(s) that will be check marked.
548          * Can be null. Can be an id not present in the choices map.
549          */
550         protected final String mCurrent;
551 
Choices( @onNull String id, @NonNull String title, @NonNull IMenuCallback callback, @NonNull List<String> titles, @Nullable List<URL> iconUrls, @NonNull List<String> ids, @Nullable String current, int sortPriority, boolean supportsMultipleNodes)552         private Choices(
553                 @NonNull String id,
554                 @NonNull String title,
555                 @NonNull IMenuCallback callback,
556                 @NonNull List<String> titles,
557                 @Nullable List<URL> iconUrls,
558                 @NonNull List<String> ids,
559                 @Nullable String current,
560                 int sortPriority,
561                 boolean supportsMultipleNodes) {
562             super(id, title, callback, sortPriority, supportsMultipleNodes);
563             mTitles = titles;
564             mIconUrls = iconUrls;
565             mIds = ids;
566             mCurrent = current;
567         }
568 
569         /**
570          * Returns the list of urls to icons to display for each choice, or null
571          *
572          * @return the list of urls to icons to display for each choice, or null
573          */
574         @Nullable
getIconUrls()575         public List<URL> getIconUrls() {
576             return mIconUrls;
577         }
578 
579         /**
580          * Returns the list of ids for the menu choices, never null
581          *
582          * @return the list of ids for the menu choices, never null
583          */
584         @NonNull
getIds()585         public List<String> getIds() {
586             return mIds;
587         }
588 
589         /**
590          * Returns the titles to be displayed for the menu choices, never null
591          *
592          * @return the titles to be displayed for the menu choices, never null
593          */
594         @NonNull
getTitles()595         public List<String> getTitles() {
596             return mTitles;
597         }
598 
599         /**
600          * Returns the current value of the choice
601          *
602          * @return the current value of the choice, possibly null
603          */
604         @Nullable
getCurrent()605         public String getCurrent() {
606             return mCurrent;
607         }
608 
609         /**
610          * Set whether this choice list is best visualized as a radio group (instead of a
611          * dropdown)
612          *
613          * @param radio true if this choice list should be visualized as a radio group
614          */
setRadio(boolean radio)615         public void setRadio(boolean radio) {
616             mRadio = radio;
617         }
618 
619         /**
620          * Returns true if this choice list is best visualized as a radio group (instead
621          * of a dropdown)
622          *
623          * @return true if this choice list should be visualized as a radio group
624          */
isRadio()625         public boolean isRadio() {
626             return mRadio;
627         }
628     }
629 
630     /**
631      * An ordered list of actions the user can choose between. Similar to
632      * {@link Choices} but for actions instead.
633      */
634     public static class NestedAction extends RuleAction {
635         /** The provider to produce the list of nested actions when needed */
636         private final ActionProvider mProvider;
637 
NestedAction( @onNull String id, @NonNull String title, @NonNull ActionProvider provider, @NonNull IMenuCallback callback, int sortPriority, boolean supportsMultipleNodes)638         private NestedAction(
639                 @NonNull String id,
640                 @NonNull String title,
641                 @NonNull ActionProvider provider,
642                 @NonNull IMenuCallback callback,
643                 int sortPriority,
644                 boolean supportsMultipleNodes) {
645             super(id, title, callback, sortPriority, supportsMultipleNodes);
646             mProvider = provider;
647         }
648 
649         /**
650          * Returns the nested actions available for the given node
651          *
652          * @param node the node to look up nested actions for
653          * @return a list of nested actions
654          */
655         @NonNull
getNestedActions(@onNull INode node)656         public List<RuleAction> getNestedActions(@NonNull INode node) {
657             return mProvider.getNestedActions(node);
658         }
659     }
660 
661     /** Like {@link Choices}, but the set of choices is computed lazily */
662     private static class DelayedChoices extends Choices {
663         private final ChoiceProvider mProvider;
664         private boolean mInitialized;
665 
DelayedChoices( @onNull String id, @NonNull String title, @NonNull IMenuCallback callback, @Nullable String current, @NonNull ChoiceProvider provider, int sortPriority, boolean supportsMultipleNodes)666         private DelayedChoices(
667                 @NonNull String id,
668                 @NonNull String title,
669                 @NonNull IMenuCallback callback,
670                 @Nullable String current,
671                 @NonNull ChoiceProvider provider,
672                 int sortPriority, boolean supportsMultipleNodes) {
673             super(id, title, callback, new ArrayList<String>(), new ArrayList<URL>(),
674                     new ArrayList<String>(), current, sortPriority, supportsMultipleNodes);
675             mProvider = provider;
676         }
677 
ensureInitialized()678         private void ensureInitialized() {
679             if (!mInitialized) {
680                 mInitialized = true;
681                 mProvider.addChoices(mTitles, mIconUrls, mIds);
682             }
683         }
684 
685         @Override
getIconUrls()686         public List<URL> getIconUrls() {
687             ensureInitialized();
688             return mIconUrls;
689         }
690 
691         @Override
getIds()692         public @NonNull List<String> getIds() {
693             ensureInitialized();
694             return mIds;
695         }
696 
697         @Override
getTitles()698         public @NonNull List<String> getTitles() {
699             ensureInitialized();
700             return mTitles;
701         }
702     }
703 
704     /**
705      * Provides the set of nested action choices associated with a {@link NestedAction}
706      * object when they are needed. Useful for lazy initialization of context
707      * menus and popup menus until they are actually needed.
708      */
709     public interface ActionProvider {
710         /**
711          * Returns the nested actions available for the given node
712          *
713          * @param node the node to look up nested actions for
714          * @return a list of nested actions
715          */
716         @NonNull
getNestedActions(@onNull INode node)717         public List<RuleAction> getNestedActions(@NonNull INode node);
718     }
719 
720     /**
721      * Provides the set of choices associated with an {@link Choices}
722      * object when they are needed. Useful for lazy initialization of context
723      * menus and popup menus until they are actually needed.
724      */
725     public interface ChoiceProvider {
726         /**
727          * Adds in the needed titles, iconUrls (if any) and ids.
728          * Use {@link RuleAction#SEPARATOR} to create separators.
729          *
730          * @param titles a list of titles that the provider should append to
731          * @param iconUrls a list of icon URLs that the provider should append to
732          * @param ids a list of ids that the provider should append to
733          */
addChoices( @onNull List<String> titles, @NonNull List<URL> iconUrls, @NonNull List<String> ids)734         public void addChoices(
735                 @NonNull List<String> titles,
736                 @NonNull List<URL> iconUrls,
737                 @NonNull List<String> ids);
738     }
739 }
740