content: /*
   * Copyright (C) 2014 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 com.alirezaafkar.toolbar;
  
  import android.app.ActionBar;
  import android.content.Context;
  import android.graphics.drawable.Drawable;
  import android.os.Parcelable;
  import android.support.v4.view.ViewCompat;
  import android.support.v4.view.ViewPropertyAnimatorCompat;
  import android.support.v4.view.ViewPropertyAnimatorListenerAdapter;
  import android.support.v7.app.WindowDecorActionBar;
  import android.support.v7.view.menu.ActionMenuItem;
  import android.support.v7.view.menu.MenuBuilder;
  import android.support.v7.view.menu.MenuPresenter;
  import android.support.v7.widget.AppCompatDrawableManager;
  import android.support.v7.widget.AppCompatSpinner;
  import android.support.v7.widget.DecorToolbar;
  import android.support.v7.widget.ScrollingTabContainerView;
  import android.support.v7.widget.TintTypedArray;
  import android.text.TextUtils;
  import android.util.Log;
  import android.util.SparseArray;
  import android.view.Gravity;
  import android.view.LayoutInflater;
  import android.view.Menu;
  import android.view.View;
  import android.view.ViewGroup;
  import android.view.Window;
  import android.widget.AdapterView;
  import android.widget.Spinner;
  import android.widget.SpinnerAdapter;
  
  /**
   * Internal class used to interact with the Toolbar widget without
   * exposing interface methods to the public API.
   * <p/>
   * <p>ToolbarWidgetWrapper manages the differences between Toolbar and ActionBarView
   * so that either variant acting as a
   * {@link WindowDecorActionBar WindowDecorActionBar} can behave
   * in the same way.</p>
   *
   * @hide
   */
  class ToolbarWidgetWrapper implements DecorToolbar {
      private static final String TAG = "ToolbarWidgetWrapper";
  
      private static final int AFFECTS_LOGO_MASK =
              ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_USE_LOGO;
      // Default fade duration for fading in/out tool bar.
      private static final long DEFAULT_FADE_DURATION_MS = 200;
  
      private RtlToolbar mToolbar;
  
      private int mDisplayOpts;
      private View mTabView;
      private Spinner mSpinner;
      private View mCustomView;
  
      private Drawable mIcon;
      private Drawable mLogo;
      private Drawable mNavIcon;
  
      private boolean mTitleSet;
      private CharSequence mTitle;
      private CharSequence mSubtitle;
      private CharSequence mHomeDescription;
  
      private Window.Callback mWindowCallback;
      private boolean mMenuPrepared;
      private ActionMenuPresenter mActionMenuPresenter;
  
      private int mNavigationMode = ActionBar.NAVIGATION_MODE_STANDARD;
  
      private final AppCompatDrawableManager mDrawableManager;
      private int mDefaultNavigationContentDescription = 0;
      private Drawable mDefaultNavigationIcon;
  
      private int mDirection;
  
      public ToolbarWidgetWrapper(RtlToolbar toolbar, boolean style, int direction) {
          this(toolbar, style, android.support.v7.appcompat.R.string.abc_action_bar_up_description,
                  android.support.v7.appcompat.R.drawable.abc_ic_ab_back_material);
          mDirection = direction;
      }
  
      public ToolbarWidgetWrapper(RtlToolbar toolbar, boolean style,
                                  int defaultNavigationContentDescription, int defaultNavigationIcon) {
          mToolbar = toolbar;
          mTitle = toolbar.getTitle();
          mSubtitle = toolbar.getSubtitle();
          mTitleSet = mTitle != null;
          mNavIcon = toolbar.getNavigationIcon();
  
          if (style) {
              final TintTypedArray a = TintTypedArray.obtainStyledAttributes(toolbar.getContext(),
                      null, R.styleable.ActionBar, R.attr.actionBarStyle, 0);
  
              final CharSequence title = a.getText(R.styleable.ActionBar_title);
              if (!TextUtils.isEmpty(title)) {
                  setTitle(title);
              }
  
              final CharSequence subtitle = a.getText(R.styleable.ActionBar_subtitle);
              if (!TextUtils.isEmpty(subtitle)) {
                  setSubtitle(subtitle);
              }
  
              final Drawable logo = a.getDrawable(R.styleable.ActionBar_logo);
              if (logo != null) {
                  setLogo(logo);
              }
  
              final Drawable icon = a.getDrawable(R.styleable.ActionBar_icon);
              if (mNavIcon == null && icon != null) {
                  setIcon(icon);
              }
  
              final Drawable navIcon = a.getDrawable(R.styleable.ActionBar_homeAsUpIndicator);
              if (navIcon != null) {
                  setNavigationIcon(navIcon);
              }
  
              setDisplayOptions(a.getInt(R.styleable.ActionBar_displayOptions, 0));
  
              final int customNavId = a.getResourceId(
                      R.styleable.ActionBar_customNavigationLayout, 0);
              if (customNavId != 0) {
                  setCustomView(LayoutInflater.from(mToolbar.getContext()).inflate(customNavId,
                          mToolbar, false));
                  setDisplayOptions(mDisplayOpts | ActionBar.DISPLAY_SHOW_CUSTOM);
              }
  
              final int height = a.getLayoutDimension(R.styleable.ActionBar_height, 0);
              if (height > 0) {
                  final ViewGroup.LayoutParams lp = mToolbar.getLayoutParams();
                  lp.height = height;
                  mToolbar.setLayoutParams(lp);
              }
  
              final int contentInsetStart = a.getDimensionPixelOffset(
                      R.styleable.ActionBar_contentInsetStart, -1);
              final int contentInsetEnd = a.getDimensionPixelOffset(
                      R.styleable.ActionBar_contentInsetEnd, -1);
              if (contentInsetStart >= 0 || contentInsetEnd >= 0) {
                  mToolbar.setContentInsetsRelative(Math.max(contentInsetStart, 0),
                          Math.max(contentInsetEnd, 0));
              }
  
              final int titleTextStyle = a.getResourceId(R.styleable.ActionBar_titleTextStyle, 0);
              if (titleTextStyle != 0) {
                  mToolbar.setTitleTextAppearance(mToolbar.getContext(), titleTextStyle);
              }
  
              final int subtitleTextStyle = a.getResourceId(
                      R.styleable.ActionBar_subtitleTextStyle, 0);
              if (subtitleTextStyle != 0) {
                  mToolbar.setSubtitleTextAppearance(mToolbar.getContext(), subtitleTextStyle);
              }
  
              final int popupTheme = a.getResourceId(R.styleable.ActionBar_popupTheme, 0);
              if (popupTheme != 0) {
                  mToolbar.setPopupTheme(popupTheme);
              }
  
              a.recycle();
          } else {
              mDisplayOpts = detectDisplayOptions();
          }
  
          mDrawableManager = AppCompatDrawableManager.get();
  
          setDefaultNavigationContentDescription(defaultNavigationContentDescription);
          mHomeDescription = mToolbar.getNavigationContentDescription();
  
          setDefaultNavigationIcon(mDrawableManager.getDrawable(getContext(), defaultNavigationIcon));
  
          mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
              final ActionMenuItem mNavItem = new ActionMenuItem(mToolbar.getContext(),
                      0, android.R.id.home, 0, 0, mTitle);
  
              @Override
              public void onClick(View v) {
                  if (mWindowCallback != null && mMenuPrepared) {
                      mWindowCallback.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, mNavItem);
                  }
              }
          });
      }
  
      /**
       * Sets the default content description for the navigation button.
       * <p/>
       * It changes the current content description if and only if the provided resource id is
       * different than the current default resource id and the current content description is empty.
       *
       * @param defaultNavigationContentDescription The resource id for the default content
       *                                            description
       */
      @Override
      public void setDefaultNavigationContentDescription(int defaultNavigationContentDescription) {
          if (defaultNavigationContentDescription == mDefaultNavigationContentDescription) {
              return;
          }
          mDefaultNavigationContentDescription = defaultNavigationContentDescription;
          if (TextUtils.isEmpty(mToolbar.getNavigationContentDescription())) {
              setNavigationContentDescription(mDefaultNavigationContentDescription);
          }
      }
  
      @Override
      public void setDefaultNavigationIcon(Drawable defaultNavigationIcon) {
          if (mDefaultNavigationIcon != defaultNavigationIcon) {
              mDefaultNavigationIcon = defaultNavigationIcon;
              updateNavigationIcon();
          }
      }
  
      private int detectDisplayOptions() {
          int opts = ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_HOME |
                  ActionBar.DISPLAY_USE_LOGO;
          if (mToolbar.getNavigationIcon() != null) {
              opts |= ActionBar.DISPLAY_HOME_AS_UP;
          }
          return opts;
      }
  
      @Override
      public ViewGroup getViewGroup() {
          return mToolbar;
      }
  
      @Override
      public Context getContext() {
          return mToolbar.getContext();
      }
  
      @Override
      public boolean hasExpandedActionView() {
          return mToolbar.hasExpandedActionView();
      }
  
      @Override
      public void collapseActionView() {
          mToolbar.collapseActionView();
      }
  
      @Override
      public void setWindowCallback(Window.Callback cb) {
          mWindowCallback = cb;
      }
  
      @Override
      public void setWindowTitle(CharSequence title) {
          // "Real" title always trumps window title.
          if (!mTitleSet) {
              setTitleInt(title);
          }
      }
  
      @Override
      public CharSequence getTitle() {
          return mToolbar.getTitle();
      }
  
      @Override
      public void setTitle(CharSequence title) {
          mTitleSet = true;
          setTitleInt(title);
      }
  
      private void setTitleInt(CharSequence title) {
          mTitle = title;
          if ((mDisplayOpts & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
              mToolbar.setTitle(title);
          }
      }
  
      @Override
      public CharSequence getSubtitle() {
          return mToolbar.getSubtitle();
      }
  
      @Override
      public void setSubtitle(CharSequence subtitle) {
          mSubtitle = subtitle;
          if ((mDisplayOpts & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
              mToolbar.setSubtitle(subtitle);
          }
      }
  
      @Override
      public void initProgress() {
          Log.i(TAG, "Progress display unsupported");
      }
  
      @Override
      public void initIndeterminateProgress() {
          Log.i(TAG, "Progress display unsupported");
      }
  
      @Override
      public boolean hasIcon() {
          return mIcon != null;
      }
  
      @Override
      public boolean hasLogo() {
          return mLogo != null;
      }
  
      @Override
      public void setIcon(int resId) {
          setIcon(resId != 0 ? mDrawableManager.getDrawable(getContext(), resId) : null);
      }
  
      @Override
      public void setIcon(Drawable d) {
          mIcon = d;
          updateToolbarLogo();
      }
  
      @Override
      public void setLogo(int resId) {
          setLogo(resId != 0 ? mDrawableManager.getDrawable(getContext(), resId) : null);
      }
  
      @Override
      public void setLogo(Drawable d) {
          mLogo = d;
          updateToolbarLogo();
      }
  
      private void updateToolbarLogo() {
          Drawable logo = null;
          if ((mDisplayOpts & ActionBar.DISPLAY_SHOW_HOME) != 0) {
              if ((mDisplayOpts & ActionBar.DISPLAY_USE_LOGO) != 0) {
                  logo = mLogo != null ? mLogo : mIcon;
              } else {
                  logo = mIcon;
              }
          }
          mToolbar.setLogo(logo);
      }
  
      @Override
      public boolean canShowOverflowMenu() {
          return mToolbar.canShowOverflowMenu();
      }
  
      @Override
      public boolean isOverflowMenuShowing() {
          return mToolbar.isOverflowMenuShowing();
      }
  
      @Override
      public boolean isOverflowMenuShowPending() {
          return mToolbar.isOverflowMenuShowPending();
      }
  
      @Override
      public boolean showOverflowMenu() {
          return mToolbar.showOverflowMenu();
      }
  
      @Override
      public boolean hideOverflowMenu() {
          return mToolbar.hideOverflowMenu();
      }
  
      @Override
      public void setMenuPrepared() {
          mMenuPrepared = true;
      }
  
      @Override
      public void setMenu(Menu menu, MenuPresenter.Callback cb) {
          if (mActionMenuPresenter == null) {
              mActionMenuPresenter = new ActionMenuPresenter(mToolbar.getContext(), mDirection);
              mActionMenuPresenter.setId(R.id.action_menu_presenter);
          }
          mActionMenuPresenter.setCallback(cb);
          mToolbar.setMenu((MenuBuilder) menu, mActionMenuPresenter);
      }
  
      @Override
      public void dismissPopupMenus() {
          mToolbar.dismissPopupMenus();
      }
  
      @Override
      public int getDisplayOptions() {
          return mDisplayOpts;
      }
  
      @Override
      public void setDisplayOptions(int newOpts) {
          final int oldOpts = mDisplayOpts;
          final int changed = oldOpts ^ newOpts;
          mDisplayOpts = newOpts;
          if (changed != 0) {
              if ((changed & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
                  if ((newOpts & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
                      updateNavigationIcon();
                      updateHomeAccessibility();
                  } else {
                      mToolbar.setNavigationIcon(null);
                  }
              }
  
              if ((changed & AFFECTS_LOGO_MASK) != 0) {
                  updateToolbarLogo();
              }
  
              if ((changed & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
                  if ((newOpts & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
                      mToolbar.setTitle(mTitle);
                      mToolbar.setSubtitle(mSubtitle);
                  } else {
                      mToolbar.setTitle(null);
                      mToolbar.setSubtitle(null);
                  }
              }
  
              if ((changed & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomView != null) {
                  if ((newOpts & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
                      mToolbar.addView(mCustomView);
                  } else {
                      mToolbar.removeView(mCustomView);
                  }
              }
          }
      }
  
      @Override
      public void setEmbeddedTabView(ScrollingTabContainerView tabView) {
          if (mTabView != null && mTabView.getParent() == mToolbar) {
              mToolbar.removeView(mTabView);
          }
          mTabView = tabView;
          if (tabView != null && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) {
              mToolbar.addView(mTabView, 0);
              RtlToolbar.LayoutParams lp = (RtlToolbar.LayoutParams) mTabView.getLayoutParams();
              lp.width = ViewGroup.LayoutParams.WRAP_CONTENT;
              lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
              lp.gravity = Gravity.START | Gravity.BOTTOM;
              tabView.setAllowCollapse(true);
          }
      }
  
      @Override
      public boolean hasEmbeddedTabs() {
          return mTabView != null;
      }
  
      @Override
      public boolean isTitleTruncated() {
          return mToolbar.isTitleTruncated();
      }
  
      @Override
      public void setCollapsible(boolean collapsible) {
          mToolbar.setCollapsible(collapsible);
      }
  
      @Override
      public void setHomeButtonEnabled(boolean enable) {
          // Ignore
      }
  
      @Override
      public int getNavigationMode() {
          return mNavigationMode;
      }
  
      @Override
      public void setNavigationMode(int mode) {
          final int oldMode = mNavigationMode;
          if (mode != oldMode) {
              switch (oldMode) {
                  case ActionBar.NAVIGATION_MODE_LIST:
                      if (mSpinner != null && mSpinner.getParent() == mToolbar) {
                          mToolbar.removeView(mSpinner);
                      }
                      break;
                  case ActionBar.NAVIGATION_MODE_TABS:
                      if (mTabView != null && mTabView.getParent() == mToolbar) {
                          mToolbar.removeView(mTabView);
                      }
                      break;
              }
  
              mNavigationMode = mode;
  
              switch (mode) {
                  case ActionBar.NAVIGATION_MODE_STANDARD:
                      break;
                  case ActionBar.NAVIGATION_MODE_LIST:
                      ensureSpinner();
                      mToolbar.addView(mSpinner, 0);
                      break;
                  case ActionBar.NAVIGATION_MODE_TABS:
                      if (mTabView != null) {
                          mToolbar.addView(mTabView, 0);
                          RtlToolbar.LayoutParams lp = (RtlToolbar.LayoutParams) mTabView.getLayoutParams();
                          lp.width = ViewGroup.LayoutParams.WRAP_CONTENT;
                          lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
                          lp.gravity = Gravity.START | Gravity.BOTTOM;
                      }
                      break;
                  default:
                      throw new IllegalArgumentException("Invalid navigation mode " + mode);
              }
          }
      }
  
      private void ensureSpinner() {
          if (mSpinner == null) {
              mSpinner = new AppCompatSpinner(getContext(), null, R.attr.actionDropDownStyle);
              RtlToolbar.LayoutParams lp = new RtlToolbar.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                      ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL);
              mSpinner.setLayoutParams(lp);
          }
      }
  
      @Override
      public void setDropdownParams(SpinnerAdapter adapter,
                                    AdapterView.OnItemSelectedListener listener) {
          ensureSpinner();
          mSpinner.setAdapter(adapter);
          mSpinner.setOnItemSelectedListener(listener);
      }
  
      @Override
      public void setDropdownSelectedPosition(int position) {
          if (mSpinner == null) {
              throw new IllegalStateException(
                      "Can't set dropdown selected position without an adapter");
          }
          mSpinner.setSelection(position);
      }
  
      @Override
      public int getDropdownSelectedPosition() {
          return mSpinner != null ? mSpinner.getSelectedItemPosition() : 0;
      }
  
      @Override
      public int getDropdownItemCount() {
          return mSpinner != null ? mSpinner.getCount() : 0;
      }
  
      @Override
      public void setCustomView(View view) {
          if (mCustomView != null && (mDisplayOpts & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
              mToolbar.removeView(mCustomView);
          }
          mCustomView = view;
          if (view != null && (mDisplayOpts & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
              mToolbar.addView(mCustomView);
          }
      }
  
      @Override
      public View getCustomView() {
          return mCustomView;
      }
  
      @Override
      public void animateToVisibility(int visibility) {
          ViewPropertyAnimatorCompat anim = setupAnimatorToVisibility(visibility,
                  DEFAULT_FADE_DURATION_MS);
          if (anim != null) {
              anim.start();
          }
      }
  
      @Override
      public ViewPropertyAnimatorCompat setupAnimatorToVisibility(final int visibility,
                                                                  final long duration) {
          return ViewCompat.animate(mToolbar)
                  .alpha(visibility == View.VISIBLE ? 1f : 0f)
                  .setDuration(duration)
                  .setListener(new ViewPropertyAnimatorListenerAdapter() {
                      private boolean mCanceled = false;
  
                      @Override
                      public void onAnimationStart(View view) {
                          mToolbar.setVisibility(View.VISIBLE);
                      }
  
                      @Override
                      public void onAnimationEnd(View view) {
                          if (!mCanceled) {
                              mToolbar.setVisibility(visibility);
                          }
                      }
  
                      @Override
                      public void onAnimationCancel(View view) {
                          mCanceled = true;
                      }
                  });
      }
  
      @Override
      public void setNavigationIcon(Drawable icon) {
          mNavIcon = icon;
          updateNavigationIcon();
      }
  
      @Override
      public void setNavigationIcon(int resId) {
          setNavigationIcon(resId != 0
                  ? AppCompatDrawableManager.get().getDrawable(getContext(), resId) : null);
      }
  
      @Override
      public void setNavigationContentDescription(CharSequence description) {
          mHomeDescription = description;
          updateHomeAccessibility();
      }
  
      @Override
      public void setNavigationContentDescription(int resId) {
          setNavigationContentDescription(resId == 0 ? null : getContext().getString(resId));
      }
  
      private void updateHomeAccessibility() {
          if ((mDisplayOpts & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
              if (TextUtils.isEmpty(mHomeDescription)) {
                  mToolbar.setNavigationContentDescription(mDefaultNavigationContentDescription);
              } else {
                  mToolbar.setNavigationContentDescription(mHomeDescription);
              }
          }
      }
  
      private void updateNavigationIcon() {
          if ((mDisplayOpts & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
              mToolbar.setNavigationIcon(mNavIcon != null ? mNavIcon : mDefaultNavigationIcon);
          }
      }
  
      @Override
      public void saveHierarchyState(SparseArray<Parcelable> toolbarStates) {
          mToolbar.saveHierarchyState(toolbarStates);
      }
  
      @Override
      public void restoreHierarchyState(SparseArray<Parcelable> toolbarStates) {
          mToolbar.restoreHierarchyState(toolbarStates);
      }
  
      @Override
      public void setBackgroundDrawable(Drawable d) {
          //noinspection deprecation
          mToolbar.setBackgroundDrawable(d);
      }
  
      @Override
      public int getHeight() {
          return mToolbar.getHeight();
      }
  
      @Override
      public void setVisibility(int visible) {
          mToolbar.setVisibility(visible);
      }
  
      @Override
      public int getVisibility() {
          return mToolbar.getVisibility();
      }
  
      @Override
      public void setMenuCallbacks(MenuPresenter.Callback actionMenuPresenterCallback,
                                   MenuBuilder.Callback menuBuilderCallback) {
          mToolbar.setMenuCallbacks(actionMenuPresenterCallback, menuBuilderCallback);
      }
  
      @Override
      public Menu getMenu() {
          return mToolbar.getMenu();
      }
  
  }