milosmns/silly-android

View on GitHub
sillyandroid/src/main/java/me/angrybyte/sillyandroid/parsable/components/ParsableDialog.java

Summary

Maintainability
A
1 hr
Test Coverage
package me.angrybyte.sillyandroid.parsable.components;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.support.annotation.CallSuper;
import android.support.annotation.IdRes;
import android.support.annotation.LayoutRes;
import android.support.annotation.MenuRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StyleRes;
import android.util.SparseArray;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;

import me.angrybyte.sillyandroid.components.EasyDialog;
import me.angrybyte.sillyandroid.parsable.AnnotationParser;
import me.angrybyte.sillyandroid.parsable.Annotations;

/**
 * An extension from {@link EasyDialog} with included {@link AnnotationParser} capabilities.
 */
@SuppressWarnings({"WeakerAccess", "unused"})
public class ParsableDialog extends EasyDialog implements View.OnClickListener, View.OnLongClickListener {

    /**
     * The layout ID pulled from the {@link me.angrybyte.sillyandroid.parsable.Annotations.Layout} annotation will be stored here.
     */
    @LayoutRes
    @SuppressWarnings("unused")
    private int mLayoutId;

    /**
     * The menu ID pulled from the {@link me.angrybyte.sillyandroid.parsable.Annotations.Menu} annotation will be stored here.
     */
    @MenuRes
    @SuppressWarnings("unused")
    private int mMenuId;

    /**
     * All Views annotated with {@link me.angrybyte.sillyandroid.parsable.Annotations.FindView} annotation will be mapped here.
     */
    private SparseArray<View> mFoundViews;

    /**
     * A real (external) dismiss listener, invoked from the dismiss proxy {@link #mOnDismissListenerProxy}.
     */
    private OnDismissListener mRealDismissListener;

    // <editor-fold desc="Constructors">

    /**
     * {@inheritDoc}
     */
    public ParsableDialog(@NonNull final Context context) {
        super(context);
    }

    /**
     * {@inheritDoc}
     */
    public ParsableDialog(@NonNull final Context context, @StyleRes final int themeResId) {
        super(context, themeResId);
    }

    /**
     * {@inheritDoc}
     */
    protected ParsableDialog(@NonNull final Context context, final boolean cancelable, @Nullable final OnCancelListener cancelListener) {
        super(context, cancelable, cancelListener);
    }

    @Override
    @CallSuper
    protected void onConstruct(@NonNull final Context context) {
        super.onConstruct(context);
        initializeParsedProperties(context);
    }
    // </editor-fold>

    // <editor-fold desc="Content View setters">

    /**
     * {@inheritDoc}
     */
    @Override
    public void setContentView(@LayoutRes final int layoutResID) {
        super.setContentView(layoutResID);
        if (mFoundViews != null) {
            mFoundViews.clear();
        }
        mFoundViews = AnnotationParser.parseFields(getContext(), this, this);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setContentView(@NonNull final View view) {
        super.setContentView(view);
        if (mFoundViews != null) {
            mFoundViews.clear();
        }
        mFoundViews = AnnotationParser.parseFields(getContext(), this, this);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setContentView(@NonNull final View view, @Nullable final ViewGroup.LayoutParams params) {
        super.setContentView(view, params);
        if (mFoundViews != null) {
            mFoundViews.clear();
        }
        mFoundViews = AnnotationParser.parseFields(getContext(), this, this);
    }
    // </editor-fold>

    /**
     * Parses the type and all its fields using the {@link AnnotationParser}.
     *
     * @param context Which context to use
     */
    @SuppressLint("ResourceType") // TODO getLayoutId() can return < 0 ???
    private void initializeParsedProperties(@NonNull final Context context) {
        AnnotationParser.parseType(context, this);
        if (getLayoutId() > 0) {
            setContentView(getLayoutId());
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        setOnDismissListener(mOnDismissListenerProxy);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @SuppressLint("ResourceType") // TODO getLayoutId() can return < 0 ???
    public boolean onCreateOptionsMenu(@NonNull final Menu menu) {
        super.onCreateOptionsMenu(menu);
        if (getMenuId() > 0 && getOwnerActivity() != null) {
            getOwnerActivity().getMenuInflater().inflate(getMenuId(), menu);
            return true;
        }
        return false;
    }

    @Override
    public void setOnDismissListener(@Nullable final OnDismissListener listener) {
        mRealDismissListener = listener;
    }

    /**
     * A local dismiss listener proxy that also clears up the parsed Views collection.
     */
    private final OnDismissListener mOnDismissListenerProxy = new OnDismissListener() {
        @Override
        public void onDismiss(final DialogInterface dialog) {
            if (mFoundViews != null) {
                mFoundViews.clear();
            }
            final OnDismissListener realListener = mRealDismissListener;
            if (realListener != null) {
                realListener.onDismiss(dialog);
            }
            setOnDismissListener(null);
        }
    };

    /**
     * {@inheritDoc}
     */
    @Override
    public void onClick(final View v) {}

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean onLongClick(final View v) {
        return false;
    }

    /**
     * Tries to find a {@link Annotations.FindView}-annotated View from the {@link #mFoundViews} cache. Note that cache is emptied when this dialog dies.
     *
     * @param viewId The ID of the View being looked for
     * @return Either a View object; or {@code null} if not found, not parsed at all or dialog died already
     */
    @Nullable
    @SuppressWarnings("unused")
    protected final View getFoundView(@IdRes final int viewId) {
        return mFoundViews == null ? null : mFoundViews.get(viewId);
    }

    /**
     * Returns the currently assigned layout's ID. This usually comes from {@link me.angrybyte.sillyandroid.parsable.Annotations.Layout}.
     */
    @LayoutRes
    protected final int getLayoutId() {
        return mLayoutId;
    }

    /**
     * Returns the currently assigned menu's ID. This usually comes from {@link me.angrybyte.sillyandroid.parsable.Annotations.Menu}.
     */
    @MenuRes
    protected final int getMenuId() {
        return mMenuId;
    }

}