org.catrobat.catroid.ui.fragment.AddBrickFragment.java Source code

Java tutorial

Introduction

Here is the source code for org.catrobat.catroid.ui.fragment.AddBrickFragment.java

Source

/*
 * Catroid: An on-device visual programming system for Android devices
 * Copyright (C) 2010-2015 The Catrobat Team
 * (<http://developer.catrobat.org/credits>)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * An additional term exception under section 7 of the GNU Affero
 * General Public License, version 3, is available at
 * http://developer.catrobat.org/license_additional_term
 *
 * 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.catrobat.catroid.ui.fragment;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockListFragment;
import com.actionbarsherlock.view.ActionMode;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;

import org.catrobat.catroid.ProjectManager;
import org.catrobat.catroid.R;
import org.catrobat.catroid.content.Script;
import org.catrobat.catroid.content.Sprite;
import org.catrobat.catroid.content.bricks.Brick;
import org.catrobat.catroid.content.bricks.ScriptBrick;
import org.catrobat.catroid.content.bricks.UserBrick;
import org.catrobat.catroid.ui.BottomBar;
import org.catrobat.catroid.ui.DeleteModeListener;
import org.catrobat.catroid.ui.ScriptActivity;
import org.catrobat.catroid.ui.UserBrickScriptActivity;
import org.catrobat.catroid.ui.adapter.PrototypeBrickAdapter;
import org.catrobat.catroid.utils.ToastUtil;

import java.util.ArrayList;
import java.util.List;

public class AddBrickFragment extends SherlockListFragment
        implements DeleteModeListener, PrototypeBrickAdapter.OnBrickCheckedListener {

    private static final String BUNDLE_ARGUMENTS_SELECTED_CATEGORY = "selected_category";
    public static final String ADD_BRICK_FRAGMENT_TAG = "add_brick_fragment";
    private ScriptFragment scriptFragment;
    private CharSequence previousActionBarTitle;
    private PrototypeBrickAdapter adapter;
    private CategoryBricksFactory categoryBricksFactory = new CategoryBricksFactory();
    public static AddBrickFragment addButtonHandler = null;
    protected boolean actionModeActive = false;
    private static String actionModeTitle;

    private static String singleItemAppendixActionMode;
    private static String multipleItemAppendixActionMode;

    private ActionMode actionMode;

    private static UserBrick brickToFocus;
    private static int listIndexToFocus = -1;
    private boolean cameDirectlyFromScriptActivity = false;

    public static void setBrickFocus(UserBrick userBrick) {
        brickToFocus = userBrick;
    }

    public static AddBrickFragment newInstance(String selectedCategory, ScriptFragment scriptFragment) {
        AddBrickFragment fragment = new AddBrickFragment();
        Bundle arguments = new Bundle();
        arguments.putString(BUNDLE_ARGUMENTS_SELECTED_CATEGORY, selectedCategory);
        fragment.setArguments(arguments);
        fragment.scriptFragment = scriptFragment;
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_brick_add, container, false);

        setUpActionBar();
        setupSelectedBrickCategory();

        return view;
    }

    private void setupSelectedBrickCategory() {
        Context context = getActivity();
        Sprite sprite = ProjectManager.getInstance().getCurrentSprite();
        String selectedCategory = getArguments().getString(BUNDLE_ARGUMENTS_SELECTED_CATEGORY);

        List<Brick> brickList = categoryBricksFactory.getBricks(selectedCategory, sprite, context);
        adapter = new PrototypeBrickAdapter(context, brickList);
        adapter.setOnBrickCheckedListener(this);
        setListAdapter(adapter);

        if (selectedCategory.equals(getActivity().getString(R.string.category_user_bricks))) {
            addButtonHandler = this;

            ScriptActivity activity = (ScriptActivity) scriptFragment.getActivity();
            activity.setDeleteModeListener(this);

            if (brickToFocus != null) {
                cameDirectlyFromScriptActivity = true;
                int i = 0;
                for (Brick brick : brickList) {
                    UserBrick userBrick = ((UserBrick) brick);
                    if (brickToFocus.isInstanceOf(userBrick)) {

                        listIndexToFocus = i;
                        animateBrick(userBrick, adapter);

                        brickToFocus = null;
                        break;
                    }
                    i++;
                }
            }

            BottomBar.showBottomBar(getActivity());
            BottomBar.hidePlayButton(getActivity());
        }
    }

    private void animateBrick(final Brick brick, PrototypeBrickAdapter adapter) {
        Context context = getActivity();
        Animation animation = AnimationUtils.loadAnimation(context, R.anim.blink);

        animation.setAnimationListener(new AnimationListener() {

            @Override
            public void onAnimationStart(Animation animation) {
                brick.setAnimationState(true);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                brick.setAnimationState(false);
            }
        });

        View view = brick.getView(context, 0, adapter);

        view.startAnimation(animation);
    }

    public void handleAddButton() {
        Sprite currentSprite = ProjectManager.getInstance().getCurrentSprite();
        int newBrickId = ProjectManager.getInstance().getCurrentSprite().getUserBrickList().size();
        UserBrick newBrick = new UserBrick(newBrickId);
        ProjectManager.getInstance().setCurrentUserBrick(newBrick);
        currentSprite.addUserBrick(newBrick);
        newBrick.getDefinitionBrick().addUIText(
                scriptFragment.getString(R.string.new_user_brick) + " " + currentSprite.getNextNewUserBrickId());
        newBrick.getDefinitionBrick().addVariableWithId(getActivity(), R.string.new_user_brick_variable);

        setupSelectedBrickCategory();

        getListView().setSelection(getListView().getCount());
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    private void setUpActionBar() {
        ActionBar actionBar = getSherlockActivity().getSupportActionBar();
        actionBar.setDisplayShowTitleEnabled(true);
        previousActionBarTitle = actionBar.getTitle();
        actionBar.setTitle(this.getArguments().getString(BUNDLE_ARGUMENTS_SELECTED_CATEGORY));
    }

    private void resetActionBar() {
        ActionBar actionBar = getSherlockActivity().getSupportActionBar();
        actionBar.setTitle(previousActionBarTitle);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        String selectedCategory = getArguments().getString(BUNDLE_ARGUMENTS_SELECTED_CATEGORY);
        if (selectedCategory.equals(getActivity().getString(R.string.category_user_bricks))) {
            menu.findItem(R.id.delete).setVisible(true);
        }
        menu.findItem(R.id.copy).setVisible(false);
        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public void onDestroy() {
        resetActionBar();
        addButtonHandler = null;

        if (cameDirectlyFromScriptActivity) {
            BottomBar.showBottomBar(getActivity());
            BottomBar.showPlayButton(getActivity());
        } else {
            BottomBar.hideBottomBar(getActivity());
        }

        ScriptActivity activity = (ScriptActivity) scriptFragment.getActivity();
        if (activity != null) {
            activity.setDeleteModeListener(null);
        }
        super.onDestroy();
    }

    @Override
    public void onPause() {
        super.onPause();
        addButtonHandler = null;
        ScriptActivity activity = (ScriptActivity) scriptFragment.getActivity();
        activity.setDeleteModeListener(null);
    }

    @Override
    public void onResume() {
        super.onResume();
        setupSelectedBrickCategory();
        addButtonHandler = this;

        ScriptActivity activity = (ScriptActivity) scriptFragment.getActivity();
        activity.setDeleteModeListener(this);
    }

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

        if (listIndexToFocus != -1) {
            getListView().setSelection(listIndexToFocus);
            listIndexToFocus = -1;
        }

        getListView().setOnItemClickListener(new ListView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Brick brickToBeAdded = null;
                try {
                    brickToBeAdded = adapter.getItem(position).clone();
                } catch (CloneNotSupportedException cloneNotSupportedException) {
                    Log.e(getTag(), "CloneNotSupportedException!", cloneNotSupportedException);
                }
                if (brickToBeAdded instanceof UserBrick) {
                    clickedOnUserBrick(((UserBrick) brickToBeAdded), view);
                    BottomBar.showBottomBar(getActivity());
                } else {
                    addBrickToScript(brickToBeAdded);
                }
            }
        });
    }

    private void clickedOnUserBrick(final UserBrick clickedBrick, View view) {
        final Context context = getActivity();

        final List<CharSequence> items = new ArrayList<CharSequence>();

        items.add(context.getText(R.string.brick_context_dialog_add_to_script));

        items.add(context.getText(R.string.brick_context_dialog_edit_brick));

        AlertDialog.Builder builder = new AlertDialog.Builder(context);

        boolean drawingCacheEnabled = view.isDrawingCacheEnabled();
        view.setDrawingCacheEnabled(true);
        view.setDrawingCacheBackgroundColor(Color.TRANSPARENT);
        view.buildDrawingCache(true);

        if (view.getDrawingCache() != null) {
            Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
            view.setDrawingCacheEnabled(drawingCacheEnabled);

            ImageView imageView = getGlowingBorder(bitmap);
            builder.setCustomTitle(imageView);
        }

        builder.setItems(items.toArray(new CharSequence[items.size()]), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int item) {
                CharSequence clickedItemText = items.get(item);
                if (clickedItemText.equals(context.getText(R.string.brick_context_dialog_add_to_script))) {
                    addBrickToScript(clickedBrick);
                } else if (clickedItemText.equals(context.getText(R.string.brick_context_dialog_edit_brick))) {
                    launchBrickScriptActivityOnBrick(context, clickedBrick);
                }
            }
        });
        AlertDialog alertDialog = builder.create();
        alertDialog.show();
    }

    public void addBrickToScript(Brick brickToBeAdded) {
        try {
            scriptFragment.updateAdapterAfterAddNewBrick(brickToBeAdded.clone());

            if (brickToBeAdded instanceof ScriptBrick) {
                Script script = ((ScriptBrick) brickToBeAdded).getScriptSafe();
                ProjectManager.getInstance().setCurrentScript(script);
            }

            FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
            Fragment categoryFragment = getFragmentManager()
                    .findFragmentByTag(BrickCategoryFragment.BRICK_CATEGORY_FRAGMENT_TAG);
            if (categoryFragment != null) {
                fragmentTransaction.remove(categoryFragment);
                getFragmentManager().popBackStack();
            }
            Fragment addBrickFragment = getFragmentManager()
                    .findFragmentByTag(AddBrickFragment.ADD_BRICK_FRAGMENT_TAG);
            if (addBrickFragment != null) {
                fragmentTransaction.remove(addBrickFragment);
                getFragmentManager().popBackStack();
            }
            fragmentTransaction.commit();
        } catch (CloneNotSupportedException exception) {
            Log.e(getTag(), "Adding a Brick was not possible because cloning it from the preview failed",
                    exception);
            ToastUtil.showError(getActivity(), R.string.error_adding_brick);
        }
    }

    @Override
    public void startDeleteActionMode() {
        if (actionMode == null) {
            actionMode = getSherlockActivity().startActionMode(deleteModeCallBack);

            unregisterForContextMenu(this.getListView());
            BottomBar.hideBottomBar(getActivity());
            adapter.setCheckboxVisibility(View.VISIBLE);
        }
    }

    private ActionMode.Callback deleteModeCallBack = new ActionMode.Callback() {

        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            return false;
        }

        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            setSelectMode(ListView.CHOICE_MODE_MULTIPLE);
            actionModeActive = true;

            actionModeTitle = getString(R.string.delete);
            singleItemAppendixActionMode = getString(R.string.brick_single);
            multipleItemAppendixActionMode = getString(R.string.brick_multiple);

            mode.setTitle(actionModeTitle);

            return true;
        }

        @Override
        public boolean onActionItemClicked(ActionMode mode, com.actionbarsherlock.view.MenuItem item) {
            return false;
        }

        @Override
        public void onDestroyActionMode(ActionMode mode) {

            if (adapter.getAmountOfCheckedItems() == 0) {
                clearCheckedBricksAndEnableButtons();
            } else {
                showConfirmDeleteDialog();
            }
        }
    };

    public void setSelectMode(int selectMode) {
        adapter.notifyDataSetChanged();
    }

    private void deleteBrick(Brick brick) {
        int brickId = adapter.getBrickList().indexOf(brick);
        if (brickId != -1) {
            adapter.removeUserBrick(brick);
            ScriptFragment scriptFragment = (ScriptFragment) getFragmentManager()
                    .findFragmentByTag(ScriptFragment.TAG);
            scriptFragment.getAdapter().updateProjectBrickList();
        }
    }

    private void deleteCheckedBricks() {
        List<Brick> checkedBricks = adapter.getReversedCheckedBrickList();

        for (Brick brick : checkedBricks) {
            deleteBrick(brick);
        }
    }

    private void showConfirmDeleteDialog() {
        String yes = getActivity().getString(R.string.yes);
        String no = getActivity().getString(R.string.no);
        String title = "";
        if (adapter.getAmountOfCheckedItems() == 1) {
            title = getActivity().getString(R.string.dialog_confirm_delete_brick_title);
        } else {
            title = getActivity().getString(R.string.dialog_confirm_delete_multiple_bricks_title);
        }

        String message = getActivity().getString(R.string.dialog_confirm_delete_brick_message);

        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setTitle(title);
        builder.setMessage(message);
        builder.setPositiveButton(yes, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int id) {
                deleteCheckedBricks();
                clearCheckedBricksAndEnableButtons();
            }
        });
        builder.setNegativeButton(no, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int id) {
                dialog.cancel();
                clearCheckedBricksAndEnableButtons();
            }
        });

        AlertDialog alertDialog = builder.create();
        alertDialog.show();
    }

    private void clearCheckedBricksAndEnableButtons() {
        setSelectMode(ListView.CHOICE_MODE_NONE);
        adapter.clearCheckedItems();

        actionMode = null;
        actionModeActive = false;

        registerForContextMenu(getListView());
        BottomBar.showBottomBar(getActivity());
    }

    public void onBrickChecked() {
        if (actionMode == null) {
            return;
        }

        int numberOfSelectedItems = adapter.getAmountOfCheckedItems();

        if (numberOfSelectedItems == 0) {
            actionMode.setTitle(actionModeTitle);
        } else {
            String appendix = multipleItemAppendixActionMode;

            if (numberOfSelectedItems == 1) {
                appendix = singleItemAppendixActionMode;
            }

            String numberOfItems = Integer.toString(numberOfSelectedItems);
            String completeTitle = actionModeTitle + " " + numberOfItems + " " + appendix;

            int titleLength = actionModeTitle.length();

            Spannable completeSpannedTitle = new SpannableString(completeTitle);
            completeSpannedTitle.setSpan(
                    new ForegroundColorSpan(getResources().getColor(R.color.actionbar_title_color)),
                    titleLength + 1, titleLength + (1 + numberOfItems.length()),
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

            actionMode.setTitle(completeSpannedTitle);
        }
    }

    public void launchBrickScriptActivityOnBrick(Context context, Brick brick) {
        Intent intent = new Intent(context, UserBrickScriptActivity.class);
        UserBrickScriptActivity.setUserBrick(brick);
        UserBrick userBrick = (UserBrick) brick;
        userBrick.getDefinitionBrick().setUserBrick(userBrick);
        context.startActivity(intent);
    }

    public ImageView getGlowingBorder(Bitmap bitmap) {
        ImageView imageView = new ImageView(getActivity());
        imageView.setBackgroundColor(Color.TRANSPARENT);
        imageView.setId(R.id.drag_and_drop_list_view_image_view);

        Bitmap glowingBitmap = Bitmap.createBitmap(bitmap.getWidth() + 30, bitmap.getHeight() + 30,
                Bitmap.Config.ARGB_8888);
        Canvas glowingCanvas = new Canvas(glowingBitmap);
        Bitmap alpha = bitmap.extractAlpha();
        Paint paintBlur = new Paint();
        paintBlur.setColor(Color.WHITE);
        glowingCanvas.drawBitmap(alpha, 15, 15, paintBlur);
        BlurMaskFilter blurMaskFilter = new BlurMaskFilter(15.0f, BlurMaskFilter.Blur.OUTER);
        paintBlur.setMaskFilter(blurMaskFilter);
        glowingCanvas.drawBitmap(alpha, 15, 15, paintBlur);
        paintBlur.setMaskFilter(null);
        glowingCanvas.drawBitmap(bitmap, 15, 15, paintBlur);

        imageView.setImageBitmap(glowingBitmap);

        return imageView;
    }
}