Home | History | Annotate | Download | only in api
      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.util.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
    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
    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
    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
    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
    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
    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
    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      */
    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
    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
    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
    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      */
    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
    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      */
    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
    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      */
    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
    447     public IMenuCallback getCallback() {
    448         return mCallback;
    449     }
    450 
    451     // Implements Comparable<MenuAciton>
    452     @Override
    453     public int compareTo(@NonNull 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
    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)} */
    470         private Separator(int sortPriority, boolean supportsMultipleNodes) {
    471             super("_separator", "", null, 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          */
    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          */
    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
    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
    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 
    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
    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
    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
    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
    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          */
    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          */
    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 
    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
    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 
    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 
    678         private void ensureInitialized() {
    679             if (!mInitialized) {
    680                 mInitialized = true;
    681                 mProvider.addChoices(mTitles, mIconUrls, mIds);
    682             }
    683         }
    684 
    685         @Override
    686         public List<URL> getIconUrls() {
    687             ensureInitialized();
    688             return mIconUrls;
    689         }
    690 
    691         @Override
    692         public List<String> getIds() {
    693             ensureInitialized();
    694             return mIds;
    695         }
    696 
    697         @Override
    698         public 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
    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          */
    734         public void addChoices(
    735                 @NonNull List<String> titles,
    736                 @NonNull List<URL> iconUrls,
    737                 @NonNull List<String> ids);
    738     }
    739 }
    740