session-android/src/org/thoughtcrime/securesms/scribbles/ScribbleActivity.java

276 lines
8.6 KiB
Java

package org.thoughtcrime.securesms.scribbles;
import android.annotation.TargetApi;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.PointF;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.View;
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.providers.PersistentBlobProvider;
import org.thoughtcrime.securesms.scribbles.viewmodel.Font;
import org.thoughtcrime.securesms.scribbles.viewmodel.Layer;
import org.thoughtcrime.securesms.scribbles.viewmodel.TextLayer;
import org.thoughtcrime.securesms.scribbles.widget.MotionView;
import org.thoughtcrime.securesms.scribbles.widget.ScribbleView;
import org.thoughtcrime.securesms.scribbles.widget.VerticalSlideColorPicker;
import org.thoughtcrime.securesms.scribbles.widget.entity.ImageEntity;
import org.thoughtcrime.securesms.scribbles.widget.entity.MotionEntity;
import org.thoughtcrime.securesms.scribbles.widget.entity.TextEntity;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public class ScribbleActivity extends PassphraseRequiredActionBarActivity implements ScribbleToolbar.ScribbleToolbarListener, VerticalSlideColorPicker.OnColorChangeListener {
private static final String TAG = ScribbleActivity.class.getName();
public static final int SELECT_STICKER_REQUEST_CODE = 123;
public static final int SCRIBBLE_REQUEST_CODE = 31424;
private VerticalSlideColorPicker colorPicker;
private ScribbleToolbar toolbar;
private ScribbleView scribbleView;
private MasterSecret masterSecret;
@Override
protected void onCreate(Bundle savedInstanceState, @NonNull MasterSecret masterSecret) {
setContentView(R.layout.scribble_activity);
this.masterSecret = masterSecret;
this.scribbleView = (ScribbleView) findViewById(R.id.scribble_view);
this.toolbar = (ScribbleToolbar) findViewById(R.id.toolbar);
this.colorPicker = (VerticalSlideColorPicker) findViewById(R.id.scribble_color_picker);
this.toolbar.setListener(this);
this.toolbar.setToolColor(Color.RED);
scribbleView.setMotionViewCallback(motionViewCallback);
scribbleView.setDrawingMode(false);
scribbleView.setImage(getIntent().getData(), masterSecret);
colorPicker.setOnColorChangeListener(this);
colorPicker.setVisibility(View.GONE);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
getSupportActionBar().setTitle(null);
}
private void addSticker(final Bitmap pica) {
Util.runOnMain(() -> {
Layer layer = new Layer();
ImageEntity entity = new ImageEntity(layer, pica, scribbleView.getWidth(), scribbleView.getHeight());
scribbleView.addEntityAndPosition(entity);
});
}
private void changeTextEntityColor(int selectedColor) {
TextEntity textEntity = currentTextEntity();
if (textEntity == null) {
return;
}
textEntity.getLayer().getFont().setColor(selectedColor);
textEntity.updateEntity();
scribbleView.invalidate();
}
private void startTextEntityEditing() {
TextEntity textEntity = currentTextEntity();
if (textEntity != null) {
scribbleView.startEditing(textEntity);
}
}
@Nullable
private TextEntity currentTextEntity() {
if (scribbleView != null && scribbleView.getSelectedEntity() instanceof TextEntity) {
return ((TextEntity) scribbleView.getSelectedEntity());
} else {
return null;
}
}
protected void addTextSticker() {
TextLayer textLayer = createTextLayer();
TextEntity textEntity = new TextEntity(textLayer, scribbleView.getWidth(), scribbleView.getHeight());
scribbleView.addEntityAndPosition(textEntity);
// move text sticker up so that its not hidden under keyboard
PointF center = textEntity.absoluteCenter();
center.y = center.y * 0.5F;
textEntity.moveCenterTo(center);
// redraw
scribbleView.invalidate();
startTextEntityEditing();
changeTextEntityColor(toolbar.getToolColor());
}
private TextLayer createTextLayer() {
TextLayer textLayer = new TextLayer();
Font font = new Font();
font.setColor(TextLayer.Limits.INITIAL_FONT_COLOR);
font.setSize(TextLayer.Limits.INITIAL_FONT_SIZE);
textLayer.setFont(font);
return textLayer;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_STICKER_REQUEST_CODE) {
if (data != null) {
toolbar.setStickerSelected(true);
final String stickerFile = data.getStringExtra(StickerSelectActivity.EXTRA_STICKER_FILE);
new AsyncTask<Void, Void, Bitmap>() {
@Override
protected @Nullable
Bitmap doInBackground(Void... params) {
try {
return BitmapFactory.decodeStream(getAssets().open(stickerFile));
} catch (IOException e) {
Log.w(TAG, e);
return null;
}
}
@Override
protected void onPostExecute(@Nullable Bitmap bitmap) {
addSticker(bitmap);
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
}
}
@Override
public void onBrushSelected(boolean enabled) {
scribbleView.setDrawingMode(enabled);
colorPicker.setVisibility(enabled ? View.VISIBLE : View.GONE);
}
@Override
public void onPaintUndo() {
scribbleView.undoDrawing();
}
@Override
public void onTextSelected(boolean enabled) {
if (enabled) {
addTextSticker();
scribbleView.setDrawingMode(false);
colorPicker.setVisibility(View.VISIBLE);
} else {
scribbleView.clearSelection();
colorPicker.setVisibility(View.GONE);
}
}
@Override
public void onStickerSelected(boolean enabled) {
colorPicker.setVisibility(View.GONE);
if (!enabled) {
scribbleView.clearSelection();
} else {
scribbleView.setDrawingMode(false);
Intent intent = new Intent(this, StickerSelectActivity.class);
startActivityForResult(intent, SELECT_STICKER_REQUEST_CODE);
}
}
public void onDeleteSelected() {
scribbleView.deleteSelected();
colorPicker.setVisibility(View.GONE);
}
@Override
public void onSave() {
ListenableFuture<Bitmap> future = scribbleView.getRenderedImage();
future.addListener(new ListenableFuture.Listener<Bitmap>() {
@Override
public void onSuccess(Bitmap result) {
PersistentBlobProvider provider = PersistentBlobProvider.getInstance(ScribbleActivity.this);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
result.compress(Bitmap.CompressFormat.JPEG, 80, baos);
byte[] data = baos.toByteArray();
baos = null;
result = null;
Uri uri = provider.create(masterSecret, data, MediaUtil.IMAGE_JPEG, null);
Intent intent = new Intent();
intent.setData(uri);
setResult(RESULT_OK, intent);
finish();
}
@Override
public void onFailure(ExecutionException e) {
Log.w(TAG, e);
}
});
}
private final MotionView.MotionViewCallback motionViewCallback = new MotionView.MotionViewCallback() {
@Override
public void onEntitySelected(@Nullable MotionEntity entity) {
if (entity == null) {
toolbar.setNoneSelected();
colorPicker.setVisibility(View.GONE);
} else if (entity instanceof TextEntity) {
toolbar.setTextSelected(true);
colorPicker.setVisibility(View.VISIBLE);
} else {
toolbar.setStickerSelected(true);
colorPicker.setVisibility(View.GONE);
}
}
@Override
public void onEntityDoubleTap(@NonNull MotionEntity entity) {
startTextEntityEditing();
}
};
@Override
public void onColorChange(int color) {
if (color == 0) color = Color.RED;
toolbar.setToolColor(color);
scribbleView.setDrawingBrushColor(color);
changeTextEntityColor(color);
}
}