gt:             if (presenter == null) {
context: /*
   * Copyright (C) 2012 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package android.support.v7.internal.view.menu;
  
  import android.content.ComponentName;
  import android.content.Context;
  import android.content.Intent;
  import android.content.pm.PackageManager;
  import android.content.pm.ResolveInfo;
  import android.content.res.Configuration;
  import android.content.res.Resources;
  import android.graphics.drawable.Drawable;
  import android.os.Bundle;
  import android.os.Parcelable;
  import android.support.v4.content.ContextCompat;
  import android.support.v4.view.MenuItemCompat;
  import android.support.v7.appcompat.R;
  import android.support.v4.view.ActionProvider;
  import android.support.v4.internal.view.SupportMenu;
  import android.support.v4.internal.view.SupportMenuItem;
  import android.util.SparseArray;
  import android.view.ContextMenu;
  import android.view.KeyCharacterMap;
  import android.view.KeyEvent;
  import android.view.MenuItem;
  import android.view.SubMenu;
  import android.view.View;
  
  import java.lang.ref.WeakReference;
  import java.util.ArrayList;
  import java.util.List;
  import java.util.concurrent.CopyOnWriteArrayList;
  
  /**
   * Implementation of the {@link android.support.v4.internal.view.SupportMenu} interface for creating a
   * standard menu UI.
   *
   * @hide
   */
  public class MenuBuilder implements SupportMenu {
  
      private static final String TAG = "MenuBuilder";
  
      private static final String PRESENTER_KEY = "android:menu:presenters";
      private static final String ACTION_VIEW_STATES_KEY = "android:menu:actionviewstates";
      private static final String EXPANDED_ACTION_VIEW_ID = "android:menu:expandedactionview";
  
      private static final int[] sCategoryToOrder = new int[]{
              1, /* No category */
              4, /* CONTAINER */
              5, /* SYSTEM */
              3, /* SECONDARY */
              2, /* ALTERNATIVE */
              0, /* SELECTED_ALTERNATIVE */
      };
  
      private final Context mContext;
  
      private final Resources mResources;
  
      /**
       * Whether the shortcuts should be qwerty-accessible. Use isQwertyMode() instead of accessing
       * this directly.
       */
      private boolean mQwertyMode;
  
      /**
       * Whether the shortcuts should be visible on menus. Use isShortcutsVisible() instead of
       * accessing this directly.
       */
      private boolean mShortcutsVisible;
  
      /**
       * Callback that will receive the various menu-related events generated by this class. Use
       * getCallback to get a reference to the callback.
       */
      private Callback mCallback;
  
      /**
       * Contains all of the items for this menu
       */
      private ArrayList<MenuItemImpl> mItems;
  
      /**
       * Contains only the items that are currently visible.  This will be created/refreshed from
       * {@link #getVisibleItems()}
       */
      private ArrayList<MenuItemImpl> mVisibleItems;
  
      /**
       * Whether or not the items (or any one item's shown state) has changed since it was last
       * fetched from {@link #getVisibleItems()}
       */
      private boolean mIsVisibleItemsStale;
  
      /**
       * Contains only the items that should appear in the Action Bar, if present.
       */
      private ArrayList<MenuItemImpl> mActionItems;
  
      /**
       * Contains items that should NOT appear in the Action Bar, if present.
       */
      private ArrayList<MenuItemImpl> mNonActionItems;
  
      /**
       * Whether or not the items (or any one item's action state) has changed since it was last
       * fetched.
       */
      private boolean mIsActionItemsStale;
  
      /**
       * Default value for how added items should show in the action list.
       */
      private int mDefaultShowAsAction = SupportMenuItem.SHOW_AS_ACTION_NEVER;
  
      /**
       * Current use case is Context Menus: As Views populate the context menu, each one has extra
       * information that should be passed along.  This is the current menu info that should be set on
       * all items added to this menu.
       */
      private ContextMenu.ContextMenuInfo mCurrentMenuInfo;
  
      /**
       * Header title for menu types that have a header (context and submenus)
       */
      CharSequence mHeaderTitle;
  
      /**
       * Header icon for menu types that have a header and support icons (context)
       */
      Drawable mHeaderIcon;
      /** Header custom view for menu types that have a header and support custom views (context) */
      View mHeaderView;
  
      /**
       * Contains the state of the View hierarchy for all menu views when the menu
       * was frozen.
       */
      private SparseArray<Parcelable> mFrozenViewStates;
  
      /**
       * Prevents onItemsChanged from doing its junk, useful for batching commands
       * that may individually call onItemsChanged.
       */
      private boolean mPreventDispatchingItemsChanged = false;
  
      private boolean mItemsChangedWhileDispatchPrevented = false;
  
      private boolean mOptionalIconsVisible = false;
  
      private boolean mIsClosing = false;
  
      private ArrayList<MenuItemImpl> mTempShortcutItemList = new ArrayList<MenuItemImpl>();
  
      private CopyOnWriteArrayList<WeakReference<MenuPresenter>> mPresenters =
              new CopyOnWriteArrayList<WeakReference<MenuPresenter>>();
  
      /**
       * Currently expanded menu item; must be collapsed when we clear.
       */
      private MenuItemImpl mExpandedItem;
  
      /**
       * Called by menu to notify of close and selection changes.
       * @hide
       */
      public interface Callback {
  
          /**
           * Called when a menu item is selected.
           *
           * @param menu The menu that is the parent of the item
           * @param item The menu item that is selected
           * @return whether the menu item selection was handled
           */
          public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item);
  
          /**
           * Called when the mode of the menu changes (for example, from icon to expanded).
           *
           * @param menu the menu that has changed modes
           */
          public void onMenuModeChange(MenuBuilder menu);
      }
  
      /**
       * Called by menu items to execute their associated action
       * @hide
       */
      public interface ItemInvoker {
          public boolean invokeItem(MenuItemImpl item);
      }
  
      public MenuBuilder(Context context) {
          mContext = context;
          mResources = context.getResources();
  
          mItems = new ArrayList<MenuItemImpl>();
  
          mVisibleItems = new ArrayList<MenuItemImpl>();
          mIsVisibleItemsStale = true;
  
          mActionItems = new ArrayList<MenuItemImpl>();
          mNonActionItems = new ArrayList<MenuItemImpl>();
          mIsActionItemsStale = true;
  
          setShortcutsVisibleInner(true);
      }
  
      public MenuBuilder setDefaultShowAsAction(int defaultShowAsAction) {
          mDefaultShowAsAction = defaultShowAsAction;
          return this;
      }
  
      /**
       * Add a presenter to this menu. This will only hold a WeakReference; you do not need to
       * explicitly remove a presenter, but you can using {@link #removeMenuPresenter(MenuPresenter)}.
       *
       * @param presenter The presenter to add
       */
      public void addMenuPresenter(MenuPresenter presenter) {
          addMenuPresenter(presenter, mContext);
      }
  
      /**
       * Add a presenter to this menu that uses an alternate context for
       * inflating menu items. This will only hold a WeakReference; you do not
       * need to explicitly remove a presenter, but you can using
       * {@link #removeMenuPresenter(MenuPresenter)}.
       *
       * @param presenter The presenter to add
       * @param menuContext The context used to inflate menu items
       */
      public void addMenuPresenter(MenuPresenter presenter, Context menuContext) {
          mPresenters.add(new WeakReference<MenuPresenter>(presenter));
          presenter.initForMenu(menuContext, this);
          mIsActionItemsStale = true;
      }
  
      /**
       * Remove a presenter from this menu. That presenter will no longer receive notifications of
       * updates to this menu's data.
       *
       * @param presenter The presenter to remove
       */
      public void removeMenuPresenter(MenuPresenter presenter) {
          for (WeakReference<MenuPresenter> ref : mPresenters) {
              final MenuPresenter item = ref.get();
              if (item == null || item == presenter) {
                  mPresenters.remove(ref);
              }
          }
      }
  
      private void dispatchPresenterUpdate(boolean cleared) {
          if (mPresenters.isEmpty()) return;
  
          stopDispatchingItemsChanged();
          for (WeakReference<MenuPresenter> ref : mPresenters) {
              final MenuPresenter presenter = ref.get();
              if (presenter == null) {
                  mPresenters.remove(ref);
              } else {
                  presenter.updateMenuView(cleared);
              }
          }
          startDispatchingItemsChanged();
      }
  
      private boolean dispatchSubMenuSelected(SubMenuBuilder subMenu,
              MenuPresenter preferredPresenter) {
          if (mPresenters.isEmpty()) return false;
  
          boolean result = false;
  
          // Try the preferred presenter first.
          if (preferredPresenter != null) {
              result = preferredPresenter.onSubMenuSelected(subMenu);
          }
  
          for (WeakReference<MenuPresenter> ref : mPresenters) {
              final MenuPresenter presenter = ref.get();
  