<commit_before>package net.simonvt.menudrawer;

import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Interpolator;

import net.simonvt.menudrawer.compat.ActionBarHelper;

public abstract class MenuDrawer extends ViewGroup {

	/**
	 * Callback interface for changing state of the drawer.
	 */
	public interface OnDrawerStateChangeListener {

		/**
		 * Called when the drawer state changes.
		 *
		 * @param oldState The old drawer state.
		 * @param newState The new drawer state.
		 */
		void onDrawerStateChange(int oldState, int newState);

		/**
		 * Called when the drawer slides.
		 *
		 * @param openRatio    Ratio for how open the menu is.
		 * @param offsetPixels Current offset of the menu in pixels.
		 */
		void onDrawerSlide(float openRatio, int offsetPixels);
	}

	/**
	 * Callback that is invoked when the drawer is in the process of deciding whether it should intercept the touch
	 * event. This lets the listener decide if the pointer is on a view that would disallow dragging of the drawer.
	 * This is only called when the touch mode is {@link #TOUCH_MODE_FULLSCREEN}.
	 */
	public interface OnInterceptMoveEventListener {

		/**
		 * Called for each child the pointer i on when the drawer is deciding whether to intercept the touch event.
		 *
		 * @param v     View to test for draggability
		 * @param delta Delta drag in pixels
		 * @param x     X coordinate of the active touch point
		 * @param y     Y coordinate of the active touch point
		 * @return true if view is draggable by delta dx.
		 */
		boolean isViewDraggable(View v, int delta, int x, int y);
	}

	public enum Type {
		/**
		 * Positions the drawer behind the content.
		 */
		BEHIND,

		/**
		 * A static drawer that can not be dragged.
		 */
		STATIC,

		/**
		 * Positions the drawer on top of the content.
		 */
		OVERLAY,

		/**
		 * Always offsets
		 */
		OFFSET,
	}

	/**
	 * Tag used when logging.
	 */
	private static final String TAG = "MenuDrawer";

	/**
	 * Indicates whether debug code should be enabled.
	 */
	private static final boolean DEBUG = false;

	/**
	 * The time between each frame when animating the drawer.
	 */
	protected static final int ANIMATION_DELAY = 1000 / 60;

	/**
	 * The default touch bezel size of the drawer in dp.
	 */
	private static final int DEFAULT_DRAG_BEZEL_DP = 24;

	/**
	 * The default drop shadow size in dp.
	 */
	private static final int DEFAULT_DROP_SHADOW_DP = 6;

	/**
	 * Drag mode for sliding only the content view.
	 */
	public static final int MENU_DRAG_CONTENT = 0;

	/**
	 * Drag mode for sliding the entire window.
	 */
	public static final int MENU_DRAG_WINDOW = 1;

	/**
	 * Disallow opening the drawer by dragging the screen.
	 */
	public static final int TOUCH_MODE_NONE = 0;

	/**
	 * Allow opening drawer only by dragging on the edge of the screen.
	 */
	public static final int TOUCH_MODE_BEZEL = 1;

	/**
	 * Allow opening drawer by dragging anywhere on the screen.
	 */
	public static final int TOUCH_MODE_FULLSCREEN = 2;

	/**
	 * Indicates that the drawer is currently closed.
	 */
	public static final int STATE_CLOSED = 0;

	/**
	 * Indicates that the drawer is currently closing.
	 */
	public static final int STATE_CLOSING = 1;

	/**
	 * Indicates that the drawer is currently being dragged by the user.
	 */
	public static final int STATE_DRAGGING = 2;

	/**
	 * Indicates that the drawer is currently opening.
	 */
	public static final int STATE_OPENING = 4;

	/**
	 * Indicates that the drawer is currently open.
	 */
	public static final int STATE_OPEN = 8;

	/**
	 * Indicates whether to use {@link View#setTranslationX(float)} when positioning views.
	 */
	static final boolean USE_TRANSLATIONS = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;

	/**
	 * Time to animate the indicator to the new active view.
	 */
	static final int INDICATOR_ANIM_DURATION = 800;

	/**
	 * The maximum animation duration.
	 */
	private static final int DEFAULT_ANIMATION_DURATION = 600;

	/**
	 * Interpolator used when animating the drawer open/closed.
	 */
	protected static final Interpolator SMOOTH_INTERPOLATOR = new SmoothInterpolator();

	/**
	 * Interpolator used for stretching/retracting the active indicator.
	 */
	protected static final Interpolator INDICATOR_INTERPOLATOR = new AccelerateInterpolator();

	/**
	 * Drawable used as menu overlay.
	 */
	protected Drawable mMenuOverlay;

	/**
	 * Defines whether the drop shadow is enabled.
	 */
	protected boolean mDropShadowEnabled;

	/**
	 * The color of the drop shadow.
	 */
	protected int mDropShadowColor;

	/**
	 * Drawable used as content drop shadow onto the menu.
	 */
	protected Drawable mDropShadowDrawable;

	private boolean mCustomDropShadow;

	/**
	 * The size of the content drop shadow.
	 */
	protected int mDropShadowSize;

	/**
	 * Bitmap used to indicate the active view.
	 */
	protected Bitmap mActiveIndicator;

	/**
	 * The currently active view.
	 */
	protected View mActiveView;

	/**
	 * Position of the active view. This is compared to View#getTag(R.id.mdActiveViewPosition) when drawing the
	 * indicator.
	 */
	protected int mActivePosition;

	/**
	 * Whether the indicator should be animated between positions.
	 */
	private boolean mAllowIndicatorAnimation;

	/**
	 * Used when reading the position of the active view.
	 */
	protected final Rect mActiveRect = new Rect();

	/**
	 * Temporary {@link Rect} used for deciding whether the view should be invalidated so the indicator can be redrawn.
	 */
	private final Rect mTempRect = new Rect();

	/**
	 * The custom menu view set by the user.
	 */
	private View mMenuView;

	/**
	 * The parent of the menu view.
	 */
	protected BuildLayerFrameLayout mMenuContainer;

	/**
	 * The parent of the content view.
	 */
	protected BuildLayerFrameLayout mContentContainer;

	/**
	 * The size of the menu (width or height depending on the gravity).
	 */
	protected int mMenuSize;

	/**
	 * Indicates whether the menu is currently visible.
	 */
	protected boolean mMenuVisible;

	/**
	 * The drag mode of the drawer. Can be either {@link #MENU_DRAG_CONTENT} or {@link #MENU_DRAG_WINDOW}.
	 */
	private int mDragMode = MENU_DRAG_CONTENT;

	/**
	 * The current drawer state.
	 *
	 * @see #STATE_CLOSED
	 * @see #STATE_CLOSING
	 * @see #STATE_DRAGGING
	 * @see #STATE_OPENING
	 * @see #STATE_OPEN
	 */
	protected int mDrawerState = STATE_CLOSED;

	/**
	 * The touch bezel size of the drawer in px.
	 */
	protected int mTouchBezelSize;

	/**
	 * The touch area size of the drawer in px.
	 */
	protected int mTouchSize;

	/**
	 * Listener used to dispatch state change events.
	 */
	private OnDrawerStateChangeListener mOnDrawerStateChangeListener;

	/**
	 * Touch mode for the Drawer.
	 * Possible values are {@link #TOUCH_MODE_NONE}, {@link #TOUCH_MODE_BEZEL} or {@link #TOUCH_MODE_FULLSCREEN}
	 * Default: {@link #TOUCH_MODE_BEZEL}
	 */
	protected int mTouchMode = TOUCH_MODE_BEZEL;

	/**
	 * Indicates whether to use {@link View#LAYER_TYPE_HARDWARE} when animating the drawer.
	 */
	protected boolean mHardwareLayersEnabled = true;

	/**
	 * The Activity the drawer is attached to.
	 */
	private Activity mActivity;

	/**
	 * Scroller used when animating the indicator to a new position.
	 */
	private FloatScroller mIndicatorScroller;

	/**
	 * Runnable used when animating the indicator to a new position.
	 */
	private Runnable mIndicatorRunnable = new Runnable() {
		@Override
		public void run() {
			animateIndicatorInvalidate();
		}
	};

	/**
	 * The start position of the indicator when animating it to a new position.
	 */
	protected int mIndicatorStartPos;

	/**
	 * [0..1] value indicating the current progress of the animation.
	 */
	protected float mIndicatorOffset;

	/**
	 * Whether the indicator is currently animating.
	 */
	protected boolean mIndicatorAnimating;

	/**
	 * Bundle used to hold the drawers state.
	 */
	protected Bundle mState;

	/**
	 * The maximum duration of open/close animations.
	 */
	protected int mMaxAnimationDuration = DEFAULT_ANIMATION_DURATION;

	/**
	 * Callback that lets the listener override intercepting of touch events.
	 */
	protected OnInterceptMoveEventListener mOnInterceptMoveEventListener;

	protected SlideDrawable mSlideDrawable;

	protected Drawable mThemeUpIndicator;

	protected boolean mDrawerIndicatorEnabled;

	private ActionBarHelper mActionBarHelper;

	private int mCurrentUpContentDesc;

	private int mDrawerOpenContentDesc;

	private int mDrawerClosedContentDesc;

	/**
	 * The position of the drawer.
	 */
	private Position mPosition;

	private Position mResolvedPosition;

	private final Rect mIndicatorClipRect = new Rect();

	protected boolean mIsStatic;

	protected final Rect mDropShadowRect = new Rect();

	/**
	 * Current offset.
	 */
	protected float mOffsetPixels;

	/**
	 * Whether an overlay should be drawn as the drawer is opened and closed.
	 */
	protected boolean mDrawOverlay;

	/**
	 * Attaches the MenuDrawer to the Activity.
	 *
	 * @param activity The activity that the MenuDrawer will be attached to.
	 * @return The created MenuDrawer instance.
	 */
	public static MenuDrawer attach(Activity activity) {
		return attach(activity, Type.BEHIND);
	}

	/**
	 * Attaches the MenuDrawer to the Activity.
	 *
	 * @param activity The activity the menu drawer will be attached to.
	 * @param type     The {@link Type} of the drawer.
	 * @return The created MenuDrawer instance.
	 */
	public static MenuDrawer attach(Activity activity, Type type) {
		return attach(activity, type, Position.START);
	}

	/**
	 * Attaches the MenuDrawer to the Activity.
	 *
	 * @param activity The activity the menu drawer will be attached to.
	 * @param position Where to position the menu.
	 * @return The created MenuDrawer instance.
	 */
	public static MenuDrawer attach(Activity activity, Position position) {
		return attach(activity, Type.BEHIND, position);
	}

	/**
	 * Attaches the MenuDrawer to the Activity.
	 *
	 * @param activity The activity the menu drawer will be attached to.
	 * @param type     The {@link Type} of the drawer.
	 * @param position Where to position the menu.
	 * @return The created MenuDrawer instance.
	 */
	public static MenuDrawer attach(Activity activity, Type type, Position position) {
		return attach(activity, type, position, MENU_DRAG_CONTENT);
	}

	/**
	 * Attaches the MenuDrawer to the Activity.
	 *
	 * @param activity The activity the menu drawer will be attached to.
	 * @param type     The {@link Type} of the drawer.
	 * @param position Where to position the menu.
	 * @param dragMode The drag mode of the drawer. Can be either {@link MenuDrawer#MENU_DRAG_CONTENT}
	 *                 or {@link MenuDrawer#MENU_DRAG_WINDOW}.
	 * @return The created MenuDrawer instance.
	 */
	public static MenuDrawer attach(Activity activity, Type type, Position position, int dragMode) {
		MenuDrawer menuDrawer = createMenuDrawer(activity, dragMode, position, type);
		menuDrawer.setId(R.id.md__drawer);

		switch (dragMode) {
			case MenuDrawer.MENU_DRAG_CONTENT:
				attachToContent(activity, menuDrawer);
				break;

			case MenuDrawer.MENU_DRAG_WINDOW:
				attachToDecor(activity, menuDrawer);
				break;

			default:
				throw new RuntimeException("Unknown menu mode: " + dragMode);
		}

		return menuDrawer;
	}

	/**
	 * Constructs the appropriate MenuDrawer based on the position.
	 */
	private static MenuDrawer createMenuDrawer(Activity activity, int dragMode, Position position, Type type) {
		MenuDrawer drawer;

		if (type == Type.STATIC) {
			drawer = new StaticDrawer(activity);

		} else if (type == Type.OVERLAY) {
			drawer = new OverlayDrawer(activity, dragMode);
			if (position == Position.LEFT || position == Position.START) {
				drawer.setupUpIndicator(activity);
			}
		} else if (type == Type.OFFSET) {
			drawer = new OffsetSlidingDrawer(activity, dragMode);
			if (position == Position.LEFT || position == Position.START) {
				drawer.setupUpIndicator(activity);
			}
		} else {
			drawer = new SlidingDrawer(activity, dragMode);
			if (position == Position.LEFT || position == Position.START) {
				drawer.setupUpIndicator(activity);
			}
		}

		drawer.mDragMode = dragMode;
		drawer.setPosition(position);

		return drawer;
	}

	/**
	 * Attaches the menu drawer to the content view.
	 */
	private static void attachToContent(Activity activity, MenuDrawer menuDrawer) {
		/**
		 * Do not call mActivity#setContentView.
		 * E.g. if using with a ListActivity, Activity#setContentView is overridden and dispatched to
		 * MenuDrawer#setContentView, which then again would call Activity#setContentView.
		 */
		ViewGroup content = (ViewGroup) activity.findViewById(android.R.id.content);
		content.removeAllViews();
		content.addView(menuDrawer, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
	}

	/**
	 * Attaches the menu drawer to the window.
	 */
	private static void attachToDecor(Activity activity, MenuDrawer menuDrawer) {
		ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
		ViewGroup decorChild = (ViewGroup) decorView.getChildAt(0);

		decorView.removeAllViews();
		decorView.addView(menuDrawer, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);

		menuDrawer.mContentContainer.addView(decorChild, decorChild.getLayoutParams());
	}

	MenuDrawer(Activity activity, int dragMode) {
		this(activity);

		mActivity = activity;
		mDragMode = dragMode;
	}

	public MenuDrawer(Context context) {
		this(context, null);
	}

	public MenuDrawer(Context context, AttributeSet attrs) {<commit_msg>IAT-13 #comment menu drawer attached below toolbars + toolbars aligned<commit_after>package net.simonvt.menudrawer;

import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Interpolator;

import net.simonvt.menudrawer.compat.ActionBarHelper;

public abstract class MenuDrawer extends ViewGroup {

	/**
	 * Callback interface for changing state of the drawer.
	 */
	public interface OnDrawerStateChangeListener {

		/**
		 * Called when the drawer state changes.
		 *
		 * @param oldState The old drawer state.
		 * @param newState The new drawer state.
		 */
		void onDrawerStateChange(int oldState, int newState);

		/**
		 * Called when the drawer slides.
		 *
		 * @param openRatio    Ratio for how open the menu is.
		 * @param offsetPixels Current offset of the menu in pixels.
		 */
		void onDrawerSlide(float openRatio, int offsetPixels);
	}

	/**
	 * Callback that is invoked when the drawer is in the process of deciding whether it should intercept the touch
	 * event. This lets the listener decide if the pointer is on a view that would disallow dragging of the drawer.
	 * This is only called when the touch mode is {@link #TOUCH_MODE_FULLSCREEN}.
	 */
	public interface OnInterceptMoveEventListener {

		/**
		 * Called for each child the pointer i on when the drawer is deciding whether to intercept the touch event.
		 *
		 * @param v     View to test for draggability
		 * @param delta Delta drag in pixels
		 * @param x     X coordinate of the active touch point
		 * @param y     Y coordinate of the active touch point
		 * @return true if view is draggable by delta dx.
		 */
		boolean isViewDraggable(View v, int delta, int x, int y);
	}

	public enum Type {
		/**
		 * Positions the drawer behind the content.
		 */
		BEHIND,

		/**
		 * A static drawer that can not be dragged.
		 */
		STATIC,

		/**
		 * Positions the drawer on top of the content.
		 */
		OVERLAY,

		/**
		 * Always offsets
		 */
		OFFSET,
	}

	/**
	 * Tag used when logging.
	 */
	private static final String TAG = "MenuDrawer";

	/**
	 * Indicates whether debug code should be enabled.
	 */
	private static final boolean DEBUG = false;

	/**
	 * The time between each frame when animating the drawer.
	 */
	protected static final int ANIMATION_DELAY = 1000 / 60;

	/**
	 * The default touch bezel size of the drawer in dp.
	 */
	private static final int DEFAULT_DRAG_BEZEL_DP = 24;

	/**
	 * The default drop shadow size in dp.
	 */
	private static final int DEFAULT_DROP_SHADOW_DP = 6;

	/**
	 * Drag mode for sliding only the content view.
	 */
	public static final int MENU_DRAG_CONTENT = 0;

	/**
	 * Drag mode for sliding the entire window.
	 */
	public static final int MENU_DRAG_WINDOW = 1;

	/**
	 * Disallow opening the drawer by dragging the screen.
	 */
	public static final int TOUCH_MODE_NONE = 0;

	/**
	 * Allow opening drawer only by dragging on the edge of the screen.
	 */
	public static final int TOUCH_MODE_BEZEL = 1;

	/**
	 * Allow opening drawer by dragging anywhere on the screen.
	 */
	public static final int TOUCH_MODE_FULLSCREEN = 2;

	/**
	 * Indicates that the drawer is currently closed.
	 */
	public static final int STATE_CLOSED = 0;

	/**
	 * Indicates that the drawer is currently closing.
	 */
	public static final int STATE_CLOSING = 1;

	/**
	 * Indicates that the drawer is currently being dragged by the user.
	 */
	public static final int STATE_DRAGGING = 2;

	/**
	 * Indicates that the drawer is currently opening.
	 */
	public static final int STATE_OPENING = 4;

	/**
	 * Indicates that the drawer is currently open.
	 */
	public static final int STATE_OPEN = 8;

	/**
	 * Indicates whether to use {@link View#setTranslationX(float)} when positioning views.
	 */
	static final boolean USE_TRANSLATIONS = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;

	/**
	 * Time to animate the indicator to the new active view.
	 */
	static final int INDICATOR_ANIM_DURATION = 800;

	/**
	 * The maximum animation duration.
	 */
	private static final int DEFAULT_ANIMATION_DURATION = 600;

	/**
	 * Interpolator used when animating the drawer open/closed.
	 */
	protected static final Interpolator SMOOTH_INTERPOLATOR = new SmoothInterpolator();

	/**
	 * Interpolator used for stretching/retracting the active indicator.
	 */
	protected static final Interpolator INDICATOR_INTERPOLATOR = new AccelerateInterpolator();

	/**
	 * Drawable used as menu overlay.
	 */
	protected Drawable mMenuOverlay;

	/**
	 * Defines whether the drop shadow is enabled.
	 */
	protected boolean mDropShadowEnabled;

	/**
	 * The color of the drop shadow.
	 */
	protected int mDropShadowColor;

	/**
	 * Drawable used as content drop shadow onto the menu.
	 */
	protected Drawable mDropShadowDrawable;

	private boolean mCustomDropShadow;

	/**
	 * The size of the content drop shadow.
	 */
	protected int mDropShadowSize;

	/**
	 * Bitmap used to indicate the active view.
	 */
	protected Bitmap mActiveIndicator;

	/**
	 * The currently active view.
	 */
	protected View mActiveView;

	/**
	 * Position of the active view. This is compared to View#getTag(R.id.mdActiveViewPosition) when drawing the
	 * indicator.
	 */
	protected int mActivePosition;

	/**
	 * Whether the indicator should be animated between positions.
	 */
	private boolean mAllowIndicatorAnimation;

	/**
	 * Used when reading the position of the active view.
	 */
	protected final Rect mActiveRect = new Rect();

	/**
	 * Temporary {@link Rect} used for deciding whether the view should be invalidated so the indicator can be redrawn.
	 */
	private final Rect mTempRect = new Rect();

	/**
	 * The custom menu view set by the user.
	 */
	private View mMenuView;

	/**
	 * The parent of the menu view.
	 */
	protected BuildLayerFrameLayout mMenuContainer;

	/**
	 * The parent of the content view.
	 */
	protected BuildLayerFrameLayout mContentContainer;

	/**
	 * The size of the menu (width or height depending on the gravity).
	 */
	protected int mMenuSize;

	/**
	 * Indicates whether the menu is currently visible.
	 */
	protected boolean mMenuVisible;

	/**
	 * The drag mode of the drawer. Can be either {@link #MENU_DRAG_CONTENT} or {@link #MENU_DRAG_WINDOW}.
	 */
	private int mDragMode = MENU_DRAG_CONTENT;

	/**
	 * The current drawer state.
	 *
	 * @see #STATE_CLOSED
	 * @see #STATE_CLOSING
	 * @see #STATE_DRAGGING
	 * @see #STATE_OPENING
	 * @see #STATE_OPEN
	 */
	protected int mDrawerState = STATE_CLOSED;

	/**
	 * The touch bezel size of the drawer in px.
	 */
	protected int mTouchBezelSize;

	/**
	 * The touch area size of the drawer in px.
	 */
	protected int mTouchSize;

	/**
	 * Listener used to dispatch state change events.
	 */
	private OnDrawerStateChangeListener mOnDrawerStateChangeListener;

	/**
	 * Touch mode for the Drawer.
	 * Possible values are {@link #TOUCH_MODE_NONE}, {@link #TOUCH_MODE_BEZEL} or {@link #TOUCH_MODE_FULLSCREEN}
	 * Default: {@link #TOUCH_MODE_BEZEL}
	 */
	protected int mTouchMode = TOUCH_MODE_BEZEL;

	/**
	 * Indicates whether to use {@link View#LAYER_TYPE_HARDWARE} when animating the drawer.
	 */
	protected boolean mHardwareLayersEnabled = true;

	/**
	 * The Activity the drawer is attached to.
	 */
	private Activity mActivity;

	/**
	 * Scroller used when animating the indicator to a new position.
	 */
	private FloatScroller mIndicatorScroller;

	/**
	 * Runnable used when animating the indicator to a new position.
	 */
	private Runnable mIndicatorRunnable = new Runnable() {
		@Override
		public void run() {
			animateIndicatorInvalidate();
		}
	};

	/**
	 * The start position of the indicator when animating it to a new position.
	 */
	protected int mIndicatorStartPos;

	/**
	 * [0..1] value indicating the current progress of the animation.
	 */
	protected float mIndicatorOffset;

	/**
	 * Whether the indicator is currently animating.
	 */
	protected boolean mIndicatorAnimating;

	/**
	 * Bundle used to hold the drawers state.
	 */
	protected Bundle mState;

	/**
	 * The maximum duration of open/close animations.
	 */
	protected int mMaxAnimationDuration = DEFAULT_ANIMATION_DURATION;

	/**
	 * Callback that lets the listener override intercepting of touch events.
	 */
	protected OnInterceptMoveEventListener mOnInterceptMoveEventListener;

	protected SlideDrawable mSlideDrawable;

	protected Drawable mThemeUpIndicator;

	protected boolean mDrawerIndicatorEnabled;

	private ActionBarHelper mActionBarHelper;

	private int mCurrentUpContentDesc;

	private int mDrawerOpenContentDesc;

	private int mDrawerClosedContentDesc;

	/**
	 * The position of the drawer.
	 */
	private Position mPosition;

	private Position mResolvedPosition;

	private final Rect mIndicatorClipRect = new Rect();

	protected boolean mIsStatic;

	protected final Rect mDropShadowRect = new Rect();

	/**
	 * Current offset.
	 */
	protected float mOffsetPixels;

	/**
	 * Whether an overlay should be drawn as the drawer is opened and closed.
	 */
	protected boolean mDrawOverlay;

	/**
	 * Attaches the MenuDrawer to the Activity.
	 *
	 * @param activity The activity that the MenuDrawer will be attached to.
	 * @return The created MenuDrawer instance.
	 */
	public static MenuDrawer attach(Activity activity) {
		return attach(activity, Type.BEHIND);
	}

	/**
	 * Attaches the MenuDrawer to the Activity.
	 *
	 * @param activity The activity the menu drawer will be attached to.
	 * @param type     The {@link Type} of the drawer.
	 * @return The created MenuDrawer instance.
	 */
	public static MenuDrawer attach(Activity activity, Type type) {
		return attach(activity, type, Position.START);
	}

	/**
	 * Attaches the MenuDrawer to the Activity.
	 *
	 * @param activity The activity the menu drawer will be attached to.
	 * @param position Where to position the menu.
	 * @return The created MenuDrawer instance.
	 */
	public static MenuDrawer attach(Activity activity, Position position) {
		return attach(activity, Type.BEHIND, position);
	}

	/**
	 * Attaches the MenuDrawer to the Activity.
	 *
	 * @param activity The activity the menu drawer will be attached to.
	 * @param type     The {@link Type} of the drawer.
	 * @param position Where to position the menu.
	 * @return The created MenuDrawer instance.
	 */
	public static MenuDrawer attach(Activity activity, Type type, Position position) {
		return attach(activity, type, position, MENU_DRAG_CONTENT);
	}

	/**
	 * Attaches the MenuDrawer to the Activity.
	 *
	 * @param activity The activity the menu drawer will be attached to.
	 * @param type     The {@link Type} of the drawer.
	 * @param position Where to position the menu.
	 * @param dragMode The drag mode of the drawer. Can be either {@link MenuDrawer#MENU_DRAG_CONTENT}
	 *                 or {@link MenuDrawer#MENU_DRAG_WINDOW}.
	 * @return The created MenuDrawer instance.
	 */
	public static MenuDrawer attach(Activity activity, Type type, Position position, int dragMode) {
		return attach(activity, type, position, dragMode, -1);
	}

	public static MenuDrawer attach(Activity activity, Type type, Position position, int dragMode, int attachToView) {
		MenuDrawer menuDrawer = createMenuDrawer(activity, dragMode, position, type);
		menuDrawer.setId(R.id.md__drawer);

		switch (dragMode) {
			case MenuDrawer.MENU_DRAG_CONTENT:
				attachToView(activity, menuDrawer, attachToView);
				break;

			case MenuDrawer.MENU_DRAG_WINDOW:
				attachToDecor(activity, menuDrawer);
				break;

			default:
				throw new RuntimeException("Unknown menu mode: " + dragMode);
		}

		return menuDrawer;
	}

	/**
	 * Constructs the appropriate MenuDrawer based on the position.
	 */
	private static MenuDrawer createMenuDrawer(Activity activity, int dragMode, Position position, Type type) {
		MenuDrawer drawer;

		if (type == Type.STATIC) {
			drawer = new StaticDrawer(activity);

		} else if (type == Type.OVERLAY) {
			drawer = new OverlayDrawer(activity, dragMode);
			if (position == Position.LEFT || position == Position.START) {
				drawer.setupUpIndicator(activity);
			}
		} else if (type == Type.OFFSET) {
			drawer = new OffsetSlidingDrawer(activity, dragMode);
			if (position == Position.LEFT || position == Position.START) {
				drawer.setupUpIndicator(activity);
			}
		} else {
			drawer = new SlidingDrawer(activity, dragMode);
			if (position == Position.LEFT || position == Position.START) {
				drawer.setupUpIndicator(activity);
			}
		}

		drawer.mDragMode = dragMode;
		drawer.setPosition(position);

		return drawer;
	}

	/**
	 * Attaches the menu drawer to the content view.
	 */
	private static void attachToContent(Activity activity, MenuDrawer menuDrawer) {
		attachToView(activity, menuDrawer, android.R.id.content);
	}

	private static void attachToView(Activity activity, MenuDrawer menuDrawer, int viewResId) {
		if (viewResId <= 0)
			viewResId = android.R.id.content;
		/**
		 * Do not call mActivity#setContentView.
		 * E.g. if using with a ListActivity, Activity#setContentView is overridden and dispatched to
		 * MenuDrawer#setContentView, which then again would call Activity#setContentView.
		 */
		ViewGroup content = (ViewGroup) activity.findViewById(viewResId);
		content.removeAllViews();
		content.addView(menuDrawer, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
	}

	/**
	 * Attaches the menu drawer to the window.
	 */
	private static void attachToDecor(Activity activity, MenuDrawer menuDrawer) {
		ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
		ViewGroup decorChild = (ViewGroup) decorView.getChildAt(0);

		decorView.removeAllViews();
		decorView.addView(menuDrawer, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);

		menuDrawer.mContentContainer.addView(decorChild, decorChild.getLayoutParams());
	}

	MenuDrawer(Activity activity, int dragMode) {
		this(activity);

		mActivity = activity;
		mDragMode = dragMode;
	}

	public MenuDrawer(Context context) {
		this(context, null);
	}

	public MenuDrawer(Context context, AttributeSet attrs) {
{'fraction_non_alphanumeric': 0.08703819661865998, 'fraction_numerical': 0.002087246921310791, 'mean_word_length': 3.6418537057968674, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3627697', 'n_tokens_mistral': 9159, 'n_tokens_neox': 8177, 'n_words': 2929}