convert MyCanvas to kotlin

This commit is contained in:
tibbi 2017-04-08 18:54:14 +02:00
parent ba838bd5cf
commit fb95526ac0
4 changed files with 259 additions and 279 deletions

View File

@ -1,277 +0,0 @@
package com.simplemobiletools.draw;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import java.util.LinkedHashMap;
import java.util.Map;
public class MyCanvas extends View {
private Paint mPaint;
private MyPath mPath;
private Map<MyPath, PaintOptions> mPaths;
private PathsChangedListener mListener;
private PaintOptions mPaintOptions;
private float mCurX;
private float mCurY;
private float mStartX;
private float mStartY;
private boolean mIsSaving = false;
private boolean mIsStrokeWidthBarEnabled = false;
public MyCanvas(Context context, AttributeSet attrs) {
super(context, attrs);
mPath = new MyPath();
mPaint = new Paint();
mPaintOptions = new PaintOptions();
mPaint.setColor(mPaintOptions.getColor());
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(mPaintOptions.getStrokeWidth());
mPaint.setAntiAlias(true);
mPaths = new LinkedHashMap<>();
mPaths.put(mPath, mPaintOptions);
pathsUpdated();
}
public void setListener(PathsChangedListener listener) {
this.mListener = listener;
}
public void undo() {
if (mPaths.size() <= 0)
return;
MyPath lastKey = null;
for (MyPath key : mPaths.keySet()) {
lastKey = key;
}
mPaths.remove(lastKey);
pathsUpdated();
invalidate();
}
public void setColor(int newColor) {
mPaintOptions.setColor(newColor);
if (mIsStrokeWidthBarEnabled) {
invalidate();
}
}
public void setStrokeWidth(float newStrokeWidth) {
mPaintOptions.setStrokeWidth(newStrokeWidth);
if (mIsStrokeWidthBarEnabled) {
invalidate();
}
}
public void setIsStrokeWidthBarEnabled(boolean isStrokeWidthBarEnabled) {
mIsStrokeWidthBarEnabled = isStrokeWidthBarEnabled;
invalidate();
}
public Bitmap getBitmap() {
final Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.WHITE);
mIsSaving = true;
draw(canvas);
mIsSaving = false;
return bitmap;
}
public Map<MyPath, PaintOptions> getPaths() {
return mPaths;
}
public void addPath(MyPath path, PaintOptions options) {
mPaths.put(path, options);
pathsUpdated();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (Map.Entry<MyPath, PaintOptions> entry : mPaths.entrySet()) {
changePaint(entry.getValue());
canvas.drawPath(entry.getKey(), mPaint);
}
changePaint(mPaintOptions);
canvas.drawPath(mPath, mPaint);
if (mIsStrokeWidthBarEnabled && !mIsSaving) {
drawPreviewCircle(canvas);
}
}
private void drawPreviewCircle(Canvas canvas) {
Resources res = getResources();
mPaint.setStyle(Paint.Style.FILL);
float y = getHeight() - res.getDimension(R.dimen.preview_dot_offset_y);
canvas.drawCircle(getWidth() / 2, y, mPaintOptions.getStrokeWidth() / 2, mPaint);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Utils.shouldUseWhite(mPaintOptions.getColor()) ? Color.WHITE : Color.BLACK);
mPaint.setStrokeWidth(res.getDimension(R.dimen.preview_dot_stroke_size));
y = getHeight() - res.getDimension(R.dimen.preview_dot_offset_y);
float radius = (mPaintOptions.getStrokeWidth() + res.getDimension(R.dimen.preview_dot_stroke_size)) / 2;
canvas.drawCircle(getWidth() / 2, y, radius, mPaint);
changePaint(mPaintOptions);
}
private void changePaint(PaintOptions paintOptions) {
mPaint.setColor(paintOptions.getColor());
mPaint.setStrokeWidth(paintOptions.getStrokeWidth());
}
public void clearCanvas() {
mPath.reset();
mPaths.clear();
pathsUpdated();
invalidate();
}
private void actionDown(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mCurX = x;
mCurY = y;
}
private void actionMove(float x, float y) {
mPath.quadTo(mCurX, mCurY, (x + mCurX) / 2, (y + mCurY) / 2);
mCurX = x;
mCurY = y;
}
private void actionUp() {
mPath.lineTo(mCurX, mCurY);
// draw a dot on click
if (mStartX == mCurX && mStartY == mCurY) {
mPath.lineTo(mCurX, mCurY + 2);
mPath.lineTo(mCurX + 1, mCurY + 2);
mPath.lineTo(mCurX + 1, mCurY);
}
mPaths.put(mPath, mPaintOptions);
pathsUpdated();
mPath = new MyPath();
mPaintOptions = new PaintOptions(mPaintOptions.getColor(), mPaintOptions.getStrokeWidth());
}
private void pathsUpdated() {
if (mListener != null && mPaths != null) {
mListener.pathsChanged(mPaths.size());
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
final float x = event.getX();
final float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mStartX = x;
mStartY = y;
actionDown(x, y);
break;
case MotionEvent.ACTION_MOVE:
actionMove(x, y);
break;
case MotionEvent.ACTION_UP:
actionUp();
break;
default:
break;
}
invalidate();
return true;
}
public interface PathsChangedListener {
void pathsChanged(int cnt);
}
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState savedState = new SavedState(superState);
savedState.mPaths = mPaths;
return savedState;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
if (!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
SavedState savedState = (SavedState) state;
super.onRestoreInstanceState(savedState.getSuperState());
mPaths = savedState.mPaths;
pathsUpdated(); // This doesn't seem to be necessary
}
static class SavedState extends BaseSavedState {
Map<MyPath, PaintOptions> mPaths;
SavedState(Parcelable superState) {
super(superState);
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt(mPaths.size());
for (Map.Entry<MyPath, PaintOptions> entry : mPaths.entrySet()) {
out.writeSerializable(entry.getKey());
PaintOptions paintOptions = entry.getValue();
out.writeInt(paintOptions.getColor());
out.writeFloat(paintOptions.getStrokeWidth());
}
}
public static final Parcelable.Creator<SavedState> CREATOR =
new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
private SavedState(Parcel in) {
super(in);
int size = in.readInt();
for (int i = 0; i < size; i++) {
MyPath key = (MyPath) in.readSerializable();
PaintOptions paintOptions = new PaintOptions(in.readInt(), in.readFloat());
mPaths.put(key, paintOptions);
}
}
}
}

View File

@ -0,0 +1,257 @@
package com.simplemobiletools.draw
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.os.Parcel
import android.os.Parcelable
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import java.util.*
class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
private val mPaint: Paint
private var mPath: MyPath? = null
private var mPaths: MutableMap<MyPath, PaintOptions>? = null
private var mListener: PathsChangedListener? = null
private var mPaintOptions: PaintOptions? = null
private var mCurX = 0f
private var mCurY = 0f
private var mStartX = 0f
private var mStartY = 0f
private var mIsSaving = false
private var mIsStrokeWidthBarEnabled = false
init {
mPath = MyPath()
mPaint = Paint()
mPaintOptions = PaintOptions()
mPaint.color = mPaintOptions!!.color
mPaint.style = Paint.Style.STROKE
mPaint.strokeJoin = Paint.Join.ROUND
mPaint.strokeCap = Paint.Cap.ROUND
mPaint.strokeWidth = mPaintOptions!!.strokeWidth
mPaint.isAntiAlias = true
mPaths = LinkedHashMap<MyPath, PaintOptions>()
mPaths!!.put(mPath!!, mPaintOptions!!)
pathsUpdated()
}
fun setListener(listener: PathsChangedListener) {
this.mListener = listener
}
fun undo() {
if (mPaths!!.isEmpty())
return
var lastKey: MyPath? = null
for (key in mPaths!!.keys) {
lastKey = key
}
mPaths!!.remove(lastKey)
pathsUpdated()
invalidate()
}
fun setColor(newColor: Int) {
mPaintOptions!!.color = newColor
if (mIsStrokeWidthBarEnabled) {
invalidate()
}
}
fun setStrokeWidth(newStrokeWidth: Float) {
mPaintOptions!!.strokeWidth = newStrokeWidth
if (mIsStrokeWidthBarEnabled) {
invalidate()
}
}
fun setIsStrokeWidthBarEnabled(isStrokeWidthBarEnabled: Boolean) {
mIsStrokeWidthBarEnabled = isStrokeWidthBarEnabled
invalidate()
}
val bitmap: Bitmap
get() {
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
canvas.drawColor(Color.WHITE)
mIsSaving = true
draw(canvas)
mIsSaving = false
return bitmap
}
val paths: Map<MyPath, PaintOptions>
get() = mPaths!!
fun addPath(path: MyPath, options: PaintOptions) {
mPaths!!.put(path, options)
pathsUpdated()
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
for ((key, value) in mPaths!!) {
changePaint(value)
canvas.drawPath(key, mPaint)
}
changePaint(mPaintOptions!!)
canvas.drawPath(mPath!!, mPaint)
if (mIsStrokeWidthBarEnabled && !mIsSaving) {
drawPreviewCircle(canvas)
}
}
private fun drawPreviewCircle(canvas: Canvas) {
val res = resources
mPaint.style = Paint.Style.FILL
var y = height - res.getDimension(R.dimen.preview_dot_offset_y)
canvas.drawCircle((width / 2).toFloat(), y, mPaintOptions!!.strokeWidth / 2, mPaint)
mPaint.style = Paint.Style.STROKE
mPaint.color = if (Utils.shouldUseWhite(mPaintOptions!!.color)) Color.WHITE else Color.BLACK
mPaint.strokeWidth = res.getDimension(R.dimen.preview_dot_stroke_size)
y = height - res.getDimension(R.dimen.preview_dot_offset_y)
val radius = (mPaintOptions!!.strokeWidth + res.getDimension(R.dimen.preview_dot_stroke_size)) / 2
canvas.drawCircle((width / 2).toFloat(), y, radius, mPaint)
changePaint(mPaintOptions!!)
}
private fun changePaint(paintOptions: PaintOptions) {
mPaint.color = paintOptions.color
mPaint.strokeWidth = paintOptions.strokeWidth
}
fun clearCanvas() {
mPath!!.reset()
mPaths!!.clear()
pathsUpdated()
invalidate()
}
private fun actionDown(x: Float, y: Float) {
mPath!!.reset()
mPath!!.moveTo(x, y)
mCurX = x
mCurY = y
}
private fun actionMove(x: Float, y: Float) {
mPath!!.quadTo(mCurX, mCurY, (x + mCurX) / 2, (y + mCurY) / 2)
mCurX = x
mCurY = y
}
private fun actionUp() {
mPath!!.lineTo(mCurX, mCurY)
// draw a dot on click
if (mStartX == mCurX && mStartY == mCurY) {
mPath!!.lineTo(mCurX, mCurY + 2)
mPath!!.lineTo(mCurX + 1, mCurY + 2)
mPath!!.lineTo(mCurX + 1, mCurY)
}
mPaths!!.put(mPath!!, mPaintOptions!!)
pathsUpdated()
mPath = MyPath()
mPaintOptions = PaintOptions(mPaintOptions!!.color, mPaintOptions!!.strokeWidth)
}
private fun pathsUpdated() {
if (mListener != null && mPaths != null) {
mListener!!.pathsChanged(mPaths!!.size)
}
}
override fun onTouchEvent(event: MotionEvent): Boolean {
val x = event.x
val y = event.y
when (event.action) {
MotionEvent.ACTION_DOWN -> {
mStartX = x
mStartY = y
actionDown(x, y)
}
MotionEvent.ACTION_MOVE -> actionMove(x, y)
MotionEvent.ACTION_UP -> actionUp()
else -> {
}
}
invalidate()
return true
}
interface PathsChangedListener {
fun pathsChanged(cnt: Int)
}
public override fun onSaveInstanceState(): Parcelable {
val superState = super.onSaveInstanceState()
val savedState = SavedState(superState)
savedState.mPaths = mPaths
return savedState
}
public override fun onRestoreInstanceState(state: Parcelable) {
if (state !is SavedState) {
super.onRestoreInstanceState(state)
return
}
val savedState = state
super.onRestoreInstanceState(savedState.superState)
mPaths = savedState.mPaths
pathsUpdated() // This doesn't seem to be necessary
}
internal class SavedState : View.BaseSavedState {
var mPaths: MutableMap<MyPath, PaintOptions>? = null
constructor(superState: Parcelable) : super(superState)
override fun writeToParcel(out: Parcel, flags: Int) {
super.writeToParcel(out, flags)
out.writeInt(mPaths!!.size)
for ((key, paintOptions) in mPaths!!) {
out.writeSerializable(key)
out.writeInt(paintOptions.color)
out.writeFloat(paintOptions.strokeWidth)
}
}
private constructor(parcel: Parcel) : super(parcel) {
val size = parcel.readInt()
for (i in 0..size - 1) {
val key = parcel.readSerializable() as MyPath
val paintOptions = PaintOptions(parcel.readInt(), parcel.readFloat())
mPaths!!.put(key, paintOptions)
}
}
companion object {
val CREATOR: Parcelable.Creator<SavedState> = object : Parcelable.Creator<SavedState> {
override fun newArray(size: Int): Array<SavedState> = arrayOf()
override fun createFromParcel(source: Parcel) = SavedState(source)
}
}
}
}

View File

@ -12,7 +12,7 @@ import java.security.InvalidParameterException
import java.util.*
// https://stackoverflow.com/a/8127953
internal class MyPath : Path(), Serializable {
class MyPath : Path(), Serializable {
private val actions = LinkedList<Action>()

View File

@ -2,7 +2,7 @@ package com.simplemobiletools.draw
import android.graphics.Color
internal class PaintOptions {
class PaintOptions {
var color = Color.BLACK
var strokeWidth = 5f