/* * We want to return the menu item associated with the key, but if there is no * ambiguity (i.e. there is only one menu item corresponding to the key) we want * to return it even if it's not an exact match; this allow the user to * _not_ use the ALT key for example, making the use of shortcuts slightly more * user-friendly. An example is on the G1, '!' and '1' are on the same key, and * in Gmail, Menu+1 will trigger Menu+! (the actual shortcut). * * On the other hand, if two (or more) shortcuts corresponds to the same key, * we have to only return the exact match. */ MenuItemImpl findItemWithShortcutForKey(int keyCode, KeyEvent event) { // Get all items that can be associated directly or indirectly with the keyCode ArrayList<MenuItemImpl> items = mTempShortcutItemList; items.clear(); findItemsWithShortcutForKey(items, keyCode, event); if (items.isEmpty()) { return null; } final int metaState = event.getMetaState(); final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData(); // Get the chars associated with the keyCode (i.e using any chording combo) event.getKeyData(possibleChars); // If we have only one element, we can safely returns it final int size = items.size(); if (size == 1) { return items.get(0); } final boolean qwerty = isQwertyMode(); // If we found more than one item associated with the key, // we have to return the exact match for (int i = 0; i < size; i++) { final MenuItemImpl item = items.get(i); final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut(); if ((shortcutChar == possibleChars.meta[0] && (metaState & KeyEvent.META_ALT_ON) == 0) || (shortcutChar == possibleChars.meta[2] && (metaState & KeyEvent.META_ALT_ON) != 0) || (qwerty && shortcutChar == '\b' && keyCode == KeyEvent.KEYCODE_DEL)) { return item; } } return null; }
public SubMenu addSubMenu(int group, int id, int categoryOrder, CharSequence title) { final MenuItemImpl item = (MenuItemImpl) addInternal(group, id, categoryOrder, title); final SubMenuBuilder subMenu = new SubMenuBuilder(mContext, this, item); item.setSubMenu(subMenu); return subMenu; }
private void addItem(final Integer index, final MenuItemImpl item) { if (index != null) { getUiReference().getItems().add(index.intValue(), item.getUiReference()); } else { getUiReference().getItems().add(item.getUiReference()); } }
public boolean performItemAction(MenuItem item, int flags) { MenuItemImpl itemImpl = (MenuItemImpl) item; if (itemImpl == null || !itemImpl.isEnabled()) { return false; } boolean invoked = itemImpl.invoke(); // if (itemImpl.hasCollapsibleActionView()) { // invoked |= itemImpl.expandActionView(); // if (invoked) close(true); // } else if (item.hasSubMenu()) { // close(false); // // final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu(); // final ActionProvider provider = item.getActionProvider(); // if (provider != null && provider.hasSubMenu()) { // provider.onPrepareSubMenu(subMenu); // } // invoked |= dispatchSubMenuSelected(subMenu); // if (!invoked) close(true); // } else { if ((flags & FLAG_PERFORM_NO_CLOSE) == 0) { close(true); } } return invoked; }
public void setGroupEnabled(int group, boolean enabled) { final int N = mItems.size(); for (int i = 0; i < N; i++) { MenuItemImpl item = mItems.get(i); if (item.getGroupId() == group) { item.setEnabled(enabled); } } }
private static int findInsertIndex(ArrayList<MenuItemImpl> items, int ordering) { for (int i = items.size() - 1; i >= 0; i--) { MenuItemImpl item = items.get(i); if (item.getOrdering() <= ordering) { return i + 1; } } return 0; }
public void setGroupCheckable(int group, boolean checkable, boolean exclusive) { final int N = mItems.size(); for (int i = 0; i < N; i++) { MenuItemImpl item = mItems.get(i); if (item.getGroupId() == group) { item.setExclusiveCheckable(exclusive); item.setCheckable(checkable); } } }
public int findItemIndex(int id) { final int size = size(); for (int i = 0; i < size; i++) { MenuItemImpl item = mItems.get(i); if (item.getItemId() == id) { return i; } } return -1; }
public boolean hasVisibleItems() { final int size = size(); for (int i = 0; i < size; i++) { MenuItemImpl item = mItems.get(i); if (item.isVisible()) { return true; } } return false; }
public void localeChanged() { this.setText(Strings.get("fileMenu")); newi.setText(Strings.get("fileNewItem")); open.setText(Strings.get("fileOpenItem")); openRecent.localeChanged(); close.setText(Strings.get("fileCloseItem")); save.setText(Strings.get("fileSaveItem")); saveAs.setText(Strings.get("fileSaveAsItem")); exportImage.setText(Strings.get("fileExportImageItem")); print.setText(Strings.get("filePrintItem")); prefs.setText(Strings.get("filePreferencesItem")); quit.setText(Strings.get("fileQuitItem")); }
void setExclusiveItemChecked(MenuItem item) { final int group = item.getGroupId(); final int N = mItems.size(); for (int i = 0; i < N; i++) { MenuItemImpl curItem = mItems.get(i); if (curItem.getGroupId() == group) { if (!curItem.isExclusiveCheckable()) continue; if (!curItem.isCheckable()) continue; // Check the item meant to be checked, uncheck the others (that are in the group) curItem.setCheckedInt(curItem == item); } } }
public void setGroupVisible(int group, boolean visible) { final int N = mItems.size(); // We handle the notification of items being changed ourselves, so we use setVisibleInt rather // than setVisible and at the end notify of items being changed boolean changedAtLeastOneItem = false; for (int i = 0; i < N; i++) { MenuItemImpl item = mItems.get(i); if (item.getGroupId() == group) { if (item.setVisibleInt(visible)) changedAtLeastOneItem = true; } } if (changedAtLeastOneItem) onItemsChanged(true); }
/** Adds an item to the menu. The other add methods funnel to this. */ private MenuItem addInternal(int group, int id, int categoryOrder, CharSequence title) { final int ordering = getOrdering(categoryOrder); final MenuItemImpl item = new MenuItemImpl(this, group, id, categoryOrder, ordering, title, mDefaultShowAsAction); if (mCurrentMenuInfo != null) { // Pass along the current menu info item.setMenuInfo(mCurrentMenuInfo); } mItems.add(findInsertIndex(mItems, ordering), item); onItemsChanged(true); return item; }
public MenuItem findItem(int id) { final int size = size(); for (int i = 0; i < size; i++) { MenuItemImpl item = mItems.get(i); if (item.getItemId() == id) { return item; } else if (item.hasSubMenu()) { MenuItem possibleItem = item.getSubMenu().findItem(id); if (possibleItem != null) { return possibleItem; } } } return null; }
@Override public String getActionViewStatesKey() { final int itemId = mItem != null ? mItem.getItemId() : 0; if (itemId == 0) { return null; } return super.getActionViewStatesKey() + ":" + itemId; }
public int findGroupIndex(int group, int start) { final int size = size(); if (start < 0) { start = 0; } for (int i = start; i < size; i++) { final MenuItemImpl item = mItems.get(i); if (item.getGroupId() == group) { return i; } } return -1; }
ArrayList<MenuItemImpl> getVisibleItems() { if (!mIsVisibleItemsStale) return mVisibleItems; // Refresh the visible items mVisibleItems.clear(); final int itemsSize = mItems.size(); MenuItemImpl item; for (int i = 0; i < itemsSize; i++) { item = mItems.get(i); if (item.isVisible()) mVisibleItems.add(item); } mIsVisibleItemsStale = false; mIsActionItemsStale = true; return mVisibleItems; }
public MenuFile(LogisimMenuBar menubar) { this.menubar = menubar; openRecent = new OpenRecent(menubar); int menuMask = getToolkit().getMenuShortcutKeyMask(); newi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, menuMask)); merge.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, menuMask)); open.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, menuMask)); close.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, menuMask | InputEvent.SHIFT_MASK)); save.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, menuMask)); saveAs.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, menuMask | InputEvent.SHIFT_MASK)); print.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, menuMask)); quit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, menuMask)); add(newi); add(merge); add(open); add(openRecent); addSeparator(); add(close); add(save); add(saveAs); addSeparator(); add(exportImage); add(print); if (!MacCompatibility.isPreferencesAutomaticallyPresent()) { addSeparator(); add(prefs); } if (!MacCompatibility.isQuitAutomaticallyPresent()) { addSeparator(); add(quit); } Project proj = menubar.getProject(); newi.addActionListener(this); open.addActionListener(this); if (proj == null) { merge.setEnabled(false); close.setEnabled(false); save.setEnabled(false); saveAs.setEnabled(false); } else { merge.addActionListener(this); close.addActionListener(this); save.addActionListener(this); saveAs.addActionListener(this); } menubar.registerItem(LogisimMenuBar.EXPORT_IMAGE, exportImage); menubar.registerItem(LogisimMenuBar.PRINT, print); prefs.addActionListener(this); quit.addActionListener(this); }
/** * This method determines which menu items get to be 'action items' that will appear in an action * bar and which items should be 'overflow items' in a secondary menu. The rules are as follows: * * <p>Items are considered for inclusion in the order specified within the menu. There is a limit * of mMaxActionItems as a total count, optionally including the overflow menu button itself. This * is a soft limit; if an item shares a group ID with an item previously included as an action * item, the new item will stay with its group and become an action item itself even if it breaks * the max item count limit. This is done to limit the conceptual complexity of the items * presented within an action bar. Only a few unrelated concepts should be presented to the user * in this space, and groups are treated as a single concept. * * <p>There is also a hard limit of consumed measurable space: mActionWidthLimit. This limit may * be broken by a single item that exceeds the remaining space, but no further items may be added. * If an item that is part of a group cannot fit within the remaining measured width, the entire * group will be demoted to overflow. This is done to ensure room for navigation and other * affordances in the action bar as well as reduce general UI clutter. * * <p>The space freed by demoting a full group cannot be consumed by future menu items. Once items * begin to overflow, all future items become overflow items as well. This is to avoid inadvertent * reordering that may break the app's intended design. */ public void flagActionItems() { // Important side effect: if getVisibleItems is stale it may refresh, // which can affect action items staleness. final ArrayList<MenuItemImpl> visibleItems = getVisibleItems(); if (!mIsActionItemsStale) { return; } // Presenters flag action items as needed. boolean flagged = false; for (WeakReference<MenuPresenter> ref : mPresenters) { final MenuPresenter presenter = ref.get(); if (presenter == null) { mPresenters.remove(ref); } else { flagged |= presenter.flagActionItems(); } } if (flagged) { mActionItems.clear(); mNonActionItems.clear(); final int itemsSize = visibleItems.size(); for (int i = 0; i < itemsSize; i++) { MenuItemImpl item = visibleItems.get(i); if (item.isActionButton()) { mActionItems.add(item); } else { mNonActionItems.add(item); } } } else { // Nobody flagged anything, everything is a non-action item. // (This happens during a first pass with no action-item presenters.) mActionItems.clear(); mNonActionItems.clear(); mNonActionItems.addAll(getVisibleItems()); } mIsActionItemsStale = false; }
/* * This function will return all the menu and sub-menu items that can * be directly (the shortcut directly corresponds) and indirectly * (the ALT-enabled char corresponds to the shortcut) associated * with the keyCode. */ void findItemsWithShortcutForKey(List<MenuItemImpl> items, int keyCode, KeyEvent event) { final boolean qwerty = isQwertyMode(); final int metaState = event.getMetaState(); final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData(); // Get the chars associated with the keyCode (i.e using any chording combo) final boolean isKeyCodeMapped = event.getKeyData(possibleChars); // The delete key is not mapped to '\b' so we treat it specially if (!isKeyCodeMapped && (keyCode != KeyEvent.KEYCODE_DEL)) { return; } // Look for an item whose shortcut is this key. final int N = mItems.size(); for (int i = 0; i < N; i++) { MenuItemImpl item = mItems.get(i); if (item.hasSubMenu()) { ((MenuBuilder) item.getSubMenu()).findItemsWithShortcutForKey(items, keyCode, event); } final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut(); if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0) && (shortcutChar != 0) && (shortcutChar == possibleChars.meta[0] || shortcutChar == possibleChars.meta[2] || (qwerty && shortcutChar == '\b' && keyCode == KeyEvent.KEYCODE_DEL)) && item.isEnabled()) { items.add(item); } } }
@Override public SubMenu addSubMenu(int groupId, int itemId, int order, CharSequence title) { final MenuItem item = new MenuItemImpl(mContext) .setGroupId(groupId) .setItemId(itemId) .setOrder(order) .setTitle(title); final SubMenu subMenu = new SubMenuImpl(mContext, item); ((MenuItemImpl) item).setSubMenu(subMenu); if (order != 0) { mMenuItems.add(order, item); } else { mMenuItems.add(item); } return subMenu; }
@Override public void setMnemonic(final char mnemonic) { menuItemDelegate.setMnemonic(mnemonic); }
@Override public void setText(final String text) { menuItemDelegate.setText(text); }
public SubMenu setIcon(Drawable icon) { mItem.setIcon(icon); return this; }
@Override public Menu getUiReference() { return (Menu) menuItemDelegate.getUiReference(); }
public SubMenu setIcon(int iconRes) { mItem.setIcon(iconRes); return this; }