/*
* 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.dialogs;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import com.google.common.io.Files;
import org.catrobat.catroid.ProjectManager;
import org.catrobat.catroid.R;
import org.catrobat.catroid.common.Constants;
import org.catrobat.catroid.common.DroneVideoLookData;
import org.catrobat.catroid.common.LookData;
import org.catrobat.catroid.content.SingleSprite;
import org.catrobat.catroid.content.Sprite;
import org.catrobat.catroid.content.bricks.PointToBrick.SpinnerAdapterWrapper;
import org.catrobat.catroid.io.StorageHandler;
import org.catrobat.catroid.ui.ProgramMenuActivity;
import org.catrobat.catroid.ui.ScriptActivity;
import org.catrobat.catroid.ui.SettingsActivity;
import org.catrobat.catroid.ui.WebViewActivity;
import org.catrobat.catroid.ui.controller.LookController;
import org.catrobat.catroid.ui.fragment.SpriteFactory;
import org.catrobat.catroid.ui.fragment.SpritesListFragment;
import org.catrobat.catroid.utils.ImageEditing;
import org.catrobat.catroid.utils.UtilCamera;
import org.catrobat.catroid.utils.Utils;
import java.io.File;
import java.io.IOException;
public class NewSpriteDialog extends DialogFragment {
public static final String DIALOG_FRAGMENT_TAG = "dialog_new_sprite";
public static final String TAG = NewSpriteDialog.class.getSimpleName();
private static final int REQUEST_SELECT_IMAGE = 0;
private static final int REQUEST_CREATE_POCKET_PAINT_IMAGE = 1;
private static final int REQUEST_TAKE_PICTURE = 2;
private static final int REQUEST_MEDIA_LIBRARY = 3;
private static final int REQUEST_DRONE_VIDEO = 4;
private final ActionAfterFinished requestedAction;
private final DialogWizardStep wizardStep;
private Uri lookUri;
private File newLookFile;
private View dialogView;
private String newObjectName = null;
private SpinnerAdapterWrapper spinnerAdapter;
private boolean isDroneVideo = false;
private SpriteFactory spriteFactory = new SpriteFactory();
public NewSpriteDialog() {
this.requestedAction = ActionAfterFinished.NONE;
this.wizardStep = DialogWizardStep.STEP_1;
}
public NewSpriteDialog(SpinnerAdapterWrapper spinnerAdapter) {
this.requestedAction = ActionAfterFinished.ACTION_UPDATE_SPINNER;
this.spinnerAdapter = spinnerAdapter;
this.wizardStep = DialogWizardStep.STEP_1;
}
private NewSpriteDialog(DialogWizardStep wizardStep, Uri lookUri, String newObjectName,
ActionAfterFinished requestedAction, SpinnerAdapterWrapper spinnerAdapter, boolean isDroneVideo) {
this.requestedAction = requestedAction;
this.wizardStep = wizardStep;
this.lookUri = lookUri;
this.newObjectName = newObjectName;
this.spinnerAdapter = spinnerAdapter;
this.isDroneVideo = isDroneVideo;
}
NewSpriteDialog newInstance() {
NewSpriteDialog newSpriteDialog = new NewSpriteDialog();
Bundle arguments = new Bundle();
arguments.putInt(ActionAfterFinished.KEY, ActionAfterFinished.ACTION_FORWARD_TO_NEW_OBJECT.ordinal());
arguments.putInt(DialogWizardStep.KEY, DialogWizardStep.STEP_1.ordinal());
newSpriteDialog.setArguments(arguments);
return newSpriteDialog;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
dialogView = View.inflate(getActivity(), R.layout.dialog_new_object, null);
setupPaintroidButton(dialogView);
setupGalleryButton(dialogView);
setupCameraButton(dialogView);
setupMediaLibraryButton(dialogView);
if (SettingsActivity.isDroneSharedPreferenceEnabled(getActivity())) {
setupDroneVideoButton(dialogView);
}
AlertDialog dialog = null;
AlertDialog.Builder dialogBuilder = new CustomAlertDialogBuilder(getActivity()).setView(dialogView).setTitle(
R.string.new_sprite_dialog_title);
if (wizardStep == DialogWizardStep.STEP_1) {
dialog = createDialogStepOne(dialogBuilder);
} else if (wizardStep == DialogWizardStep.STEP_2) {
dialog = createDialogStepTwo(dialogBuilder);
}
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(final DialogInterface dialog) {
Button button = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (handleOkButton()) {
dialog.dismiss();
}
}
});
}
});
dialog.setCanceledOnTouchOutside(true);
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
return dialog;
}
private AlertDialog createDialogStepOne(AlertDialog.Builder dialogBuilder) {
AlertDialog dialog = dialogBuilder.create();
dialogView.findViewById(R.id.dialog_new_object_step_2_layout).setVisibility(View.GONE);
return dialog;
}
private AlertDialog createDialogStepTwo(AlertDialog.Builder dialogBuilder) {
AlertDialog dialog = dialogBuilder.setPositiveButton(R.string.ok, null)
.setNegativeButton(R.string.cancel, null).create();
dialogView.findViewById(R.id.dialog_new_object_step_1_layout).setVisibility(View.GONE);
dialogView.findViewById(R.id.dialog_new_object_second_row).setVisibility(View.GONE);
dialogView.findViewById(R.id.dialog_new_object_third_row).setVisibility(View.GONE);
ImageView imageView = (ImageView) dialogView.findViewById(R.id.dialog_new_object_look_preview);
if (newObjectName == null) {
newObjectName = getString(R.string.new_sprite_dialog_default_sprite_name);
}
newObjectName = Utils.getUniqueObjectName(newObjectName);
DisplayMetrics metrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
int[] imageDimensions = ImageEditing.getImageDimensions(lookUri.getPath());
while (metrics.widthPixels < imageDimensions[0] && metrics.heightPixels < imageDimensions[1]) {
imageDimensions[0] = imageDimensions[0] / 2;
imageDimensions[1] = imageDimensions[1] / 2;
}
Bitmap bitmap = ImageEditing.getScaledBitmapFromPath(lookUri.getPath(), imageDimensions[0],
imageDimensions[1], ImageEditing.ResizeType.STAY_IN_RECTANGLE_WITH_SAME_ASPECT_RATIO, true);
if (bitmap == null) {
this.dismiss();
Utils.showErrorDialog(getActivity(), R.string.error_load_image_special_chars);
}
imageView.setImageBitmap(bitmap);
EditText editTextNewObject = (EditText) dialogView.findViewById(R.id.dialog_new_object_name_edit_text);
editTextNewObject.setHint(newObjectName);
return dialog;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (lookUri == null) {
lookUri = UtilCamera.getDefaultLookFromCameraUri(getString(R.string.default_look_name));
}
isDroneVideo = false;
try {
switch (requestCode) {
case REQUEST_CREATE_POCKET_PAINT_IMAGE:
lookUri = Uri.parse(data.getExtras().getString(Constants.EXTRA_PICTURE_PATH_POCKET_PAINT));
break;
case REQUEST_SELECT_IMAGE:
lookUri = decodeUri(data.getData());
newObjectName = new File(lookUri.toString()).getName();
break;
case REQUEST_TAKE_PICTURE:
lookUri = UtilCamera.rotatePictureIfNecessary(lookUri, getString(R.string.default_look_name));
break;
case REQUEST_MEDIA_LIBRARY:
lookUri = Uri.parse(data.getStringExtra(WebViewActivity.MEDIA_FILE_PATH));
newObjectName = Files.getNameWithoutExtension(lookUri.toString());
break;
case REQUEST_DRONE_VIDEO:
isDroneVideo = true;
newObjectName = getString(R.string.add_look_drone_video);
break;
default:
return;
}
NewSpriteDialog dialog = new NewSpriteDialog(DialogWizardStep.STEP_2, lookUri, newObjectName,
requestedAction, spinnerAdapter, isDroneVideo);
dialog.show(getActivity().getFragmentManager(), NewSpriteDialog.DIALOG_FRAGMENT_TAG);
dismiss();
} catch (NullPointerException e) {
Utils.showErrorDialog(getActivity(), R.string.error_load_image);
Log.e(TAG, Log.getStackTraceString(e));
} catch (Exception e) {
Utils.showErrorDialog(getActivity(), R.string.error_load_image);
Log.e(TAG, Log.getStackTraceString(e));
}
} else {
dismiss();
}
}
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
if (spinnerAdapter != null) {
spinnerAdapter.updateSpinner();
}
}
private Uri decodeUri(Uri uri) throws NullPointerException {
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = getActivity().getContentResolver().query(uri, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndexOrThrow(filePathColumn[0]);
Uri decodedUri = Uri.parse(cursor.getString(columnIndex));
cursor.close();
return decodedUri;
}
private void setupPaintroidButton(View parentView) {
View paintroidButton = parentView.findViewById(R.id.dialog_new_object_paintroid);
final Intent intent = new Intent("android.intent.action.MAIN");
intent.setComponent(new ComponentName(Constants.POCKET_PAINT_PACKAGE_NAME,
Constants.POCKET_PAINT_INTENT_ACTIVITY_NAME));
paintroidButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (LookController.getInstance().checkIfPocketPaintIsInstalled(intent, getActivity())) {
Intent intent = new Intent("android.intent.action.MAIN");
intent.setComponent(new ComponentName(Constants.POCKET_PAINT_PACKAGE_NAME,
Constants.POCKET_PAINT_INTENT_ACTIVITY_NAME));
Bundle bundleForPocketPaint = new Bundle();
bundleForPocketPaint.putString(Constants.EXTRA_PICTURE_PATH_POCKET_PAINT, "");
bundleForPocketPaint.putString(Constants.EXTRA_PICTURE_NAME_POCKET_PAINT,
getString(R.string.default_look_name));
intent.putExtras(bundleForPocketPaint);
intent.putExtra(MediaStore.EXTRA_OUTPUT, lookUri);
intent.addCategory("android.intent.category.LAUNCHER");
startActivityForResult(intent, REQUEST_CREATE_POCKET_PAINT_IMAGE);
}
}
});
}
private void setupGalleryButton(View parentView) {
View galleryButton = parentView.findViewById(R.id.dialog_new_object_gallery);
galleryButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI);
intent.putExtra(MediaStore.EXTRA_OUTPUT, lookUri);
startActivityForResult(intent, REQUEST_SELECT_IMAGE);
}
});
}
private void setupCameraButton(View parentView) {
View cameraButton = parentView.findViewById(R.id.dialog_new_object_camera);
cameraButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
lookUri = UtilCamera.getDefaultLookFromCameraUri(getString(R.string.default_look_name));
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, lookUri);
startActivityForResult(intent, REQUEST_TAKE_PICTURE);
}
});
}
private void setupMediaLibraryButton(View parentView) {
View mediaButton = parentView.findViewById(R.id.dialog_new_object_library);
mediaButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (Utils.isNetworkAvailable(view.getContext(), true)) {
Intent intent = new Intent(getActivity(), WebViewActivity.class);
String url = Constants.LIBRARY_LOOKS_URL;
intent.putExtra(WebViewActivity.INTENT_PARAMETER_URL, url);
intent.putExtra(WebViewActivity.CALLING_ACTIVITY, SpritesListFragment.TAG);
startActivityForResult(intent, REQUEST_MEDIA_LIBRARY);
}
}
});
}
private void setupDroneVideoButton(View parentView) {
View droneVideoButton = parentView.findViewById(R.id.dialog_new_object_drone_video);
View droneDialogItem = parentView.findViewById(R.id.dialog_new_object_third_row);
droneDialogItem.setVisibility(View.VISIBLE);
droneVideoButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
newLookFile = StorageHandler.getInstance().copyImageFromResourceToCatroid(getActivity(), R.drawable.ic_video, getString(R.string.add_look_drone_video));
} catch (IOException e) {
Utils.showErrorDialog(getActivity(), R.string.error_load_image);
Log.e(TAG, Log.getStackTraceString(e));
}
lookUri = Uri.fromFile(newLookFile);
onActivityResult(REQUEST_DRONE_VIDEO, Activity.RESULT_OK, new Intent());
}
});
}
private boolean handleOkButton() {
EditText editText = (EditText) dialogView.findViewById(R.id.dialog_new_object_name_edit_text);
String newSpriteName;
if (editText.length() == 0) {
newSpriteName = editText.getHint().toString();
} else {
newSpriteName = editText.getText().toString().trim();
}
if (newSpriteName.contains(".")) {
int fileExtensionPosition = newSpriteName.indexOf('.');
newSpriteName = newSpriteName.substring(0, fileExtensionPosition);
}
ProjectManager projectManager = ProjectManager.getInstance();
if (newSpriteName.equalsIgnoreCase("")) {
Utils.showErrorDialog(getActivity(), R.string.no_name, R.string.no_spritename_entered);
return false;
}
if (projectManager.spriteExists(newSpriteName)) {
Utils.showErrorDialog(getActivity(), R.string.name_exists, R.string.spritename_already_exists);
return false;
}
LookData lookData;
try {
if (isDroneVideo) {
lookData = new DroneVideoLookData();
newLookFile = new File(lookUri.getPath());
} else {
lookData = new LookData();
newLookFile = StorageHandler.getInstance().copyImage(projectManager.getCurrentProject().getName(),
projectManager.getCurrentScene().getName(), lookUri.getPath(), null);
if (lookUri.getPath().contains(Constants.TMP_LOOKS_PATH)) {
File oldFile = new File(lookUri.getPath());
oldFile.delete();
}
}
String imageFileName = newLookFile.getName();
Utils.rewriteImageFileForStage(getActivity(), newLookFile);
lookData.setLookName(newSpriteName);
lookData.setLookFilename(imageFileName);
} catch (IOException ioException) {
Utils.showErrorDialog(getActivity(), R.string.error_load_image);
Log.e(TAG, Log.getStackTraceString(ioException));
dismiss();
return false;
} catch (NullPointerException e) {
Utils.showErrorDialog(getActivity(), R.string.error_load_image_special_chars);
Log.e(TAG, "somebody might have selected an image and deleted it before it was added");
Log.e(TAG, Log.getStackTraceString(e));
dismiss();
return false;
}
Sprite sprite;
sprite = spriteFactory.newInstance(SingleSprite.class.getSimpleName(), newSpriteName);
projectManager.addSprite(sprite);
sprite.getLookDataList().add(lookData);
if (requestedAction == ActionAfterFinished.ACTION_UPDATE_SPINNER && spinnerAdapter != null) {
Intent broadcastIntent;
broadcastIntent = new Intent(ScriptActivity.ACTION_BRICK_LIST_CHANGED);
getActivity().sendBroadcast(broadcastIntent);
spinnerAdapter.refreshSpinnerAfterNewSprite(getActivity(), newSpriteName);
} else {
Intent broadcastIntent;
broadcastIntent = new Intent(ScriptActivity.ACTION_SPRITES_LIST_CHANGED);
getActivity().sendBroadcast(broadcastIntent);
}
if (requestedAction == ActionAfterFinished.ACTION_FORWARD_TO_NEW_OBJECT) {
projectManager.setCurrentSprite(sprite);
Intent intent = new Intent(getActivity(), ProgramMenuActivity.class);
intent.putExtra(ProgramMenuActivity.FORWARD_TO_SCRIPT_ACTIVITY, ScriptActivity.FRAGMENT_SCRIPTS);
startActivity(intent);
}
dismiss();
return true;
}
public enum ActionAfterFinished {
ACTION_FORWARD_TO_NEW_OBJECT, ACTION_UPDATE_SPINNER, NONE;
static final String KEY = "action";
}
public enum DialogWizardStep {
STEP_1, STEP_2;
static final String KEY = "step";
}
}