/* * Catroid: An on-device visual programming system for Android devices * Copyright (C) 2010-2016 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.app.Fragment; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.os.Bundle; import android.preference.PreferenceManager; import android.text.Editable; import android.text.Spannable; import android.text.SpannableString; import android.text.TextWatcher; import android.text.style.ForegroundColorSpan; import android.util.Log; import android.view.ActionMode; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import org.catrobat.catroid.ProjectManager; import org.catrobat.catroid.R; import org.catrobat.catroid.common.LookData; import org.catrobat.catroid.common.SoundInfo; import org.catrobat.catroid.content.GroupItemSprite; import org.catrobat.catroid.content.GroupSprite; import org.catrobat.catroid.content.Scene; import org.catrobat.catroid.content.SingleSprite; import org.catrobat.catroid.content.Sprite; import org.catrobat.catroid.formulaeditor.DataContainer; import org.catrobat.catroid.io.StorageHandler; import org.catrobat.catroid.ui.BackPackActivity; import org.catrobat.catroid.ui.BottomBar; import org.catrobat.catroid.ui.CapitalizedTextView; import org.catrobat.catroid.ui.ProgramMenuActivity; import org.catrobat.catroid.ui.ProjectActivity; import org.catrobat.catroid.ui.ScriptActivity; import org.catrobat.catroid.ui.adapter.SpriteAdapter; import org.catrobat.catroid.ui.controller.BackPackListManager; import org.catrobat.catroid.ui.controller.BackPackSpriteController; import org.catrobat.catroid.ui.dialogs.CustomAlertDialogBuilder; import org.catrobat.catroid.ui.dialogs.RenameSpriteDialog; import org.catrobat.catroid.ui.dynamiclistview.DynamicExpandableListView; import org.catrobat.catroid.utils.SnackbarUtil; import org.catrobat.catroid.utils.ToastUtil; import org.catrobat.catroid.utils.UtilUi; import org.catrobat.catroid.utils.Utils; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; public class SpritesListFragment extends Fragment implements SpriteAdapter.OnSpriteEditListener, BackPackSpriteController.OnBackpackSpriteCompleteListener, ListItemActionsInterface { public static final String TAG = SpritesListFragment.class.getSimpleName(); public static final String SHARED_PREFERENCE_NAME = "showDetailsProjects"; private static final String BUNDLE_ARGUMENTS_SPRITE_TO_EDIT = "sprite_to_edit"; private static String multiSelectActionModeTitle; private static String singleItemAppendixMultiSelectActionMode; private static String multipleItemAppendixMultiSelectActionMode; private SpriteAdapter spriteAdapter; private Sprite spriteToEdit; private SpriteRenamedReceiver spriteRenamedReceiver; private SpritesListChangedReceiver spritesListChangedReceiver; private SpritesListInitReceiver spritesListInitReceiver; private SpriteListTouchActionUpReceiver spriteListTouchActionUpReceiver; private ActionMode actionMode; private View selectAllActionModeButton; private boolean isRenameActionMode; private boolean isBackPackActionMode; private boolean isCopyActionMode; private boolean isDeleteActionMode; private boolean selectAll = true; private boolean actionModeActive = false; private Button okButton; private DynamicExpandableListView listView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); SnackbarUtil.showHintSnackbar(getActivity(), R.string.hint_objects); return inflater.inflate(R.layout.fragment_sprites_list, container, false); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); listView = (DynamicExpandableListView) getActivity().findViewById(R.id.fragment_sprites_list_listview); listView.setAdapter(spriteAdapter); listView.getUtilDynamicListView().setSpritesListFragment(this); registerForContextMenu(getListView()); if (savedInstanceState != null) { spriteToEdit = (Sprite) savedInstanceState.get(BUNDLE_ARGUMENTS_SPRITE_TO_EDIT); } } @Override public void onSaveInstanceState(Bundle outState) { outState.putSerializable(BUNDLE_ARGUMENTS_SPRITE_TO_EDIT, spriteToEdit); super.onSaveInstanceState(outState); } @Override public void onStart() { super.onStart(); initListeners(); } @Override public void onResume() { super.onResume(); if (ProjectManager.getInstance().getCurrentProject().isScenesEnabled()) { getActivity().getActionBar().setTitle(ProjectManager.getInstance().getCurrentScene().getName()); } else { getActivity().getActionBar().setTitle(ProjectManager.getInstance().getCurrentProject().getName()); } if (actionMode != null) { actionMode.finish(); actionMode = null; } if (!Utils.checkForExternalStorageAvailableAndDisplayErrorIfNot(getActivity())) { return; } if (BackPackListManager.getInstance().isBackpackEmpty()) { BackPackListManager.getInstance().loadBackpack(); } if (spriteRenamedReceiver == null) { spriteRenamedReceiver = new SpriteRenamedReceiver(); } if (spritesListChangedReceiver == null) { spritesListChangedReceiver = new SpritesListChangedReceiver(); } if (spritesListInitReceiver == null) { spritesListInitReceiver = new SpritesListInitReceiver(); } if (spriteListTouchActionUpReceiver == null) { spriteListTouchActionUpReceiver = new SpriteListTouchActionUpReceiver(); } IntentFilter intentFilterSpriteRenamed = new IntentFilter(ScriptActivity.ACTION_SPRITE_RENAMED); getActivity().registerReceiver(spriteRenamedReceiver, intentFilterSpriteRenamed); IntentFilter intentFilterSpriteListChanged = new IntentFilter(ScriptActivity.ACTION_SPRITES_LIST_CHANGED); getActivity().registerReceiver(spritesListChangedReceiver, intentFilterSpriteListChanged); IntentFilter intentFilterSpriteListInit = new IntentFilter(ScriptActivity.ACTION_SPRITES_LIST_INIT); getActivity().registerReceiver(spritesListInitReceiver, intentFilterSpriteListInit); IntentFilter intentFilterSpriteListTouchActionUp = new IntentFilter(ScriptActivity .ACTION_SPRITE_TOUCH_ACTION_UP); getActivity().registerReceiver(spriteListTouchActionUpReceiver, intentFilterSpriteListTouchActionUp); SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getActivity() .getApplicationContext()); setShowDetails(settings.getBoolean(SHARED_PREFERENCE_NAME, false)); reExpandAllGroups(); } private void reExpandAllGroups() { for (int groupPosition : spriteAdapter.getGroupSpritePositions()) { Sprite sprite = (Sprite) spriteAdapter.getGroup(groupPosition); if (!listView.isGroupExpanded(groupPosition) && sprite instanceof GroupSprite && ((GroupSprite) sprite).shouldBeExpanded()) { listView.expandGroup(groupPosition); } } } @Override public void onPause() { super.onPause(); ProjectManager projectManager = ProjectManager.getInstance(); if (projectManager.getCurrentProject() != null) { projectManager.saveProject(getActivity().getApplicationContext()); } if (spriteRenamedReceiver != null) { getActivity().unregisterReceiver(spriteRenamedReceiver); } if (spritesListChangedReceiver != null) { getActivity().unregisterReceiver(spritesListChangedReceiver); } if (spritesListInitReceiver != null) { getActivity().unregisterReceiver(spritesListInitReceiver); } if (spriteListTouchActionUpReceiver != null) { getActivity().unregisterReceiver(spriteListTouchActionUpReceiver); } SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getActivity() .getApplicationContext()); SharedPreferences.Editor editor = settings.edit(); editor.putBoolean(SHARED_PREFERENCE_NAME, getShowDetails()); editor.commit(); } public void switchToBackPack() { Intent intent = new Intent(getActivity(), BackPackActivity.class); intent.putExtra(BackPackActivity.EXTRA_FRAGMENT_POSITION, BackPackActivity.FRAGMENT_BACKPACK_SPRITES); startActivity(intent); } @Override public void onSpriteChecked() { if (isRenameActionMode || actionMode == null) { return; } updateActionModeTitle(); updateSelectAllView(); } private void updateSelectAllView() { CapitalizedTextView selectAllView = (CapitalizedTextView) selectAllActionModeButton.findViewById(R.id.select_all); Scene scene = ProjectManager.getInstance().getCurrentScene(); int numberOfNonGroupItems = scene.getSpriteList().size() - spriteAdapter.getNumberOfGroups(); int numberOfCheckedItems = spriteAdapter.getCheckedItems().size(); if ((isBackPackActionMode && numberOfCheckedItems < numberOfNonGroupItems) || (!isBackPackActionMode && numberOfCheckedItems < (numberOfNonGroupItems - 1))) { selectAll = true; selectAllView.setVisibility(View.VISIBLE); selectAllView.setText(R.string.select_all); } else if (numberOfCheckedItems > 0) { selectAll = false; selectAllView.setVisibility(View.VISIBLE); selectAllView.setText(R.string.deselect_all); } } private void updateActionModeTitle() { int numberOfSelectedItems = spriteAdapter.getAmountOfCheckedItems(); if (numberOfSelectedItems == 0) { actionMode.setTitle(multiSelectActionModeTitle); } else { String appendix = multipleItemAppendixMultiSelectActionMode; if (numberOfSelectedItems == 1) { appendix = singleItemAppendixMultiSelectActionMode; } String numberOfItems = Integer.toString(numberOfSelectedItems); String completeTitle = multiSelectActionModeTitle + " " + numberOfItems + " " + appendix; int titleLength = multiSelectActionModeTitle.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); } } @Override public void onSpriteEdit(int groupPosition, int childPosition) { if (isRenameActionMode) { spriteToEdit = (Sprite) spriteAdapter.getChild(groupPosition, childPosition); showRenameDialog(); } else { Sprite currentSprite = (Sprite) spriteAdapter.getChild(groupPosition, childPosition); ProjectManager.getInstance().setCurrentSprite(currentSprite); Intent intent = new Intent(getActivity(), ProgramMenuActivity.class); startActivity(intent); } } @Override public void onSpriteEdit(int groupPosition) { if (isRenameActionMode) { spriteToEdit = (Sprite) spriteAdapter.getGroup(groupPosition); showRenameDialog(); } else { Sprite currentSprite = (Sprite) spriteAdapter.getGroup(groupPosition); ProjectManager.getInstance().setCurrentSprite(currentSprite); Intent intent = new Intent(getActivity(), ProgramMenuActivity.class); startActivity(intent); } } @Override public void startCopyActionMode() { startActionMode(copyModeCallBack, false, false); } @Override public void startRenameActionMode() { startActionMode(renameModeCallBack, true, false); } @Override public void startDeleteActionMode() { startActionMode(deleteModeCallBack, false, false); } @Override public void startBackPackActionMode() { startActionMode(backPackModeCallBack, false, true); } private void startActionMode(ActionMode.Callback actionModeCallback, boolean isRenameMode, boolean isBackPackMode) { if (actionMode == null) { List<Sprite> spriteList = ProjectManager.getInstance().getCurrentScene().getSpriteList(); if (spriteList.size() == 1 && !actionModeCallback.equals(backPackModeCallBack)) { if (actionModeCallback.equals(copyModeCallBack)) { ((ProjectActivity) getActivity()).showEmptyActionModeDialog(getString(R.string.copy)); } else if (actionModeCallback.equals(deleteModeCallBack)) { ((ProjectActivity) getActivity()).showEmptyActionModeDialog(getString(R.string.delete)); } else if (actionModeCallback.equals(renameModeCallBack)) { ((ProjectActivity) getActivity()).showEmptyActionModeDialog(getString(R.string.rename)); } } else { expandAllGroups(); actionMode = getActivity().startActionMode(actionModeCallback); BottomBar.hideBottomBar(getActivity()); isRenameActionMode = isRenameMode; isBackPackActionMode = isBackPackMode; } } } @Override public void handleAddButton() { //handled in ProjectActivity } public void copySprite() { spriteToEdit.setConvertToSingleSprite(true); Sprite copiedSprite = spriteToEdit.clone(); spriteToEdit.setConvertToSingleSprite(false); String oldName = copiedSprite.getName(); copiedSprite.setName(getSpriteName(spriteToEdit.getName().concat(getString(R.string.copy_sprite_name_suffix)), 0)); String newName = copiedSprite.getName(); copiedSprite.updateCollisionBroadcastMessages(oldName, newName); ProjectManager projectManager = ProjectManager.getInstance(); projectManager.addSprite(copiedSprite); projectManager.setCurrentSprite(copiedSprite); getActivity().sendBroadcast(new Intent(ScriptActivity.ACTION_SPRITES_LIST_CHANGED)); Log.d(TAG, copiedSprite.toString()); } @Override public void showRenameDialog() { RenameSpriteDialog dialog = new RenameSpriteDialog(R.string.rename_sprite_dialog, R.string.sprite_name, spriteToEdit.getName()); dialog.show(getFragmentManager(), RenameSpriteDialog.DIALOG_FRAGMENT_TAG); } @Override public void showDeleteDialog() { final Context context = getActivity(); final CharSequence deleteGroupSpriteOnly = context.getText(R.string.ungroup); final CharSequence deleteGroupAndSprites = context.getText(R.string.group_objects_delete); final List<CharSequence> items = new ArrayList<>(); items.add(deleteGroupSpriteOnly); items.add(deleteGroupAndSprites); String title = context.getText(R.string.delete).toString(); AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(title); builder.setItems(items.toArray(new CharSequence[items.size()]), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { CharSequence clickedItemText = items.get(which); if (clickedItemText.equals(deleteGroupSpriteOnly)) { deleteCheckedSprites(false); } else if (clickedItemText.equals(deleteGroupAndSprites)) { deleteCheckedSprites(true); } clearCheckedSpritesAndEnableButtons(); } }); builder.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { clearCheckedSpritesAndEnableButtons(); } }); AlertDialog alertDialog = builder.create(); alertDialog.show(); } private void deleteCheckedSprites(boolean deleteGroupItemSprites) { int numDeleted = 0; for (int position : spriteAdapter.getCheckedItems()) { spriteToEdit = getSpriteList().get(position - numDeleted); if (spriteToEdit instanceof GroupSprite) { if (!deleteGroupItemSprites) { convertGroupItemsToSingleSprites(position - numDeleted); } else { numDeleted += spriteAdapter.getChildrenCount(spriteToEdit); } deleteGroup(deleteGroupItemSprites); numDeleted++; } else { deleteSprite(); numDeleted++; } } } private void deleteGroup(boolean deleteSprites) { int numberOfGroupItemSprites = 0; int indexOfGroupSprite = getSpriteList().indexOf(spriteToEdit); for (int groupItemPosition = indexOfGroupSprite + 1; groupItemPosition < getSpriteList().size(); groupItemPosition++) { Sprite currentSprite = getSpriteList().get(groupItemPosition); if (currentSprite instanceof GroupItemSprite) { numberOfGroupItemSprites++; } else { break; } } for (int groupItemPosition = indexOfGroupSprite + numberOfGroupItemSprites; groupItemPosition > indexOfGroupSprite; groupItemPosition--) { spriteToEdit = getSpriteList().get(groupItemPosition); if (deleteSprites) { deleteSprite(); } else { spriteToEdit.setConvertToSingleSprite(true); SingleSprite clonedSprite = (SingleSprite) spriteToEdit.clone(); getSpriteList().add(groupItemPosition, clonedSprite); } } spriteToEdit = getSpriteList().get(indexOfGroupSprite); deleteSprite(); } private void showConfirmDeleteDialog() { int titleId; if (spriteAdapter.getAmountOfCheckedItems() == 1) { titleId = R.string.dialog_confirm_delete_object_title; } else { titleId = R.string.dialog_confirm_delete_multiple_objects_title; } AlertDialog.Builder builder = new CustomAlertDialogBuilder(getActivity()); builder.setTitle(titleId); builder.setMessage(R.string.dialog_confirm_delete_object_message); builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { if (isGroupWithoutGroupItemsChecked()) { showDeleteDialog(); } else { deleteCheckedSprites(false); clearCheckedSpritesAndEnableButtons(); } } }); builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { dialog.cancel(); clearCheckedSpritesAndEnableButtons(); } }); builder.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { clearCheckedSpritesAndEnableButtons(); } }); AlertDialog alertDialog = builder.create(); alertDialog.show(); } private boolean isGroupWithoutGroupItemsChecked() { Set<Integer> checkedItems = spriteAdapter.getCheckedItems(); for (int position : checkedItems) { Sprite sprite = getSpriteList().get(position); if (sprite instanceof GroupSprite) { int childrenCount = spriteAdapter.getChildrenCount(sprite); boolean groupItemSpriteChecked = false; for (int childPosition = position + 1; childPosition < position + 1 + childrenCount; childPosition++) { if (checkedItems.contains(childPosition)) { groupItemSpriteChecked = true; } } if (childrenCount > 0 && !groupItemSpriteChecked) { return true; } } } return false; } public void deleteSprite() { ProjectManager projectManager = ProjectManager.getInstance(); DataContainer dataContainer = projectManager.getCurrentScene().getDataContainer(); for (LookData currentLookData : spriteToEdit.getLookDataList()) { currentLookData.getCollisionInformation().cancelCalculation(); } deleteSpriteFiles(); dataContainer.cleanVariableListForSprite(spriteToEdit); dataContainer.cleanUserListForSprite(spriteToEdit); if (projectManager.getCurrentSprite() != null && projectManager.getCurrentSprite().equals(spriteToEdit)) { projectManager.setCurrentSprite(null); } projectManager.getCurrentScene().getSpriteList().remove(spriteToEdit); } private void convertGroupItemsToSingleSprites(int groupPosition) { int childCount = spriteAdapter.getChildCountWithGroupSpriteIndex(groupPosition); for (int position = groupPosition + 1; position < groupPosition + 1 + childCount; position++) { getSpriteList().get(position).setConvertToSingleSprite(true); Sprite cloneSprite = getSpriteList().get(position).clone(); getSpriteList().remove(position); getSpriteList().add(position, cloneSprite); } } private void clearCheckedSpritesAndEnableButtons() { setSelectMode(ListView.CHOICE_MODE_NONE); spriteAdapter.clearCheckedItems(); actionMode = null; actionModeActive = false; BottomBar.showBottomBar(getActivity()); } @Override public int getSelectMode() { return spriteAdapter.getSelectMode(); } @Override public void setSelectMode(int selectMode) { spriteAdapter.setSelectMode(selectMode); spriteAdapter.notifyDataSetChanged(); } @Override public boolean getActionModeActive() { return actionModeActive; } @Override public void setActionModeActive(boolean actionModeActive) { this.actionModeActive = actionModeActive; } @Override public boolean getShowDetails() { return spriteAdapter.getShowDetails(); } @Override public void setShowDetails(boolean showDetails) { spriteAdapter.setShowDetails(showDetails); spriteAdapter.notifyDataSetChanged(); } public boolean shouldSpriteBeChecked(int flatPosition) { Sprite sprite = getSpriteList().get(flatPosition); if ((isBackPackActionMode && !(sprite instanceof GroupSprite)) || ((isCopyActionMode) && !(sprite instanceof GroupSprite) && flatPosition > 0) || ((isRenameActionMode) && flatPosition > 0) || ((isDeleteActionMode) && flatPosition > 0)) { return true; } return false; } private void addSelectAllActionModeButton(ActionMode mode, Menu menu) { selectAll = true; selectAllActionModeButton = UtilUi.addSelectAllActionModeButton(getActivity().getLayoutInflater(), mode, menu); selectAllActionModeButton.setOnClickListener(new OnClickListener() { CapitalizedTextView selectAllView = (CapitalizedTextView) selectAllActionModeButton.findViewById(R.id.select_all); @Override public void onClick(View view) { if (selectAll) { int startPosition = 1; if (isBackPackActionMode) { startPosition = 0; } while (startPosition < getSpriteList().size()) { if (shouldSpriteBeChecked(startPosition)) { spriteAdapter.addCheckedSprite(startPosition); } startPosition++; } spriteAdapter.notifyDataSetChanged(); onSpriteChecked(); selectAll = false; selectAllView.setText(R.string.deselect_all); } else { spriteAdapter.clearCheckedItems(); spriteAdapter.notifyDataSetChanged(); onSpriteChecked(); selectAll = true; selectAllView.setText(R.string.select_all); } } }); } private void expandAllGroups() { for (int groupPosition : spriteAdapter.getGroupSpritePositions()) { if (!listView.isGroupExpanded(groupPosition)) { listView.expandGroup(groupPosition); } } spriteAdapter.setExpandedIndicatorsForAllGroupSprites(true); } public void collapseAllGroups() { for (int groupPosition : spriteAdapter.getGroupSpritePositions()) { if (listView.isGroupExpanded(groupPosition)) { listView.collapseGroup(groupPosition); } } spriteAdapter.setExpandedIndicatorsForAllGroupSprites(false); } private class SpriteRenamedReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(ScriptActivity.ACTION_SPRITE_RENAMED)) { String newSpriteName = intent.getExtras().getString(RenameSpriteDialog.EXTRA_NEW_SPRITE_NAME); String oldSpriteName = spriteToEdit.getName(); spriteToEdit.rename(newSpriteName); spriteAdapter.replaceItemInIdMap(oldSpriteName, newSpriteName); } } } private class SpritesListChangedReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(ScriptActivity.ACTION_SPRITES_LIST_CHANGED)) { spriteAdapter.notifyDataSetChanged(); final ListView listView = getListView(); listView.post(new Runnable() { @Override public void run() { listView.setSelection(listView.getCount() - 1); } }); } } } private class SpritesListInitReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(ScriptActivity.ACTION_SPRITES_LIST_INIT)) { spriteAdapter.notifyDataSetChanged(); } } } private class SpriteListTouchActionUpReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(ScriptActivity.ACTION_SPRITE_TOUCH_ACTION_UP)) { getListView().notifyListItemTouchActionUp(); } } } 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; multiSelectActionModeTitle = getString(R.string.delete); singleItemAppendixMultiSelectActionMode = getString(R.string.sprite); multipleItemAppendixMultiSelectActionMode = getString(R.string.sprites); mode.setTitle(multiSelectActionModeTitle); addSelectAllActionModeButton(mode, menu); isDeleteActionMode = true; return true; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return false; } @Override public void onDestroyActionMode(ActionMode mode) { if (spriteAdapter.getAmountOfCheckedItems() == 0) { clearCheckedSpritesAndEnableButtons(); } else { showConfirmDeleteDialog(); } isDeleteActionMode = false; } }; private ActionMode.Callback renameModeCallBack = 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_SINGLE); mode.setTitle(R.string.rename); actionModeActive = true; isRenameActionMode = true; return true; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return false; } @Override public void onDestroyActionMode(ActionMode mode) { isRenameActionMode = false; Set<Integer> checkedSprites = spriteAdapter.getCheckedItems(); Iterator<Integer> iterator = checkedSprites.iterator(); if (iterator.hasNext()) { int position = iterator.next(); spriteToEdit = getSpriteList().get(position); showRenameDialog(); } clearCheckedSpritesAndEnableButtons(); } }; private ActionMode.Callback copyModeCallBack = 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; multiSelectActionModeTitle = getString(R.string.copy); singleItemAppendixMultiSelectActionMode = getString(R.string.sprite); multipleItemAppendixMultiSelectActionMode = getString(R.string.sprites); mode.setTitle(multiSelectActionModeTitle); addSelectAllActionModeButton(mode, menu); isCopyActionMode = true; return true; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return false; } @Override public void onDestroyActionMode(ActionMode mode) { for (int position : spriteAdapter.getCheckedItems()) { spriteToEdit = getSpriteList().get(position); copySprite(); } clearCheckedSpritesAndEnableButtons(); isCopyActionMode = false; } }; private ActionMode.Callback backPackModeCallBack = 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); setActionModeActive(true); multiSelectActionModeTitle = getString(R.string.backpack); singleItemAppendixMultiSelectActionMode = getString(R.string.sprite); multipleItemAppendixMultiSelectActionMode = getString(R.string.sprites); mode.setTitle(multiSelectActionModeTitle); addSelectAllActionModeButton(mode, menu); return true; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return false; } @Override public void onDestroyActionMode(ActionMode mode) { List<Sprite> spriteListToBackpack = new ArrayList<>(); for (Integer position : spriteAdapter.getCheckedItems()) { spriteToEdit = getSpriteList().get(position); spriteListToBackpack.add(spriteToEdit); } boolean spritesAlreadyInBackpack = BackPackSpriteController.getInstance().checkSpriteReplaceInBackpack(spriteListToBackpack); if (!spriteListToBackpack.isEmpty()) { if (!spritesAlreadyInBackpack) { for (Sprite spriteToBackpack : spriteListToBackpack) { BackPackSpriteController.getInstance().backpackVisibleSprite(spriteToBackpack); onBackpackSpriteComplete(true); } } else { BackPackSpriteController.getInstance().setOnBackpackSpriteCompleteListener(SpritesListFragment.this); BackPackSpriteController.getInstance().showBackPackReplaceDialog(spriteListToBackpack, getActivity()); } } else { clearCheckedSpritesAndEnableButtons(); } } }; @Override public void onBackpackSpriteComplete(boolean startBackpackActivity) { if (!spriteAdapter.getCheckedItems().isEmpty() && startBackpackActivity) { switchToBackPack(); } clearCheckedSpritesAndEnableButtons(); isBackPackActionMode = false; } private void initListeners() { List<Sprite> spriteList = ProjectManager.getInstance().getCurrentScene().getSpriteList(); getListView().setDataList(spriteList); getListView().isForSpriteList(); spriteAdapter = new SpriteAdapter(getActivity(), spriteList); spriteAdapter.setSpritesListFragment(this); spriteAdapter.setOnSpriteEditListener(this); listView.setAdapter(spriteAdapter); getListView().setTextFilterEnabled(true); getListView().setDivider(null); getListView().setDividerHeight(0); } private void deleteSpriteFiles() { for (LookData currentLookData : spriteToEdit.getLookDataList()) { StorageHandler.getInstance().deleteFile(currentLookData.getAbsolutePath(), false); } for (SoundInfo currentSoundInfo : spriteToEdit.getSoundList()) { StorageHandler.getInstance().deleteFile(currentSoundInfo.getAbsolutePath(), false); } } public boolean isBackPackActionMode() { return isBackPackActionMode; } public boolean isCopyActionMode() { return isCopyActionMode; } public boolean isDeleteActionMode() { return isDeleteActionMode; } private static String getSpriteName(String name, int nextNumber) { String newName; if (nextNumber == 0) { newName = name; } else { newName = name + nextNumber; } for (Sprite sprite : ProjectManager.getInstance().getCurrentScene().getSpriteList()) { if (sprite.getName().equals(newName)) { return getSpriteName(name, ++nextNumber); } } return newName; } public void showNewObjectGroupDialog() { AlertDialog.Builder builder = new CustomAlertDialogBuilder(getActivity()); builder.setTitle(R.string.new_group); View view = View.inflate(getActivity(), R.layout.new_group_dialog, null); builder.setView(view); final EditText groupNameEditText = (EditText) view.findViewById(R.id.new_group_dialog_group_name); int currentNumberOfGroups = spriteAdapter.getNumberOfGroups(); String text = getString(R.string.group) + " " + (currentNumberOfGroups + 1); groupNameEditText.setText(text); UtilUi.positionCursorForEditText(groupNameEditText); builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { String groupName = groupNameEditText.getText().toString().trim(); List<String> takenNames = spriteAdapter.getGroupNames(); takenNames.addAll(spriteAdapter.getNonGroupNames()); if (takenNames.contains(groupName)) { showNameForGroupAlreadyGivenDialog(); } else { createGroup(groupName); } } }); builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); AlertDialog alertDialog = builder.create(); groupNameEditText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence groupName, int start, int before, int count) { if (groupName.toString().trim().isEmpty()) { okButton.setEnabled(false); } else { okButton.setEnabled(true); } } @Override public void afterTextChanged(Editable s) { } }); alertDialog.setCanceledOnTouchOutside(false); alertDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); alertDialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); alertDialog.show(); okButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE); } private void showNameForGroupAlreadyGivenDialog() { AlertDialog.Builder builder = new CustomAlertDialogBuilder(getActivity()); builder.setTitle(R.string.new_group); View view = View.inflate(getActivity(), R.layout.new_group_name_given_dialog, null); builder.setView(view); builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { dialog.cancel(); showNewObjectGroupDialog(); } }); AlertDialog alertDialog = builder.create(); alertDialog.setCanceledOnTouchOutside(true); alertDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); alertDialog.show(); } private void createGroup(String groupName) { GroupSprite groupSprite = new GroupSprite(groupName); getSpriteList().add(groupSprite); spriteAdapter.notifyDataSetChanged(); ToastUtil.showSuccess(getActivity(), R.string.group_created); } public DynamicExpandableListView getListView() { return listView; } public SpriteAdapter getSpriteAdapter() { return spriteAdapter; } private List<Sprite> getSpriteList() { return spriteAdapter.getSpriteList(); } }