text:
package android.support.design.widget;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.os.ParcelableCompat;
import android.support.v4.os.ParcelableCompatCreatorCallbacks;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.WindowInsetsCompat;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.widget.LinearLayout;

import com.yc.androidsupportlibrary.R;

/**
 * AppBarLayout is a vertical {@link LinearLayout} which implements many of the features of
 * material designs app bar concept, namely scrolling gestures.
 *

 * Children should provide their desired scrolling behavior through
 * {@link LayoutParams#setScrollFlags(int)} and the associated layout xml attribute:
 * {@code app:layout_scrollFlags}.
 *
 *

 * This view depends heavily on being used as a direct child within a {@link CoordinatorLayout}.
 * If you use AppBarLayout within a different {@link ViewGroup}, most of it's functionality will
 * not work.
 *

 * AppBarLayout also requires a separate scrolling sibling in order to know when to scroll.
 * The binding is done through the {@link ScrollingViewBehavior} behavior class, meaning that you
 * should set your scrolling view's behavior to be an instance of {@link ScrollingViewBehavior}.
 * A string resource containing the full class name is available.
 *
 *

 * <android.support.design.widget.CoordinatorLayout
 *         xmlns:android="http://schemas.android.com/apk/res/android"
 *         xmlns:app="http://schemas.android.com/apk/res-auto"
 *         android:layout_width="match_parent"
 *         android:layout_height="match_parent">
 *
 *     <android.support.v4.widget.NestedScrollView
 *             android:layout_width="match_parent"
 *             android:layout_height="match_parent"
 *             app:layout_behavior="@string/appbar_scrolling_view_behavior">
 *
 *         <!-- Your scrolling content -->
 *
 *     </android.support.v4.widget.NestedScrollView>
 *
 *     <android.support.design.widget.AppBarLayout
 *             android:layout_height="wrap_content"
 *             android:layout_width="match_parent">
 *
 *         <android.support.v7.widget.Toolbar
 *                 ...
 *                 app:layout_scrollFlags="scroll|enterAlways"/>
 *
 *         <android.support.design.widget.TabLayout
 *                 ...
 *                 app:layout_scrollFlags="scroll|enterAlways"/>
 *
 *     </android.support.design.widget.AppBarLayout>
 *
 * </android.support.design.widget.CoordinatorLayout>
 *

 *
 * @see
 *     http://www.google.com/design/spec/layout/structure.html#structure-app-bar
 */
@CoordinatorLayout.DefaultBehavior(AppBarLayout.Behavior.class)
public class AppBarLayout extends LinearLayout {

    private static final int PENDING_ACTION_NONE = 0x0;
    private static final int PENDING_ACTION_EXPANDED = 0x1;
    private static final int PENDING_ACTION_COLLAPSED = 0x2;
    private static final int PENDING_ACTION_ANIMATE_ENABLED = 0x4;

    /**
     * Interface definition for a callback to be invoked when an {@link AppBarLayout}'s vertical
     * offset changes.
     */
    public interface OnOffsetChangedListener {
        /**
         * Called when the {@link AppBarLayout}'s layout offset has been changed. This allows
         * child views to implement custom behavior based on the offset (for instance pinning a
         * view at a certain y value).
         *
         * @param appBarLayout the {@link AppBarLayout} which offset has changed
         * @param verticalOffset the vertical offset for the parent {@link AppBarLayout}, in px
         */
        void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset);
    }

    private static final int INVALID_SCROLL_RANGE = -1;

    private int mTotalScrollRange = INVALID_SCROLL_RANGE;
    private int mDownPreScrollRange = INVALID_SCROLL_RANGE;
    private int mDownScrollRange = INVALID_SCROLL_RANGE;

    boolean mHaveChildWithInterpolator;

    private float mTargetElevation;

    private int mPendingAction = PENDING_ACTION_NONE;

    private WindowInsetsCompat mLastInsets;

    private final List<OnOffsetChangedListener> mListeners;

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

    public AppBarLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        setOrientation(VERTICAL);

        ThemeUtils.checkAppCompatTheme(context);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AppBarLayout,
                0, R.style.Widget_Design_AppBarLayout);
        mTargetElevation = a.getDimensionPixelSize(R.styleable.AppBarLayout_elevation, 0);
        setBackgroundDrawable(a.getDrawable(R.styleable.AppBarLayout_android_background));
        if (a.hasValue(R.styleable.AppBarLayout_expanded)) {
            setExpanded(a.getBoolean(R.styleable.AppBarLayout_expanded, false));
        }
        a.recycle();

        // Use the bounds view outline provider so that we cast a shadow, even without a background
        ViewUtils.setBoundsViewOutlineProvider(this);

        mListeners = new ArrayList<>();

        ViewCompat.setElevation(this, mTargetElevation);

        ViewCompat.setOnApplyWindowInsetsListener(this,
                new android.support.v4.view.OnApplyWindowInsetsListener() {
                    @Override
                    public WindowInsetsCompat onApplyWindowInsets(View v,
                            WindowInsetsCompat insets) {
                        setWindowInsets(insets);
                        return insets.consumeSystemWindowInsets();
                    }
                });
    }

    /**
     * Add a listener that will be called when the offset of this {@link AppBarLayout} changes.
     *
     * @param listener The listener that will be called when the offset changes.]
     *
     * @see #removeOnOffsetChangedListener(OnOffsetChangedListener)
     */
    public void addOnOffsetChangedListener(OnOffsetChangedListener listener) {
        if (listener != null && !mListeners.contains(listener)) {
            mListeners.add(listener);
        }
    }

    /**
     * Remove the previously added {@link OnOffsetChangedListener}.
     *
     * @param listener the listener to remove.
     */
    public void removeOnOffsetChangedListener(OnOffsetChangedListener listener) {
        if (listener != null) {
            mListeners.remove(listener);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        invalidateScrollRanges();
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        invalidateScrollRanges();

        mHaveChildWithInterpolator = false;
        for (int i = 0, z = getChildCount(); i < z; i++) {
            final View child = getChildAt(i);
            final LayoutParams childLp = (LayoutParams) child.getLayoutParams();
            final Interpolator interpolator = childLp.getScrollInterpolator();

            if (interpolator != null) {
                mHaveChildWithInterpolator = true;
                break;
            }
        }
    }

    private void invalidateScrollRanges() {
        // Invalidate the scroll ranges
        mTotalScrollRange = INVALID_SCROLL_RANGE;
        mDownPreScrollRange = INVALID_SCROLL_RANGE;
        mDownScrollRange = INVALID_SCROLL_RANGE;
    }

    @Override
    public void setOrientation(int orientation) {
        if (orientation != VERTICAL) {
            throw new IllegalArgumentException("AppBarLayout is always vertical and does"
                    + " not support horizontal orientation");
        }
        super.setOrientation(orientation);
    }

    /**
     * Sets whether this {@link AppBarLayout} is expanded or not, animating if it has already
     * been laid out.
     *
     *
As with {@link AppBarLayout}'s scrolling, this method relies on this layout being a
     * direct child of a {@link CoordinatorLayout}.

     *
     * @param expanded true if the layout should be fully expanded, false if it should
     *                 be fully collapsed
     *
     * @attr ref android.support.design.R.styleable#AppBarLayout_expanded
     */
    public void setExpanded(boolean expanded) {
        setExpanded(expanded, ViewCompat.isLaidOut(this));
    }

    /**
     * Sets whether this {@link AppBarLayout} is expanded or not.
     *
     *
As with {@link AppBarLayout}'s scrolling, this method relies on this layout being a
     * direct child of a {@link CoordinatorLayout}.

     *
     * @param expanded true if the layout should be fully expanded, false if it should
     *                 be fully collapsed
     * @param animate Whether to animate to the new state
     *
     * @attr ref android.support.design.R.styleable#AppBarLayout_expanded
     */
    public void setExpanded(boolean expanded, boolean animate) {
        mPendingAction = (expanded ? PENDING_ACTION_EXPANDED : PENDING_ACTION_COLLAPSED)
                | (animate ? PENDING_ACTION_ANIMATE_ENABLED : 0);
        requestLayout();
    }

    @Override
    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
        return p instanceof LayoutParams;
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new LayoutParams(getContext(), attrs);
    }

    @Override
    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
        if (p instanceof LinearLayout.LayoutParams) {
            return new LayoutParams((LinearLayout.LayoutParams) p);
        } else if (p instanceof MarginLayoutParams) {
            return new LayoutParams((MarginLayoutParams) p);
        }
        return new LayoutParams(p);
    }

    private boolean hasChildWithInterpolator() {
        return mHaveChildWithInterpolator;
    }

    /**
     * Returns the scroll range of all children.
     *
     * @return the scroll range in px
     */
    public final int getTotalScrollRange() {
        if (mTotalScrollRange != INVALID_SCROLL_RANGE) {
            return mTotalScrollRange;
        }

        int range = 0;
        for (int i = 0, z = getChildCount(); i < z; i++) {
            final View child = getChildAt(i);
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            final int childHeight = child.getMeasuredHeight();
            final int flags = lp.mScrollFlags;

            if ((flags & LayoutParams.SCROLL_FLAG_SCROLL) != 0) {
                // We're set to scroll so add the child's height
                range += childHeight + lp.topMargin + lp.bottomMargin;

                if ((flags & LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED) != 0) {
                    // For a collapsing scroll, we to take the collapsed height into account.
                    // We also break straight away since later views can't scroll beneath
                    // us
                    range -= ViewCompat.getMinimumHeight(child);
                    break;
                }
            } else {
                // As soon as a view doesn't have the scroll flag, we end the range calculation.
                // This is because views below can not scroll under a fixed view.
                break;
            }
        }
        return mTotalScrollRange = Math.max(0, range - getTopInset());
    }

    private boolean hasScrollableChildren() {
        return getTotalScrollRange() != 0;
    }

    /**
     * Return the scroll range when scrolling up from a nested pre-scroll.
     */
    private int getUpNestedPreScrollRange() {
        return getTotalScrollRange();
    }

    /**
     * Return the scroll range when scrolling down from a nested pre-scroll.
     */
    private int getDownNestedPreScrollRange() {
        if (mDownPreScrollRange != INVALID_SCROLL_RANGE) {
            // If we already have a valid value, return it
            return mDownPreScrollRange;
        }

        int range = 0;
        for (int i = getChildCount() - 1; i >= 0; i--) {
            final View child = getChildAt(i);
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            final int childHeight = child.getMeasuredHeight();
            final int flags = lp.mScrollFlags;

            if ((flags & LayoutParams.FLAG_QUICK_RETURN) == LayoutParams.FLAG_QUICK_RETURN) {
                // First take the margin into account
                range += lp.topMargin + lp.bottomMargin;
                // The view has the quick return flag combination...
                if ((flags & LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED) != 0) {
                    // If they're set to enter collapsed, use the minimum height
                    range += ViewCompat.getMinimumHeight(child);
                } else {
                    // Else use the full height
                    range += childHeight;
                }
            } else if (range > 0) {
                // If we've hit an non-quick return scrollable view, and we've already hit a
                // quick return view, return now
                break;
            }
        }
        return mDownPreScrollRange = range;
    }

    /**
     * Return the scroll range when scrolling down from a nested scroll.
     */
    private int getDownNestedScrollRange() {
        if (mDownScrollRange != INVALID_SCROLL_RANGE) {
            // If we already have a valid value, return it
            return mDownScrollRange;
        }

        int range = 0;
        for (int i = 0, z = getChildCount(); i < z; i++) {
            final View child = getChildAt(i);
            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
            int childHeight = child.getMeasuredHeight();
            childHeight += lp.topMargin + lp.bottomMargin;

            final int flags = lp.mScrollFlags;

            if ((flags & LayoutParams.SCROLL_FLAG_SCROLL) != 0) {
                // We're set to scroll so add the child's height
                range += childHeight;

                if ((flags & LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED) != 0) {
                    // For a collapsing exit scroll, we to take the collapsed height into account.
                    // We also break the range straight away since later views can't scroll
                    // beneath us
                    range -= ViewCompat.getMinimumHeight(child) + getTopInset();
                    break;
                }
            } else {
                // As soon as a view doesn't have the scroll flag, we end the range calculation.
                // This is because views below can not scroll under a fixed view.
                break;
            }
        }
        return mDownScrollRange = Math.max(0, range);
    }

    final int getMinimumHeightForVisibleOverlappingContent() {
        final int topInset = mLastInsets != null ? mLastInsets.getSystemWindowInsetTop() : 0;
        final int minHeight = ViewCompat.getMinimumHeight(this);
        if (minHeight != 0) {
            // If this layout has a min height, use it (doubled)
            return (minHeight * 2) + topInset;
        }

        // Otherwise, we'll use twice the min height of our last child
        final int childCount = getChildCount();
        return childCount >= 1
                ? (ViewCompat.getMinimumHeight(getChildAt(childCount - 1)) * 2) + topInset
                : 0;
    }

    /**
     * Set the elevation value to use when this {@link AppBarLayout} should be elevated
     * above content.
     *

     * This method does not do anything itself. A typical use for this method is called from within
     * an {@link OnOffsetChangedListener} when the offset has changed in such a way to require an
     * elevation change.
     *
     * @param elevation the elevation value to use.
     *
     * @see ViewCompat#setElevation(View, float)
     */
    public void setTargetElevation(float elevation) {
        mTargetElevation = elevation;
    }

    /**
     * Returns the elevation value to use when this {@link AppBarLayout} should be elevated
     * above content.
     */
    public float getTargetElevation() {
        return mTargetElevation;
    }

    private int getPendingAction() {
        return mPendingAction;
    }

    private void resetPendingAction() {
        mPendingAction = PENDING_ACTION_NONE;
    }

    private int getTopInset() {
        return mLastInsets != null ? mLastInsets.getSystemWindowInsetTop() : 0;
    }

    private void setWindowInsets(WindowInsetsCompat insets) {
        // Invalidate the total scroll range...
        mTotalScrollRange = INVALID_SCROLL_RANGE;
        mLastInsets = insets;

        // Now dispatch them to our children
        for (int i = 0, z = getChildCount(); i < z; i++) {
            final View child = getChildAt(i);
            insets = ViewCompat.dispatchApplyWindowInsets(child, insets);
            if (insets.isConsumed()) {
                break;
            }
        }
    }

    public static class LayoutParams extends LinearLayout.LayoutParams {

        /** @hide */
        @IntDef(flag=true, value={
                SCROLL_FLAG_SCROLL,
                SCROLL_FLAG_EXIT_UNTIL_COLLAPSED,
                SCROLL_FLAG_ENTER_ALWAYS,
                SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED,
                SCROLL_FLAG_SNAP
        })
        @Retention(RetentionPolicy.SOURCE)
        public @interface ScrollFlags {}

        /**
         * The view will be scroll in direct relation to scroll events. This flag needs to be
         * set for any of the other flags to take effect. If any sibling views
         * before this one do not have this flag, then this value has no effect.
         */
        public static final int SCROLL_FLAG_SCROLL = 0x1;

        /**
         * When exiting (scrolling off screen) the view will be scrolled until it is
         * 'collapsed'. The collapsed height is defined by the view's minimum height.
         *
         * @see ViewCompat#getMinimumHeight(View)
         * @see View#setMinimumHeight(int)
         */
        public static final int SCROLL_FLAG_EXIT_UNTIL_COLLAPSED = 0x2;

        /**
         * When entering (scrolling on screen) the view will scroll on any downwards
         * scroll event, regardless of whether the scrolling view is also scrolling. This
         * is commonly referred to as the 'quick return' pattern.
         */
        public static final int SCROLL_FLAG_ENTER_ALWAYS = 0x4;

        /**
         * An additional flag for 'enterAlways' which modifies the returning view to
         * only initially scroll back to it's collapsed height. Once the scrolling view has
         * reached the end of it's scroll range, the remainder of this view will be scrolled
         * into view. The collapsed height is defined by the view's minimum height.
         *
         * @see ViewCompat#getMinimumHeight(View)
         * @see View#setMinimumHeight(int)
         */
        public static final int SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED = 0x8;

        /**
         * Upon a scroll ending, if the view is only partially visible then it will be snapped
         * and scrolled to it's closest edge. For example, if the view only has it's bottom 25%
         * displayed, it will be scrolled off screen completely. Conversely, if it's bottom 75%
         * is visible then it will be scrolled fully into view.
         */
        public static final int SCROLL_FLAG_SNAP = 0x10;

        /**
         * Internal flags which allows quick checking features
         */
        static final int FLAG_QUICK_RETURN = SCROLL_FLAG_SCROLL | SCROLL_FLAG_ENTER_ALWAYS;
        static final int FLAG_SNAP = SCROLL_FLAG_SCROLL | SCROLL_FLAG_SNAP;

        int mScrollFlags = SCROLL_FLAG_SCROLL;
        Interpolator mScrollInterpolator;

        public LayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);
            TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.AppBarLayout_LayoutParams);
            mScrollFlags = a.getInt(R.styleable.AppBarLayout_LayoutParams_layout_scrollFlags, 0);
            if (a.hasValue(R.styleable.AppBarLayout_LayoutParams_layout_scrollInterpolator)) {
                int resId = a.getResourceId(
                        R.styleable.AppBarLayout_LayoutParams_layout_scrollInterpolator, 0);
                mScrollInterpolator = android.view.animation.AnimationUtils.loadInterpolator(
                        c, resId);
            }
            a.recycle();
        }

        public LayoutParams(int width, int height) {
            super(width, height);
        }

        public LayoutParams(int width, int height, float weight) {
            super(width, height, weight);
        }

        public LayoutParams(ViewGroup.LayoutParams p) {
            super(p);
        }

        public LayoutParams(MarginLayoutParams source) {
            super(source);
        }

        public LayoutParams(LinearLayout.LayoutParams source) {
            super(source);
        }

        public LayoutParams(LayoutParams source) {
            super(source);
            mScrollFlags = source.mScrollFlags;
            mScrollInterpolator = source.mScrollInterpolator;
        }

        /**
         * Set the scrolling flags.
         *
         * @param flags bitwise int of {@link #SCROLL_FLAG_SCROLL},
         *             {@link #SCROLL_FLAG_EXIT_UNTIL_COLLAPSED}, {@link #SCROLL_FLAG_ENTER_ALWAYS},
         *             {@link #SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED} and {@link #SCROLL_FLAG_SNAP }.
         *
         * @see #getScrollFlags()
         *
         * @attr ref android.support.design.R.styleable#AppBarLayout_LayoutParams_layout_scrollFlags
         */
        public void setScrollFlags(@ScrollFlags int flags) {
            mScrollFlags = flags;
        }

        /**
         * Returns the scrolling flags.
         *
         * @see #setScrollFlags(int)
         *
         * @attr ref android.support.design.R.styleable#AppBarLayout_LayoutParams_layout_scrollFlags
         */
        @ScrollFlags
        public int getScrollFlags() {
            return mScrollFlags;
        }

        /**
         * Set the interpolator to when scrolling the view associated with this
         * {@link LayoutParams}.
         *
         * @param interpolator the interpolator to use, or null to use normal 1-to-1 scrolling.
         *
         * @attr ref android.support.design.R.styleable#AppBarLayout_LayoutParams_layout_scrollInterpolator
         * @see #getScrollInterpolator()
         */
        public void setScrollInterpolator(Interpolator interpolator) {
            mScrollInterpolator = interpolator;
        }

        /**
         * Returns the {@link Interpolator} being used for scrolling the view associated with this
         * {@link LayoutParams}. Null indicates 'normal' 1-to-1 scrolling.
         *
         * @attr ref android.support.design.R.styleable#AppBarLayout_LayoutParams_layout_scrollInterpolator
         * @see #setScrollInterpolator(Interpolator)
         */
        public Interpolator getScrollInterpolator() {
            return mScrollInterpolator;
        }
    }

    /**
     * The default {@link Behavior} for {@link AppBarLayout}. Implements the necessary nested
     * scroll handling with offsetting.
     */
    public static class Behavior extends HeaderBehavior<AppBarLayout> {
        private static final int ANIMATE_OFFSET_DIPS_PER_SECOND = 300;
        private static final int INVALID_POSITION = -1;

        /**
         * Callback to allow control over any {@link AppBarLayout} dragging.
         */
        public static abstract class DragCallback {
            /**
             * Allows control over whether the given {@link AppBarLayout} can be dragged or not.
             *
             *
Dragging is defined as a direct touch on the AppBarLayout with movement. This
             * call does not affect any nested scrolling.

             *
             * @return true if we are in a position to scroll the AppBarLayout via a drag, false
             *         if not.
             */
            public abstract boolean canDrag(@NonNull AppBarLayout appBarLayout);
        }

        private int mOffsetDelta;

        private boolean mSkipNestedPreScroll;
        private boolean mWasFlung;

        private ValueAnimatorCompat mAnimator;

        private int mOffsetToChildIndexOnLayout = INVALID_POSITION;
        private boolean mOffsetToChildIndexOnLayoutIsMinHeight;
        private float mOffsetToChildIndexOnLayoutPerc;

        private WeakReference<View> mLastNestedScrollingChildRef;
        private DragCallback mOnDragCallback;

        public Behavior() {}

        public Behavior(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        @Override
        public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child,
                View directTargetChild, View target, int nestedScrollAxes) {
            // Return true if we're nested scrolling vertically, and we have scrollable children
            // and the scrolling view is big enough to scroll
            final boolean started = (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0
                    && child.hasScrollableChildren()
                    && parent.getHeight() - directTargetChild.getHeight() <= child.getHeight();

            if (started && mAnimator != null) {
                // Cancel any offset animation
                mAnimator.cancel();
            }

            // A new nested scroll has started so clear out the previous ref
            mLastNestedScrollingChildRef = null;

            return started;
        }

        @Override
        public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child,
                View target, int dx, int dy, int[] consumed) {
            if (dy != 0 && !mSkipNestedPreScroll) {
                int min, max;
                if (dy < 0) {
                    // We're scrolling down
                    min = -child.getTotalScrollRange();
                    max = min + child.getDownNestedPreScrollRange();
                } else {
                    // We're scrolling up
                    min = -child.getUpNestedPreScrollRange();
                    max = 0;
                }
                consumed[1] = scroll(coordinatorLayout, child, dy, min, max);
            }
        }

        @Override
        public void onNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child,
                View target, int dxConsumed, int dyConsumed,
                int dxUnconsumed, int dyUnconsumed) {
            if (dyUnconsumed < 0) {
                // If the scrolling view is scrolling down but not consuming, it's probably be at
                // the top of it's content
                scroll(coordinatorLayout, child, dyUnconsumed,
                        -child.getDownNestedScrollRange(), 0);
                // Set the expanding flag so that onNestedPreScroll doesn't handle any events
                mSkipNestedPreScroll = true;
            } else {
                // As we're no longer handling nested scrolls, reset the skip flag
                mSkipNestedPreScroll = false;
            }
        }

        @Override
        public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout abl,
                View target) {
            if (!mWasFlung) {
                // If we haven't been flung then let's see if the current view has been set to snap
                snapToChildIfNeeded(coordinatorLayout, abl);
            }

            // Reset the flags
            mSkipNestedPreScroll = false;
            mWasFlung = false;
            // Keep a reference to the previous nested scrolling child
            mLastNestedScrollingChildRef = new WeakReference<>(target);
        }

        @Override
        public boolean onNestedFling(final CoordinatorLayout coordinatorLayout,
                final AppBarLayout child, View target, float velocityX, float velocityY,
                boolean consumed) {
            boolean flung = false;

            if (!consumed) {
                // It has been consumed so let's fling ourselves
                flung = fling(coordinatorLayout, child, -child.getTotalScrollRange(),
                        0, -velocityY);
            } else {
                // If we're scrolling up and the child also consumed the fling. We'll fake scroll
                // upto our 'collapsed' offset
                if (velocityY < 0) {
                    // We're scrolling down
                    final int targetScroll = -child.getTotalScrollRange()
                            + child.getDownNestedPreScrollRange();
                    if (getTopBottomOffsetForScrollingSibling() < targetScroll) {
                        // If we're currently not expanded more than the target scroll, we'll
                        // animate a fling
                        animateOffsetTo(coordinatorLayout, child, targetScroll);
                        flung = true;
                    }
                } else {
                    // We're scrolling up
                    final int targetScroll = -child.getUpNestedPreScrollRange();
                    if (getTopBottomOffsetForScrollingSibling() > targetScroll) {
                        // If we're currently not expanded less than the target scroll, we'll
                        // animate a fling
                        animateOffsetTo(coordinatorLayout, child, targetScroll);
                        flung = true;
                    }
                }
            }

            mWasFlung = flung;
            return flung;
        }

        /**
         * Set a callback to control any {@link AppBarLayout} dragging.
         *
         * @param callback the callback to use, or {@code null} to use the default behavior.
         */
        public void setDragCallback(@Nullable DragCallback callback) {
            mOnDragCallback = callback;
        }

        private void animateOffsetTo(final CoordinatorLayout coordinatorLayout,
                final AppBarLayout child, final int offset) {
            final int currentOffset = getTopBottomOffsetForScrollingSibling();
            if (currentOffset == offset) {
                if (mAnimator != null && mAnimator.isRunning()) {
                    mAnimator.cancel();
                }
                return;
            }

            if (mAnimator == null) {
                mAnimator = ViewUtils.createAnimator();
                mAnimator.setInterpolator(AnimationUtils.DECELERATE_INTERPOLATOR);
                mAnimator.setUpdateListener(new ValueAnimatorCompat.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimatorCompat animator) {
                        setHeaderTopBottomOffset(coordinatorLayout, child,
                                animator.getAnimatedIntValue());
                    }
                });
            } else {
                mAnimator.cancel();
            }

            // Set the duration based on the amount of dips we're travelling in
            final float distanceDp = Math.abs(currentOffset - offset) /
                    coordinatorLayout.getResources().getDisplayMetrics().density;
            mAnimator.setDuration(Math.round(distanceDp * 1000 / ANIMATE_OFFSET_DIPS_PER_SECOND));

            mAnimator.setIntValues(currentOffset, offset);
            mAnimator.start();
        }

        private View getChildOnOffset(AppBarLayout abl, final int offset) {
            for (int i = 0, count = abl.getChildCount(); i < count; i++) {
                View child = abl.getChildAt(i);
                if (child.getTop() <= -offset && child.getBottom() >= -offset) {
                    return child;
                }
            }
            return null;
        }

        private void snapToChildIfNeeded(CoordinatorLayout coordinatorLayout, AppBarLayout abl) {
            final int offset = getTopBottomOffsetForScrollingSibling();
            final View offsetChild = getChildOnOffset(abl, offset);
            if (offsetChild != null) {
                final LayoutParams lp = (LayoutParams) offsetChild.getLayoutParams();
                if ((lp.getScrollFlags() & LayoutParams.FLAG_SNAP) == LayoutParams.FLAG_SNAP) {
                    // We're set the snap, so animate the offset to the nearest edge
                    int childTop = -offsetChild.getTop();
                    int childBottom = -offsetChild.getBottom();

                    // If the view is set only exit until it is collapsed, we'll abide by that
                    if ((lp.getScrollFlags() & LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED)
                            == LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED) {
                        childBottom += ViewCompat.getMinimumHeight(offsetChild);
                    }

                    final int newOffset = offset < (childBottom + childTop) / 2
                            ? childBottom : childTop;
                    animateOffsetTo(coordinatorLayout, abl,
                            MathUtils.constrain(newOffset, -abl.getTotalScrollRange(), 0));
                }
            }
        }

        @Override
        public boolean onLayoutChild(CoordinatorLayout parent, AppBarLayout abl,
                int layoutDirection) {
            boolean handled = super.onLayoutChild(parent, abl, layoutDirection);

            final int pendingAction = abl.getPendingAction();
            if (pendingAction != PENDING_ACTION_NONE) {
                final boolean animate = (pendingAction & PENDING_ACTION_ANIMATE_ENABLED) != 0;
                if ((pendingAction & PENDING_ACTION_COLLAPSED) != 0) {
                    final int offset = -abl.getUpNestedPreScrollRange();
                    if (animate) {
                        animateOffsetTo(parent, abl, offset);
                    } else {
                        setHeaderTopBottomOffset(parent, abl, offset);
                    }
                } else if ((pendingAction & PENDING_ACTION_EXPANDED) != 0) {
                    if (animate) {
                        animateOffsetTo(parent, abl, 0);
                    } else {
                        setHeaderTopBottomOffset(parent, abl, 0);
                    }
                }
            } else if (mOffsetToChildIndexOnLayout >= 0) {
                View child = abl.getChildAt(mOffsetToChildIndexOnLayout);
                int offset = -child.getBottom();
                if (mOffsetToChildIndexOnLayoutIsMinHeight) {
                    offset += ViewCompat.getMinimumHeight(child);
                } else {
                    offset += Math.round(child.getHeight() * mOffsetToChildIndexOnLayoutPerc);
                }
                setTopAndBottomOffset(offset);
            }

            // Finally reset any pending states
            abl.resetPendingAction();
            mOffsetToChildIndexOnLayout = INVALID_POSITION;

            // Make sure we update the elevation
            dispatchOffsetUpdates(abl);

            return handled;
        }

        @Override
        boolean canDragView(AppBarLayout view) {
            if (mOnDragCallback != null) {
                // If there is a drag callback set, it's in control
                return mOnDragCallback.canDrag(view);
            }

            // Else we'll use the default behaviour of seeing if it can scroll down
            if (mLastNestedScrollingChildRef != null) {
                // If we have a reference to a scrolling view, check it
                final View scrollingView = mLastNestedScrollingChildRef.get();
                return scrollingView != null && scrollingView.isShown()
                        && !ViewCompat.canScrollVertically(scrollingView, -1);
            } else {
                // Otherwise we assume that the scrolling view hasn't been scrolled and can drag.
                return true;
            }
        }

        @Override
        int getMaxDragOffset(AppBarLayout view) {
            return -view.getDownNestedScrollRange();
        }

        @Override
        int getScrollRangeForDragFling(AppBarLayout view) {
            return view.getTotalScrollRange();
        }

        @Override
        int setHeaderTopBottomOffset(CoordinatorLayout coordinatorLayout,
                AppBarLayout header, int newOffset, int minOffset, int maxOffset) {
            final int curOffset = getTopBottomOffsetForScrollingSibling();
            int consumed = 0;

            if (minOffset != 0 && curOffset >= minOffset
                    && curOffset <= maxOffset) {
                // If we have some scrolling range, and we're currently within the min and max
                // offsets, calculate a new offset
                newOffset = MathUtils.constrain(newOffset, minOffset, maxOffset);
                AppBarLayout appBarLayout = (AppBarLayout) header;
                if (curOffset != newOffset) {
                    final int interpolatedOffset = appBarLayout.hasChildWithInterpolator()
                            ? interpolateOffset(appBarLayout, newOffset)
                            : newOffset;

                    boolean offsetChanged = setTopAndBottomOffset(interpolatedOffset);

                    // Update how much dy we have consumed
                    consumed = curOffset - newOffset;
                    // Update the stored sibling offset
                    mOffsetDelta = newOffset - interpolatedOffset;

                    if (!offsetChanged && appBarLayout.hasChildWithInterpolator()) {
                        // If the offset hasn't changed and we're using an interpolated scroll
                        // then we need to keep any dependent views updated. CoL will do this for
                        // us when we move, but we need to do it manually when we don't (as an
                        // interpolated scroll may finish early).
                        coordinatorLayout.dispatchDependentViewsChanged(appBarLayout);
                    }

                    // Dispatch the updates to any listeners
                    dispatchOffsetUpdates(appBarLayout);
                }
            }

            return consumed;
        }

        private void dispatchOffsetUpdates(AppBarLayout layout) {
            final List<OnOffsetChangedListener> listeners = layout.mListeners;

            // Iterate backwards through the list so that most recently added listeners
            // get the first chance to decide
            for (int i = 0, z = listeners.size(); i < z; i++) {
                final OnOffsetChangedListener listener = listeners.get(i);
                if (listener != null) {
                    listener.onOffsetChanged(layout, getTopAndBottomOffset());
                }
            }
        }

        private int interpolateOffset(AppBarLayout layout, final int offset) {
            final int absOffset = Math.abs(offset);

            for (int i = 0, z = layout.getChildCount(); i < z; i++) {
                final View child = layout.getChildAt(i);
                final AppBarLayout.LayoutParams childLp = (LayoutParams) child.getLayoutParams();
                final Interpolator interpolator = childLp.getScrollInterpolator();

                if (absOffset >= child.getTop() && absOffset <= child.getBottom()) {
                    if (interpolator != null) {
                        int childScrollableHeight = 0;
                        final int flags = childLp.getScrollFlags();
                        if ((flags & LayoutParams.SCROLL_FLAG_SCROLL) != 0) {
                            // We're set to scroll so add the child's height plus margin
                            childScrollableHeight += child.getHeight() + childLp.topMargin
                                    + childLp.bottomMargin;

                            if ((flags & LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED) != 0) {
                                // For a collapsing scroll, we to take the collapsed height
                                // into account.
                                childScrollableHeight -= ViewCompat.getMinimumHeight(child);
                            }
                        }

                        if (ViewCompat.getFitsSystemWindows(child)) {
                            childScrollableHeight -= layout.getTopInset();
                        }

                        if (childScrollableHeight > 0) {
                            final int offsetForView = absOffset - child.getTop();
                            final int interpolatedDiff = Math.round(childScrollableHeight *
                                    interpolator.getInterpolation(
                                            offsetForView / (float) childScrollableHeight));

                            return Integer.signum(offset) * (child.getTop() + interpolatedDiff);
                        }
                    }

                    // If we get to here then the view on the offset isn't suitable for interpolated
                    // scrolling. So break out of the loop
                    break;
                }
            }

            return offset;
        }

        @Override
        int getTopBottomOffsetForScrollingSibling() {
            return getTopAndBottomOffset() + mOffsetDelta;
        }

        @Override
        public Parcelable onSaveInstanceState(CoordinatorLayout parent, AppBarLayout appBarLayout) {
            final Parcelable superState = super.onSaveInstanceState(parent, appBarLayout);
            final int offset = getTopAndBottomOffset();

            // Try and find the first visible child...
            for (int i = 0, count = appBarLayout.getChildCount(); i < count; i++) {
                View child = appBarLayout.getChildAt(i);
                final int visBottom = child.getBottom() + offset;

                if (child.getTop() + offset <= 0 && visBottom >= 0) {
                    final SavedState ss = new SavedState(superState);
                    ss.firstVisibleChildIndex = i;
                    ss.firstVisibileChildAtMinimumHeight =
                            visBottom == ViewCompat.getMinimumHeight(child);
                    ss.firstVisibileChildPercentageShown = visBottom / (float) child.getHeight();
                    return ss;
                }
            }

            // Else we'll just return the super state
            return superState;
        }

        @Override
        public void onRestoreInstanceState(CoordinatorLayout parent, AppBarLayout appBarLayout,
                Parcelable state) {
            if (state instanceof SavedState) {
                final SavedState ss = (SavedState) state;
                super.onRestoreInstanceState(parent, appBarLayout, ss.getSuperState());
                mOffsetToChildIndexOnLayout = ss.firstVisibleChildIndex;
                mOffsetToChildIndexOnLayoutPerc = ss.firstVisibileChildPercentageShown;
                mOffsetToChildIndexOnLayoutIsMinHeight = ss.firstVisibileChildAtMinimumHeight;
            } else {
                super.onRestoreInstanceState(parent, appBarLayout, state);
                mOffsetToChildIndexOnLayout = INVALID_POSITION;
            }
        }

        protected static class SavedState extends BaseSavedState {
            int firstVisibleChildIndex;
            float firstVisibileChildPercentageShown;
            boolean firstVisibileChildAtMinimumHeight;

            public SavedState(Parcel source, ClassLoader loader) {
                super(source);
                firstVisibleChildIndex = source.readInt();
                firstVisibileChildPercentageShown = source.readFloat();
                firstVisibileChildAtMinimumHeight = source.readByte() != 0;
            }

            public SavedState(Parcelable superState) {
                super(superState);
            }

            @Override
            public void writeToParcel(Parcel dest, int flags) {
                super.writeToParcel(dest, flags);
                dest.writeInt(firstVisibleChildIndex);
                dest.writeFloat(firstVisibileChildPercentageShown);
                dest.writeByte((byte) (firstVisibileChildAtMinimumHeight ? 1 : 0));
            }

            public static final Parcelable.Creator<SavedState> CREATOR =
                    ParcelableCompat.newCreator(new ParcelableCompatCreatorCallbacks<SavedState>() {
                        @Override
                        public SavedState createFromParcel(Parcel source, ClassLoader loader) {
                            return new SavedState(source, loader);
                        }

                        @Override
                        public SavedState[] newArray(int size) {
                            return new SavedState[size];
                        }
                    });
        }
    }

    /**
     * Behavior which should be used by {@link View}s which can scroll vertically and support
     * nested scrolling to automatically scroll any {@link AppBarLayout} siblings.
     */
    public static class ScrollingViewBehavior extends HeaderScrollingViewBehavior {
        private int mOverlayTop;

        public ScrollingViewBehavior() {}

        public ScrollingViewBehavior(Context context, AttributeSet attrs) {
            super(context, attrs);

            TypedArray a = context.obtainStyledAttributes(attrs,
                    R.styleable.ScrollingViewBehavior_Params);
            mOverlayTop = a.getDimensionPixelSize(
                    R.styleable.ScrollingViewBehavior_Params_behavior_overlapTop, 0);
            a.recycle();
        }

        @Override
        public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
            // We depend on any AppBarLayouts
            return dependency instanceof AppBarLayout;
        }

        @Override
        public boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) {
            // First lay out the child as normal
            super.onLayoutChild(parent, child, layoutDirection);

            // Now offset us correctly to be in the correct position. This is important for things
            // like activity transitions which rely on accurate positioning after the first layout.
            final List<View> dependencies = parent.getDependencies(child);
            for (int i = 0, z = dependencies.size(); i < z; i++) {
                if (updateOffset(parent, child, dependencies.get(i))) {
                    // If we updated the offset, break out of the loop now
                    break;
                }
            }
            return true;
        }

        @Override
        public boolean onDependentViewChanged(CoordinatorLayout parent, View child,
                View dependency) {
            updateOffset(parent, child, dependency);
            return false;
        }

        private boolean updateOffset(CoordinatorLayout parent, View child, View dependency) {
            final CoordinatorLayout.Behavior behavior =
                    ((CoordinatorLayout.LayoutParams) dependency.getLayoutParams()).getBehavior();
            if (behavior instanceof Behavior) {
                // Offset the child so that it is below the app-bar (with any overlap)
                final int offset = ((Behavior) behavior).getTopBottomOffsetForScrollingSibling();
                setTopAndBottomOffset(dependency.getHeight() + offset
                        - getOverlapForOffset(dependency, offset));
                return true;
            }
            return false;
        }

        private int getOverlapForOffset(final View dependency, final int offset) {
            if (mOverlayTop != 0 && dependency instanceof AppBarLayout) {
                final AppBarLayout abl = (AppBarLayout) dependency;
                final int totalScrollRange = abl.getTotalScrollRange();
                final int preScrollDown = abl.getDownNestedPreScrollRange();

                if (preScrollDown != 0 && (totalScrollRange + offset) <= preScrollDown) {
                    // If we're in a pre-scroll down. Don't use the offset at all.
                    return 0;
                } else {
                    final int availScrollRange = totalScrollRange - preScrollDown;
                    if (availScrollRange != 0) {
                        // Else we'll use a interpolated ratio of the overlap, depending on offset
                        final float percScrolled = offset / (float) availScrollRange;
                        return MathUtils.constrain(
                                Math.round((1f + percScrolled) * mOverlayTop), 0, mOverlayTop);
                    }
                }
            }
            return mOverlayTop;
        }

        /**
         * Set the distance that this view should overlap any {@link AppBarLayout}.
         *
         * @param overlayTop the distance in px
         */
        public void setOverlayTop(int overlayTop) {
            mOverlayTop = overlayTop;
        }

        /**
         * Returns the distance that this view should overlap any {@link AppBarLayout}.
         */
        public int getOverlayTop() {
            return mOverlayTop;
        }

        @Override
        View findFirstDependency(List<View> views) {
            for (int i = 0, z = views.size(); i < z; i++) {
                View view = views.get(i);
                if (view instanceof AppBarLayout) {
                    return view;
                }
            }
            return null;
        }

        @Override
        int getScrollRange(View v) {
            if (v instanceof AppBarLayout) {
                return ((AppBarLayout) v).getTotalScrollRange();
            } else {
                return super.getScrollRange(v);
            }
        }
    }
}


text:
        {{site.username}}
        {{site.user_title}}

        Sobre

redpajama_set_name: RedPajamaGithub


text:
function findFrameByName(strName) {
    return findFrame(top, strName);
  }

function findFrame(doc, strName) {
   if (doc.frames.length == 0) return;

   for (var i = 0; i != doc.frames.length; i++)
     if (doc.frames[i].name == strName)
       return doc.frames[i];
     else {
       var frm = findFrame(doc.frames[i].window, strName);

       if ( frm  )
         return frm;
     }

   return top;
}
function performAction_not_used(urlParams){
  var frm = findFrameByName('body');
  document.body.style.cursor = "wait";
  frm.document.body.style.cursor = "wait";
  frm.document.location = "search?"+urlParams + "<%= callerParams %>";
}
function formSearchAction(urlParams){
    var frm = findFrameByName('body');
    document.body.style.cursor = "wait";
    frm.document.body.style.cursor = "wait";
    frm.document.location = "/CDEBrowser/formSearchAction.do?method=getAllFormsForTreeNode&"+urlParams;
}

function formDetailsAction(urlParams){
    top.document.location = "/CDEBrowser/formDetailsAction.do?method=getFormDetails&"+urlParams;
}


text:
namespace MindFlavor.SQLServer.Errorlog
{
    public class ServerInfo
    {
        public string Name { get; set; }
        public string LogPath { get; set; }
    }
}


text:
/* Bootstrap css */
@import "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css";

/* Propeller icons */
@import "http://fonts.googleapis.com/icon?family=Material+Icons";
@import "http://propeller.in/components/icons/css/google-icons.css";

/* Propeller text field */
@import "http://propeller.in/components/textfield/css/textfield.css";


text:
package com.epi;

/*

public class OnlineMedian {
  private static List<Double> globalResult = new ArrayList<>();

  // @include
  private static final int DEFAULT_INITIAL_CAPACITY = 16;

  public static void onlineMedian(Iterator<Integer> sequence) {
    // minHeap stores the larger half seen so far.
    PriorityQueue<Integer> minHeap = new PriorityQueue<>();
    // maxHeap stores the smaller half seen so far.
    PriorityQueue<Integer> maxHeap = new PriorityQueue<>(
        DEFAULT_INITIAL_CAPACITY, Collections.reverseOrder());

    while (sequence.hasNext()) {
      int x = sequence.next();
      if (minHeap.isEmpty()) {
        // This is the very first element.
        minHeap.add(x);
      } else {
        if (x >= minHeap.peek()) {
          minHeap.add(x);
        } else {
          maxHeap.add(x);
        }
      }
      // Ensure minHeap and maxHeap have equal number of elements if
      // an even number of elements is read; otherwise, minHeap must have
      // one more element than maxHeap.
      if (minHeap.size() > maxHeap.size() + 1) {
        maxHeap.add(minHeap.remove());
      } else if (maxHeap.size() > minHeap.size()) {
        minHeap.add(maxHeap.remove());
      }

      // @exclude
      globalResult.add((minHeap.size() == maxHeap.size()
                            ? 0.5 * (minHeap.peek() + maxHeap.peek())
                            : minHeap.peek()));
      // @include
      System.out.println(minHeap.size() == maxHeap.size()
                             ? 0.5 * (minHeap.peek() + maxHeap.peek())
                             : minHeap.peek());
    }
  }
  // @exclude

  private static void smallTest() {
    //List<Double> stream = Arrays.asList(5, 4, 3, 2, 1);
    //onlineMedian(stream.iterator());
    List<Double> golden = Arrays.asList(5.0, 4.5, 4.0, 3.5, 3.0);
    assert golden.equals(globalResult);

    globalResult.clear();
    //stream = Arrays.asList(1, 2, 3, 4, 5);
    //onlineMedian(stream.iterator());
    golden = Arrays.asList(1.0, 1.5, 2.0, 2.5, 3.0);
    assert golden.equals(globalResult);

    globalResult.clear();
    //stream = Arrays.asList(1, 0, 3, 5, 2, 0, 1);
    //onlineMedian(stream.iterator());
    golden = Arrays.asList(1.0, 0.5, 1.0, 2.0, 2.0, 1.5, 1.0);
    assert golden.equals(globalResult);

    globalResult.clear();
    //stream = Arrays.asList(-1);
    //onlineMedian(stream.iterator());
    golden = Arrays.asList(-1.0);
    assert golden.equals(globalResult);
  }

  public static void main(String[] args) {
    smallTest();
    Random r = new Random();
    int num;
    if (args.length == 1) {
      num = Integer.parseInt(args[0]);
    } else {
      num = r.nextInt(100000) + 1;
    }
    List<Integer> stream = new ArrayList<>();
    for (int i = 0; i < num; ++i) {
      stream.add(r.nextInt(10000) + 1);
    }
    onlineMedian(stream.iterator());
  }
}
*/


text:
import Node from './Node';
import ParentNode from './ParentNode';

/**
 * The DocumentFragment interface represents a minimal document object that has no parent. It is used as
 * a light-weight version of Document to store well-formed or potentially non-well-formed fragments of XML.
 *
  * @see https://developer.mozilla.org/en/docs/Web/API/DocumentFragment
 */
export default class DocumentFragment extends ParentNode {
    /**
     * @inheritdoc
     */
    get outerHTML() {
        return this.innerHTML;
    }
}

/**
 * @constant {number} Comment#nodeType
 */
Object.defineProperty(DocumentFragment.prototype, 'nodeType', { value: Node.DOCUMENT_FRAGMENT_NODE });


text:
package com.google.gwt.chrome.storage;

import com.google.gwt.chrome.def.SimpleJSObject;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONString;

/**
 * Items under the "sync" storage area are synced using Chrome Sync.
 *
 * @author jarrod
 *
 */
public class SyncStorageArea implements StorageArea {
	/**
	 * The maximum number of items that can be stored in sync storage.
	 *

	 * Updates that would cause this limit to be exceeded will fail immediately
	 * and set chrome.runtime.lastError.
	 *

	 *

	 * Value: 512
	 *

	 */
	public static final int MAX_ITEMS = 512;
	/**
	 * The maximum number of set, remove, or clear operations that can be
	 * performed each minute, sustained over 10 minutes.
	 *

	 * Updates that would cause this limit to be exceeded fail immediately and
	 * set chrome.runtime.lastError.
	 *

	 *

	 * Value: 10
	 *

	 */
	public static final int MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE = 10;
	/**
	 * The maximum number of set, remove, or clear operations that can be
	 * performed each hour.
	 *

	 * Updates that would cause this limit to be exceeded fail immediately and
	 * set chrome.runtime.lastError.
	 *

	 *

	 * Value: 1,000
	 *

	 */
	public static final int MAX_WRITE_OPERATIONS_PER_HOUR = 1000;
	/**
	 * The maximum total amount (in bytes) of data that can be stored in sync
	 * storage, as measured by the JSON stringification of every value plus
	 * every key's length.
	 *

	 * Updates that would cause this limit to be exceeded fail immediately and
	 * set chrome.runtime.lastError.
	 *

	 *

	 * Value: 102,400 B
	 *

	 */
	public static final int QUOTA_BYTES = 102400;
	/**
	 * The maximum size (in bytes) of each individual item in sync storage, as
	 * measured by the JSON stringification of its value plus its key length.
	 *

	 * Updates containing items larger than this limit will fail immediately and
	 * set chrome.runtime.lastError.
	 *

	 *

	 * Value: 4,096 B
	 *

	 */
	public static final int QUOTA_BYTES_PER_ITEM = 4096;

	final StorageAreaImpl impl;
	protected SyncStorageArea(boolean isAvailable){
		if(isAvailable){
			impl = GWT.create(SyncStorageAreaImpl.class);
		} else {
			impl = GWT.create(SyncStorageAreaWebImpl.class);
		}
	}

	@Override
	public void getBytesInUse(String key, StorageUseCallback callback) {
		impl.getBytesInUse(new String[]{key}, callback);
	}

	@Override
	public void getBytesInUse(String[] keys, StorageUseCallback callback) {
		impl.getBytesInUse(keys, callback);
	}

	@Override
	public void clear(StorageSimpleCallback callback) {
		impl.clear(callback);
	}

	@Override
	public void set(JavaScriptObject data, StorageSimpleCallback callback) {
		impl.set(data, callback);
	}

	@Override
	public void remove(String key, StorageSimpleCallback callback) {
		impl.remove(new String[]{key}, callback);
	}

	@Override
	public void remove(String[] keys, StorageSimpleCallback callback) {
		impl.remove(keys, callback);
	}

	@Override
	public void get(final String key, final StorageItemCallback callback) {
		JSONObject obj = new JSONObject();
		obj.put(key, new JSONString(""));
		get(obj.getJavaScriptObject(), new StorageItemsCallback() {

			@Override
			public void onResult(JavaScriptObject data) {
				SimpleJSObject obj = data.cast();
				String[] keys = obj.getKeys();
				for(String _key : keys){
					if(_key.equals(key)){
						callback.onResult(obj.getString(_key));
						return;
					}
				}
				callback.onResult("");
			}

			@Override
			public void onError(String message) {
				callback.onError(message);
			}
		});
	}

	@Override
	public void get(String[] keys, StorageItemsCallback callback) {
		JSONObject obj = new JSONObject();
		for(String key : keys){
			obj.put(key, new JSONString(""));
		}
		get(obj.getJavaScriptObject(), callback);
	}

	@Override
	public void get(JavaScriptObject keysWithDefaults,
			StorageItemsCallback callback) {
		impl.get(keysWithDefaults, callback);
	}

}


text:
package com.training.weather.strategy.impl;

import com.github.fedy2.weather.YahooWeatherService;
import com.github.fedy2.weather.data.Channel;
import com.github.fedy2.weather.data.unit.DegreeUnit;
import com.training.weather.domain.WeatherForecast;
import com.training.weather.strategy.WeatherForecastEmitterStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import reactor.core.publisher.MonoSink;

import javax.xml.bind.JAXBException;
import java.io.IOException;
import java.util.List;

/**
 * Yahoo Weather specific implementation of {@link WeatherForecastEmitterStrategy}.
 *
 * @author Gabor_Bata
 */
@Component
public class YahooWeatherForecastEmitterStrategy implements WeatherForecastEmitterStrategy {
    private static final Logger LOG = LoggerFactory.getLogger(YahooWeatherForecastEmitterStrategy.class);

    @Autowired
    private Converter<Channel, WeatherForecast> yahooChannelToWeatherForecastConverter;

    @Override
    public void emitWeatherForecast(String location, MonoSink<WeatherForecast> emitter) {
        try {
            LOG.debug("Getting forecast data for [{}]", location);
            YahooWeatherService yahooWeatherService = new YahooWeatherService();
            List<Channel> channels = yahooWeatherService.getForecastForLocation(location, DegreeUnit.CELSIUS).first(1);
            emitter.success(channels.stream()
                    .map(yahooChannelToWeatherForecastConverter::convert)
                    .findFirst()
                    .orElse(null));
        } catch (JAXBException | IOException | NullPointerException e) {
            emitter.error(e);
        }
    }
}


text:
https://onlinecourses.science.psu.edu/stat414/node/191
http://stats.stackexchange.com/questions/27436/how-to-take-derivative-of-multivariate-normal-density
https://www.statlect.com/fundamentals-of-statistics/
https://www.youtube.com/watch?v=kPrHqQzCkg0


text:
blue=$(tput setaf 4)
normal=$(tput sgr0)

# if [[ ( $1 -eq "prok") ]];
# then

	# create a test experimental design file for proks
    printf "${blue}Creating experimental design file for prokaryotes\n${normal}"
    find tests/data/fastqs -iname "*test*R2.fastq" | sort > testR2.txt
    find tests/data/fastqs -iname "*test*R1.fastq" | sort | sed 's/R1\.fastq/R1\.fastq:/g' > testR1.txt
    printf "samp1\nsamp2\nsamp3\nsamp4\nsamp5\nsamp6\n" > test_id.txt
    printf "liver\nspleen\nspleen\nliver\nliver\nspleen\n" > test_gr.txt
    paste test_id.txt testR1.txt testR2.txt test_gr.txt > test_ed.txt
    rm test_id.txt testR1.txt testR2.txt test_gr.txt
    sed "s/:$(printf '\t')/:/g" test_ed.txt > test_edII.txt
    printf "#SampleID\tFiles\tGroup\n" | cat - test_edII.txt > tests/test_prok.txt
    # rm test_ed.txt test_edII.txt

# fi

# if [[ ( $1 -eq "prok" && $2 -eq "hisat" ) || ( -z $1 ) ]];
# then
#     #==============================================================================#
#     printf "${blue}testing pipeline with prokarya using DEedge\n${normal}"
#     printf "${blue}using HISAT2\n${normal}"

#     printf "bin/piret -d tests/test_prok -e test_prok.txt \
#     -gp tests/data/test_prok.gff \
#     -i tests/test_prok/prok_index -k prokarya -m DEedge \
#     -fp tests/data/test_prok.fna --config luigi.cfg"

#     bin/piret -d tests/test_prok -e test_prok.txt \
#     -gp tests/data/test_prok.gff \
#     -i tests/test_prok/prok_index -k prokarya -m DEedge \
#     -fp tests/data/test_prok.fna --config luigi.cfg \
#     --aligner hisat2

#     printf "${blue} using STAR\n${normal}"

#     bin/piret -d tests/test_prok -e test_prok.txt  \
#     -gp tests/data/test_prok.gff \
#     -i tests/test_prok/prok_index \
#     -k prokarya -m DEedge  \
#     -fp tests/data/test_prok.fna \
#     --config luigi.cfg \
#     --aligner STAR

#     printf "${blue}fininshed testing pipeline for prokarya only\n${normal}"
#     #==============================================================================#
# fi
# 	############################################################################

# # euk star ballgown
# # This run takes 3m14.979s in my laptop
# bin/piret -d tests/test_euk -e test_euk.txt -ge tests/data2/chr22_ERCC92.gff3 -k eukarya -m ballgown -fe tests/data2/chr22_ERCC92.fa  -p 0.05 --e_org hsa --aligner STAR --config luigi.cfg

# # euk star novel ballgown
# # This run takes 4m54.541s in my laptop
# bin/piret -d tests/test_euk -e test_euk.txt -ge tests/data2/chr22_ERCC92.gff3 -k eukarya -m ballgown -fe tests/data2/chr22_ERCC92.fa  -p 0.05 --e_org hsa --aligner STAR --config luigi.cfg --novel

# # euk star novel edgeR
# # This run takes  4m59.662s in my laptop
# bin/piret -d tests/test_euk -e test_euk.txt -ge tests/data2/chr22_ERCC92.gff3 -k eukarya -m edgeR -fe tests/data2/chr22_ERCC92.fa  -p 0.05 --e_org hsa --aligner STAR --config luigi.cfg --novel

# # euk star edger novel (fails at pathway step)

# # euk star deseq novel
# # This run takes 4m53.541s in my laptop
# bin/piret -d tests/test_euk -e test_euk.txt -ge tests/data2/chr22_ERCC92.gff3 -k eukarya -m DESeq2 -fe tests/data2/chr22_ERCC92.fa  -p 0.05 --e_org hsa --aligner STAR --config luigi.cfg --novel

# # euk hisat2 edgeR novel
# bin/piret -d tests/test_euk -e test_euk.txt -ge tests/data2/chr22_ERCC92.gff3 -k eukarya -m edgeR -fe tests/data2/chr22_ERCC92.fa  -p 0.05 --org hsa --aligner hisat2 --config luigi.cfg --novel

# # euk hisat2 edgeR
# bin/piret -d tests/test_euk -e test_euk.txt -ge tests/data2/chr22_ERCC92.gff3 -k eukarya -m edgeR -fe tests/data2/chr22_ERCC92.fa  -p 0.05 --org hsa --aligner hisat2 --config luigi.cfg

# # both hisat

# if [[ $1 -eq "euk" ]] || [[ -z $1 ]];
# then
#     printf "${blue}testing pipeline with eukarya \n${normal}"

#     find tests/data2/fastqs -iname "*read2.fastq" | sort > testR2.txt
#     find tests/data2/fastqs -iname "*read1.fastq" | sort | sed 's/read1\.fastq/read1\.fastq:/g' > testR1.txt
#     printf "samp1\nsamp2\nsamp3\nsamp4\nsamp5\nsamp6\n" > test_id.txt
#     printf "HBR\nHBR\nHBR\nUBR\nUBR\nUBR\n" > test_gr.txt
#     paste test_id.txt testR1.txt testR2.txt test_gr.txt > test_ed.txt
#     rm test_id.txt testR1.txt testR2.txt test_gr.txt
#     sed "s/:$(printf '\t')/:/g" test_ed.txt > test_edII.txt
#     printf "#SampleID\tFiles\tGroup\n" | cat - test_edII.txt > test_euk.txt
#     rm test_ed.txt test_edII.txt
# fi

# # printf "bin/piret -d tests/test_euk -e test_euk.txt -ge tests/data2/chr22_ERCC92.gff3 \
# # -k eukarya -m DESeq2 -fe tests/data2/chr22_ERCC92.fa  -p 0.05 --org hsa \
# # --novel --aligner STAR --config luigi.cfg "

# # bin/piret -d tests/test_euk -e test_euk.txt -ge tests/data2/chr22_ERCC92.gff3 \
# # -k eukarya -m DESeq2 -fe tests/data2/chr22_ERCC92.fa  -p 0.05 --org hsa \
# # --novel --aligner STAR --config luigi.cfg

# # bin/piret -d tests/test_euk -e test_euk.txt \
# # -ge tests/data2/chr22_ERCC92.gff3 \
# # -i tests/test_euk/euk_index -k eukarya -m all \
# # -fe tests/data2/chr22_ERCC92.fa --config luigi.cfg -p 0.05

# # printf "${blue}fininshed testing pipeline for eukarya\n${normal}"

# # # #==============================================================================#
# # # printf "${blue}testing pipeline with prok and euk now \n${normal}"

# # printf "bin/piret -d tests/test_both -e test_prok.txt \
# # -gp tests/data/test_prok.gff -ge tests/data/eukarya_test.gff3 \
# # -i tests/test_both/prok_euk_index -k both -m all \
# # -fp tests/data/test_prok.fna -fe tests/data/eukarya_test.fa"

# # # mkdir -p tests/test_both/samp1/trimming_results
# # # mkdir -p tests/test_both/samp2/trimming_results
# # # mkdir -p tests/test_both/samp3/trimming_results
# # # mkdir -p tests/test_both/samp4/trimming_results
# # # mkdir -p tests/test_both/samp5/trimming_results
# # # mkdir -p tests/test_both/samp6/trimming_results

# # # cp tests/test_both/samp1/trimming_results/*.* tests/test_euk/samp1/trimming_results/
# # # cp tests/test_both/samp2/trimming_results/*.* tests/test_euk/samp2/trimming_results/
# # # cp tests/test_both/samp3/trimming_results/*.* tests/test_euk/samp3/trimming_results/
# # # cp tests/test_both/samp4/trimming_results/*.* tests/test_euk/samp4/trimming_results/
# # # cp tests/test_both/samp5/trimming_results/*.* tests/test_euk/samp5/trimming_results/
# # # cp tests/test_both/samp6/trimming_results/*.* tests/test_euk/samp6/trimming_results/

# bin/piret -d tests/test_both -e test_prok.txt \
# -gp tests/data/test_prok.gff -ge tests/data/eukarya_test.gff3 \
# -i tests/test_both/prok_euk_index -k both -m all \
# -fp tests/data/test_prok.fna -fe tests/data/eukarya_test.fa

# # printf "${blue}fininshed testing pipeline for prok and euk\n${normal}"

# # # printf "${blue}Cleanning up!!\n${normal}"
# # # # rm -rf test_experimental_design.txt
# # # # rm -rf tests/test_both tests/test_euk tests/test_prok

# printf "${green}piret with both euk and prok, and edgeR\n${normal}"
# bin/piret -d tests/test_both_hisat2_edger -e test_prok.txt \
# -gp tests/data/test_prok.gff -ge tests/data/eukarya_test.gff3 \
# -i tests/test_both/prok_euk_index -k both -m edgeR \
# -fp tests/data/test_prok.fna -fe tests/data/eukarya_test.fa --novel
# printf "${blue}fininshed testing pipeline for prok and euk\n${normal}"

# bin/piret -d tests/test_both_hisat2_edger -e test_prok.txt \
# -gp tests/data/test_prok.gff -ge tests/data/eukarya_test.gff3 \
# -i tests/test_both/prok_euk_index -k both -m edgeR \
# -fp tests/data/test_prok.fna -fe tests/data/eukarya_test.fa --novel \
# --aligner STAR

# bin/piret -d tests/test_both_hisat2_ballgown -e test_prok.txt \
# -gp tests/data/test_prok.gff -ge tests/data/eukarya_test.gff3 \
# -i tests/test_both/prok_euk_index -k both -m ballgown \
# -fp tests/data/test_prok.fna -fe tests/data/eukarya_test.fa --novel

#  bin/piret -d tests/test_both_hisat2_deseq2 -e test_prok.txt \
#  -gp tests/data/test_prok.gff -ge tests/data/eukarya_test.gff3 \
#  -i tests/test_both/prok_euk_index -k both -m DESeq2 \
#  -fp tests/data/test_prok.fna -fe tests/data/eukarya_test.fa --novel


text:
require_relative '../lib/ba'
require_relative '../lib/ba/cli'


text:
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package tutorial;

import com.opensymphony.xwork2.ActionSupport;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.interceptor.ServletRequestAware;

/**
 *
 * @author Administrator
 */
public class Test_RedirectAction extends ActionSupport implements ServletRequestAware{

    private HttpServletRequest request;

    public void setServletRequest(HttpServletRequest arg0) {
        this.request = arg0;
    }

    @Override
    public String execute() throws Exception {
        //request.setAttribute("name", "bbbbb");
        return SUCCESS;
    }

}


text:
class FeatureListSaver : public kmlconvenience::CsvParserHandler {
 public:
  FeatureListSaver(kmlconvenience::FeatureList* feature_list)
    : feature_list_(feature_list) {
  }

  // This is the method called from within the CsvParser for each line in the
  // input CSV.  In this implementation we save all Placemarks from good lines
  // and quietly skip over imperfect lines.
  virtual bool HandleLine(int line, kmlconvenience::CsvParserStatus status,
                          kmldom::PlacemarkPtr p) {
    if (status == kmlconvenience::CSV_PARSER_STATUS_OK &&
        kmlengine::GetFeatureLatLon(p, NULL, NULL)) {
      feature_list_->PushBack(p);
    }
    // TODO: how to indicate an error on a given line?
    return true;  // Always advance to the next line of CSV data.
  }

 private:
  kmlconvenience::FeatureList* feature_list_;
};

// IDs for the controls and menu commands.
enum {
  Regionator_Quit = wxID_EXIT,
  Regionator_About = wxID_ABOUT,
  Regionator_InputFile,
  Regionator_OutputDir,
  Regionator_GenerateKML
};

// Event tables.
BEGIN_EVENT_TABLE(MainFrame, wxFrame)
  EVT_MENU(Regionator_Quit, MainFrame::OnQuit)
  EVT_MENU(Regionator_About, MainFrame::OnAbout)
END_EVENT_TABLE()

MainFrame::MainFrame(const wxString& title)
  : wxFrame(NULL, -1, title, wxPoint(-1, -1), wxSize(450, 400)),
    panel_(NULL), input_file_ctrl_(NULL), output_dir_ctrl_(NULL) {

  // Menu bar setup.
  wxMenu* filemenu = new wxMenu;
  filemenu->Append(Regionator_Quit, _T("Exit"), _T("Quit this application"));
  wxMenu* helpmenu = new wxMenu;
  helpmenu->Append(Regionator_About, _T("About..."), _T("Show about dialog"));
  wxMenuBar* menubar = new wxMenuBar();
  menubar->Append(filemenu, _T("&File"));
  menubar->Append(helpmenu, _T("&Help"));
  SetMenuBar(menubar);

  // Status bar.
  CreateStatusBar(2);
  SetStatusText(_T("Regionator demo"));

  // Layout.
  panel_ = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(450, 400));
  wxBoxSizer* vbox = new wxBoxSizer(wxVERTICAL);

  // Input file picker.
  wxBoxSizer *hbox1 = new wxBoxSizer(wxHORIZONTAL);
  wxStaticText *st1 =  new wxStaticText(panel_, wxID_ANY,
                                        wxT("Input CSV file"));
  hbox1->Add(st1, 0, wxRIGHT, 10);
  input_file_ctrl_ = new wxFilePickerCtrl(panel_, Regionator_InputFile,
                                          wxEmptyString,
                                          wxT("Select input CSV file"),
                                          wxT("*"),
                                          wxDefaultPosition, wxDefaultSize,
                                          wxFLP_USE_TEXTCTRL);
  hbox1->Add(input_file_ctrl_, 1);
  vbox->Add(hbox1, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 10);
  vbox->Add(-1, 10);  // Spacer.

  // Output directory picker.
  wxBoxSizer *hbox2 = new wxBoxSizer(wxHORIZONTAL);
  wxStaticText *st2 = new wxStaticText(panel_, wxID_ANY,
                                       wxT("Output directory"));
  hbox2->Add(st2, 0, wxRIGHT, 10);
  output_dir_ctrl_ = new wxDirPickerCtrl(panel_, Regionator_OutputDir,
                                         wxEmptyString,
                                         wxT("Select output directory"),
                                         wxDefaultPosition, wxDefaultSize,
                                         wxDIRP_USE_TEXTCTRL);
  hbox2->Add(output_dir_ctrl_, 1);
  vbox->Add(hbox2, 0, wxLEFT | wxRIGHT | wxEXPAND, 10);
  vbox->Add(-1, 30);

  // OK and Cancel buttons.
  wxBoxSizer *hbox5 = new wxBoxSizer(wxHORIZONTAL);
  wxButton *btn1 = new wxButton(panel_, Regionator_GenerateKML,
                                wxT("Generate KML files"));
  hbox5->Add(btn1, 0);
  vbox->Add(hbox5, 0, wxALIGN_RIGHT | wxRIGHT | wxBOTTOM, 15);

  // Events.
  Connect(Regionator_GenerateKML, wxEVT_COMMAND_BUTTON_CLICKED,
          wxCommandEventHandler(MainFrame::GenerateRbnl));

  // Final sizing before display.
  vbox->SetMinSize(450,100);
  panel_->SetSizer(vbox);
  vbox->SetSizeHints(this);
  Centre();
}

void MainFrame::GenerateRbnl(wxCommandEvent& event) {
  // Ensure the values for the input and output are sane.
  if (!ValidateFormFields(input_file_ctrl_->GetPath().c_str(),
                          output_dir_ctrl_->GetPath())) {
    return;
  }

  // Check if the output dir is empty. Bail if the dir wasn't empty and the
  // user elected not to continue.
  const char* output_dir = output_dir_ctrl_->GetPath();
  if (!AskIfOutputDirNotEmpty(output_dir)) {
    return;
  }

  string csv_data;
  if (!kmlbase::File::ReadFileToString(input_file_ctrl_->GetPath().c_str(),
                                       &csv_data)) {
    // TODO: how to indicate file read error?
    return;
  }
  kmlbase::CsvSplitter csv_splitter(csv_data);

  // Parse the CSV file into a FeatureList of Point Placemarks sorted by score.
  kmlconvenience::FeatureList feature_list;
  FeatureListSaver feature_saver(&feature_list);
  if (!kmlconvenience::CsvParser::ParseCsv(&csv_splitter, &feature_saver)) {
    // TODO: how to indicate CSV parse error?
    return;
  }

  wxString info("Regionation in progress");
  // TODO: use a smart pointer
  progress_dialog_ = new wxProgressDialog(info, info, feature_list.Size(),
                                          this,
                                          wxPD_CAN_ABORT | wxPD_APP_MODAL);

  // Give the FeatureList to the FeatureListRegionator which walks the
  // hierarchy starting at root.  The output is aligned to a quadtree rooted
  // at n=180, s=-180, e=180, w=-180.
  if (!kmlregionator::FeatureListRegionator<MainFrame>::Regionate(
      &feature_list, 10, this, output_dir)) {
    // TODO: tell user about failure
  }
  delete progress_dialog_;  // This takes down the dialog.
  // TODO: tell user OK!
}

bool MainFrame::RegionatorProgress(unsigned int completed, unsigned int total) {
  if (progress_dialog_) {
    if (!progress_dialog_->Update(completed)) {
      return false;  // User pressed cancel so that we will do.
    }
  }
  return true;  // Continue regionating.
}

void MainFrame::OnQuit(wxCommandEvent& event) {
  delete output_dir_ctrl_;
  delete input_file_ctrl_;
  delete panel_;
  Close(true);
}

void MainFrame::OnAbout(wxCommandEvent& event) {
  wxMessageBox(wxString::Format(
    _T("Welcome to the Regionator!\n")
    _T("\n")
    _T("http://libkml.googlecode.com/")
  ),
  _T("About Regionator"),
  wxOK | wxICON_INFORMATION,
  this);
}

// Private.
bool MainFrame::ValidateFormFields(const wxChar* input_file,
                                   const wxString& output_dir) {
  wxString errors;
  // Ensure the CSV file is readable.
  if (!wxFile::Access(input_file, wxFile::read)) {
    errors.Printf(_T("Error: input file is not readable\n"));
  // Ensure the output dir exists.
  } else if (!wxDir::Exists(output_dir)) {
    errors.Printf(_T("Error: the output directory must exist\n"));
  }
  if (errors.empty()) {
    return true;
  }
  wxMessageDialog err_dialog(this, errors, _T("Cannot continue"),
                             wxOK | wxICON_ERROR);
  err_dialog.ShowModal();
  return false;
}

// Private.
bool MainFrame::AskIfOutputDirNotEmpty(const wxString& output_dir) {
  wxDir dir(output_dir);
  if (dir.HasFiles()) {
    wxString warning;
    warning.Printf(_T("Output directory is not empty\n")
                   _T("Would you like to continue anyway?\n"));
    wxMessageDialog dialog(this, warning, _T("Warning"),
                           wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION);
    return dialog.ShowModal() == wxID_YES;
  }
  return true;
}