com.github.michalbednarski.intentslab.editor.NewExtraPickerDialog.java Source code

Java tutorial

Introduction

Here is the source code for com.github.michalbednarski.intentslab.editor.NewExtraPickerDialog.java

Source

/*
 * IntentsLab - Android app for playing with Intents and Binder IPC
 * Copyright (C) 2014 Micha Bednarski
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.github.michalbednarski.intentslab.editor;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.github.michalbednarski.intentslab.R;
import com.github.michalbednarski.intentslab.Utils;

/**
 * Created by mb on 21.08.13.
 */
public class NewExtraPickerDialog extends DialogFragment implements AdapterView.OnItemClickListener {

    /**
     * Default constructor, required and should by only used by framework
     */
    public NewExtraPickerDialog() {
    }

    /**
     * Constructor for use in BundleAdapter
     */
    NewExtraPickerDialog(IntentExtrasFragment intentExtrasFragment) {
        setTargetFragment(intentExtrasFragment, 0);
    }

    /**
     * Check if we're in IntentEditorActivity and if yes check if we are insterested in it's intent
     *
     * @return true if BundleAdapter should use this dialog, false to redirect it to {@link NewBundleEntryDialog}
     */
    public static boolean mayHaveSomethingForIntent(Activity activity) {
        if (!(activity instanceof IntentEditorActivity)) {
            return false;
        }
        final IntentEditorActivity intentEditor = ((IntentEditorActivity) activity);
        intentEditor.updateIntent();
        final Intent editedIntent = intentEditor.getEditedIntent();
        return !Utils.stringEmptyOrNull(editedIntent.getAction()) /*|| editedIntent.getComponent() != null*/;
    }

    /**
     * Get BundleAdapter this fragment is associated with, may change on configuration change
     * if instance is retained
     */
    private BundleAdapter getBundleAdapter() {
        return ((IntentExtrasFragment) getTargetFragment()).getBundleAdapter();
    }

    /**
     * Task for filling {@link #mSuggestionsByAction}
     */
    private NewExtraSuggesterByAction mFetchSuggestionsByActionTask = null;

    /**
     * Array of options under "By action" heading
     */
    private ExtraSuggestion[] mSuggestionsByAction = null;

    /**
     * Reserved for future use
     */
    private ExtraSuggestion[] mSuggestionsByClass = null;

    /**
     * Adapter for list in dialog
     */
    private BaseAdapter mAdapter = new BaseAdapter() {

        @Override
        public int getCount() {
            return 1 + (mSuggestionsByAction != null ? mSuggestionsByAction.length + 1 : 0)
                    + (mSuggestionsByClass != null ? mSuggestionsByClass.length + 1 : 0);
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            if (position == 0) {
                return 0;
            }
            position -= 1;
            if (mSuggestionsByAction != null) {
                if (position <= mSuggestionsByAction.length) {
                    return position + 100;
                }
                position -= mSuggestionsByAction.length + 1;
            }
            return position + 1000;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            int dummy_import = R.layout.xml_viewer; // TODO: remove
            long id = getItemId(position);
            if (id == 100 || id == 1000) {
                if (convertView == null) {
                    convertView = getActivity().getLayoutInflater().inflate(android.R.layout.preference_category,
                            parent, false);
                }
                ((TextView) convertView).setText(id == 100 ? "By action" : "By scanned class");

            } else {
                if (convertView == null) {
                    convertView = getActivity().getLayoutInflater().inflate(android.R.layout.simple_list_item_1,
                            parent, false);
                }
                String text = "Other...";
                if (id > 1000) {
                    text = mSuggestionsByClass[((int) (id - 1001))].name;
                } else if (id > 100) {
                    text = mSuggestionsByAction[((int) (id - 101))].name;
                }
                ((TextView) convertView).setText(text);
            }
            return convertView;
        }

        @Override
        public int getItemViewType(int position) {
            long id = getItemId(position);
            return (id == 100 || id == 1000) ? 1 : 0;
        }

        @Override
        public int getViewTypeCount() {
            return 2;
        }

        @Override
        public boolean areAllItemsEnabled() {
            return false;
        }

        @Override
        public boolean isEnabled(int position) {
            long id = getItemId(position);
            return id != 100 && id != 1000;
        }
    };

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        // "Other" option
        if (id == 0) {
            jumpToNewBundleEntryDialog(null);
            return;
        }

        // Get ExtraSuggestion
        ExtraSuggestion extraSuggestion = id > 1000 ? mSuggestionsByClass[((int) (id - 1001))]
                : mSuggestionsByAction[((int) (id - 101))];

        String type = extraSuggestion.type;

        // Ask user if type is unknown
        if (type == null) {
            jumpToNewBundleEntryDialog(extraSuggestion.name);
        }

        // Auto-expand "java/lang/"
        if (type.indexOf('.') == -1) {
            type = "java.lang." + type;
        }

        // For boolean we just set them to true
        if (type.equals("java.lang.Boolean")) {
            getBundleAdapter().onEditorResult(extraSuggestion.name, true);
            dismiss();
            return;
        }

        // Instantiate new object and pass it to editor
        final Object initialValue;
        try {
            Class c = Class.forName(type);
            initialValue = c.newInstance();
        } catch (ClassNotFoundException e) {
            Utils.toastException(getActivity(), "Class.forName", e);
            return;
        } catch (java.lang.InstantiationException e) {
            Utils.toastException(getActivity(), "aClass.newInstance", e);
            return;
        } catch (IllegalAccessException e) {
            Utils.toastException(getActivity(), "aClass.newInstance", e);
            return;
        }
        dismiss();
        getBundleAdapter().launchEditorForNewEntry(extraSuggestion.name, initialValue);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
        IntentEditorActivity intentEditor = (IntentEditorActivity) getActivity();
        intentEditor.updateIntent();
        final Intent editedIntent = intentEditor.getEditedIntent();
        String action = editedIntent.getAction();
        if (!Utils.stringEmptyOrNull(action)) {
            mFetchSuggestionsByActionTask = new NewExtraSuggesterByAction(intentEditor, action, false, this);
            mFetchSuggestionsByActionTask.execute();
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        ListView listView = new ListView(getActivity());
        listView.setAdapter(mAdapter);
        listView.setOnItemClickListener(this);
        Utils.fixListViewInDialogBackground(listView);
        return listView;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();

        try {
            // Work around dismiss on rotation after setRetainInstance(true)
            // http://stackoverflow.com/a/13596466
            getDialog().setOnDismissListener(null);
        } catch (Exception ignored) {
        }
    }

    @Override
    public void onDestroy() {
        if (mFetchSuggestionsByActionTask != null) {
            mFetchSuggestionsByActionTask.cancel(true);
        }
        super.onDestroy();
    }

    public static class ExtraSuggestion {
        String name;
        String type;
    }

    void onExtrasByActionReceived(ExtraSuggestion[] suggestions) {
        mFetchSuggestionsByActionTask = null;
        if (suggestions != null && suggestions.length == 0) {
            suggestions = null;
        }
        if (suggestions != mSuggestionsByAction) {
            mSuggestionsByAction = suggestions;
            mAdapter.notifyDataSetChanged();
        }
        skipSuggestionDialogIfNotNeeded();
    }

    void onExtrasByClassReceived(ExtraSuggestion[] suggestions) { // TODO
        if (suggestions != null && suggestions.length == 0) {
            suggestions = null;
        }
        if (suggestions != mSuggestionsByClass) {
            mSuggestionsByClass = suggestions;
            mAdapter.notifyDataSetChanged();
        }
        skipSuggestionDialogIfNotNeeded();
    }

    /**
     * Check if we have no data nor we are not loading some and if so replace ourselves with {@link NewBundleEntryDialog}
     */
    private void skipSuggestionDialogIfNotNeeded() {
        if (mSuggestionsByAction == null && mFetchSuggestionsByActionTask == null && mSuggestionsByClass == null) {
            jumpToNewBundleEntryDialog(null);
        }
    }

    /**
     * Replace this dialog with {@link NewBundleEntryDialog}
     */
    private void jumpToNewBundleEntryDialog(String defaultName) {
        dismiss();
        NewBundleEntryDialog newBundleEntryDialog = new NewBundleEntryDialog(getTargetFragment());
        if (defaultName != null) {
            Bundle arguments = new Bundle();
            arguments.putString(NewBundleEntryDialog.ARG_DEFAULT_NAME, defaultName);
            newBundleEntryDialog.setArguments(arguments);
        }
        newBundleEntryDialog.show(getFragmentManager(), "newBundleEntryFallback");
    }
}