misc updates here and there

This commit is contained in:
tibbi 2017-04-08 21:04:24 +02:00
parent f0d2c8e491
commit 1052af3e42
3 changed files with 117 additions and 153 deletions

View file

@ -14,12 +14,12 @@ import com.simplemobiletools.commons.extensions.getContrastColor
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
var mPaths: MutableMap<MyPath, PaintOptions>
private var mPaint: Paint
private var mPath: MyPath
private var mPaintOptions: PaintOptions
private var mPaintOptions: PaintOptions? = null
private var mListener: PathsChangedListener? = null
private var mCurX = 0f
private var mCurY = 0f
private var mStartX = 0f
@ -28,19 +28,19 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
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
mPaint = Paint().apply {
color = mPaintOptions.color
style = Paint.Style.STROKE
strokeJoin = Paint.Join.ROUND
strokeCap = Paint.Cap.ROUND
strokeWidth = mPaintOptions.strokeWidth
isAntiAlias = true
}
mPaths = LinkedHashMap<MyPath, PaintOptions>()
mPaths!!.put(mPath!!, mPaintOptions!!)
mPaths.put(mPath, mPaintOptions)
pathsUpdated()
}
@ -49,28 +49,25 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
}
fun undo() {
if (mPaths!!.isEmpty())
if (mPaths.isEmpty())
return
var lastKey: MyPath? = null
for (key in mPaths!!.keys) {
lastKey = key
}
val lastKey: MyPath? = mPaths.keys.lastOrNull()
mPaths!!.remove(lastKey)
mPaths.remove(lastKey)
pathsUpdated()
invalidate()
}
fun setColor(newColor: Int) {
mPaintOptions!!.color = newColor
mPaintOptions.color = newColor
if (mIsStrokeWidthBarEnabled) {
invalidate()
}
}
fun setStrokeWidth(newStrokeWidth: Float) {
mPaintOptions!!.strokeWidth = newStrokeWidth
mPaintOptions.strokeWidth = newStrokeWidth
if (mIsStrokeWidthBarEnabled) {
invalidate()
}
@ -81,35 +78,31 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
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 getBitmap(): Bitmap {
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
}
fun addPath(path: MyPath, options: PaintOptions) {
mPaths!!.put(path, options)
mPaths.put(path, options)
pathsUpdated()
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
for ((key, value) in mPaths!!) {
for ((key, value) in mPaths) {
changePaint(value)
canvas.drawPath(key, mPaint)
}
changePaint(mPaintOptions!!)
canvas.drawPath(mPath!!, mPaint)
changePaint(mPaintOptions)
canvas.drawPath(mPath, mPaint)
if (mIsStrokeWidthBarEnabled && !mIsSaving) {
drawPreviewCircle(canvas)
@ -121,15 +114,15 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
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)
canvas.drawCircle((width / 2).toFloat(), y, mPaintOptions.strokeWidth / 2, mPaint)
mPaint.style = Paint.Style.STROKE
mPaint.color = mPaintOptions!!.color.getContrastColor()
mPaint.color = mPaintOptions.color.getContrastColor()
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
val radius = (mPaintOptions.strokeWidth + res.getDimension(R.dimen.preview_dot_stroke_size)) / 2
canvas.drawCircle((width / 2).toFloat(), y, radius, mPaint)
changePaint(mPaintOptions!!)
changePaint(mPaintOptions)
}
private fun changePaint(paintOptions: PaintOptions) {
@ -138,45 +131,43 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
}
fun clearCanvas() {
mPath!!.reset()
mPaths!!.clear()
mPath.reset()
mPaths.clear()
pathsUpdated()
invalidate()
}
private fun actionDown(x: Float, y: Float) {
mPath!!.reset()
mPath!!.moveTo(x, y)
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)
mPath.quadTo(mCurX, mCurY, (x + mCurX) / 2, (y + mCurY) / 2)
mCurX = x
mCurY = y
}
private fun actionUp() {
mPath!!.lineTo(mCurX, mCurY)
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)
mPath.lineTo(mCurX, mCurY + 2)
mPath.lineTo(mCurX + 1, mCurY + 2)
mPath.lineTo(mCurX + 1, mCurY)
}
mPaths!!.put(mPath!!, mPaintOptions!!)
mPaths.put(mPath, mPaintOptions)
pathsUpdated()
mPath = MyPath()
mPaintOptions = PaintOptions(mPaintOptions!!.color, mPaintOptions!!.strokeWidth)
mPaintOptions = PaintOptions(mPaintOptions.color, mPaintOptions.strokeWidth)
}
private fun pathsUpdated() {
if (mListener != null && mPaths != null) {
mListener!!.pathsChanged(mPaths!!.size)
}
mListener?.pathsChanged(mPaths.size)
}
override fun onTouchEvent(event: MotionEvent): Boolean {
@ -207,7 +198,7 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
val superState = super.onSaveInstanceState()
val savedState = SavedState(superState)
savedState.mPaths = mPaths
savedState.paths = mPaths
return savedState
}
@ -219,12 +210,12 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
val savedState = state
super.onRestoreInstanceState(savedState.superState)
mPaths = savedState.mPaths
mPaths = savedState.paths
pathsUpdated()
}
internal class SavedState : View.BaseSavedState {
var mPaths: MutableMap<MyPath, PaintOptions>? = null
var paths: MutableMap<MyPath, PaintOptions> = HashMap()
companion object {
val CREATOR: Parcelable.Creator<SavedState> = object : Parcelable.Creator<SavedState> {
@ -238,8 +229,8 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
override fun writeToParcel(out: Parcel, flags: Int) {
super.writeToParcel(out, flags)
out.writeInt(mPaths!!.size)
for ((key, paintOptions) in mPaths!!) {
out.writeInt(paths.size)
for ((key, paintOptions) in paths) {
out.writeSerializable(key)
out.writeInt(paintOptions.color)
out.writeFloat(paintOptions.strokeWidth)
@ -251,7 +242,7 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
for (i in 0..size - 1) {
val key = parcel.readSerializable() as MyPath
val paintOptions = PaintOptions(parcel.readInt(), parcel.readFloat())
mPaths!!.put(key, paintOptions)
paths.put(key, paintOptions)
}
}
}

View file

@ -14,7 +14,7 @@ object Svg {
val out = FileOutputStream(output)
val writer = BufferedWriter(OutputStreamWriter(out))
writeSvg(writer, backgroundColor, canvas.paths, canvas.width, canvas.height)
writeSvg(writer, backgroundColor, canvas.mPaths, canvas.width, canvas.height)
writer.close()
}
@ -32,7 +32,7 @@ object Svg {
writer.write("\" height=\"")
writer.write(height.toString())
writer.write("\" fill=\"#")
writer.write(Integer.toHexString(backgroundColor).substring(2)) // Skip the alpha FF
writer.write(Integer.toHexString(backgroundColor).substring(2))
writer.write("\"/>")
for ((key, value) in paths) {
@ -50,7 +50,7 @@ object Svg {
}
writer.write("\" fill=\"none\" stroke=\"#")
writer.write(Integer.toHexString(options.color).substring(2)) // Skip the alpha FF
writer.write(Integer.toHexString(options.color).substring(2))
writer.write("\" stroke-width=\"")
writer.write(options.strokeWidth.toString())
writer.write("\" stroke-linecap=\"round\"/>")
@ -115,11 +115,11 @@ object Svg {
return svg
}
private class SSvg internal constructor() : Serializable {
internal var width: Int = 0
internal var height: Int = 0
internal var background: SRect? = null
internal val paths: ArrayList<SPath> = ArrayList()
private class SSvg : Serializable {
var background: SRect? = null
val paths: ArrayList<SPath> = ArrayList()
private var width = 0
private var height = 0
internal fun setSize(w: Int, h: Int) {
width = w
@ -127,7 +127,7 @@ object Svg {
}
}
private class SRect internal constructor(internal val width: Int, internal val height: Int, internal val color: Int) : Serializable
private class SRect(val width: Int, val height: Int, val color: Int) : Serializable
private class SPath internal constructor(internal var data: String, internal var color: Int, internal var strokeWidth: Float) : Serializable
private class SPath(var data: String, var color: Int, var strokeWidth: Float) : Serializable
}

View file

@ -10,19 +10,18 @@ import android.net.Uri
import android.os.Bundle
import android.os.Environment
import android.support.v4.app.ActivityCompat
import android.support.v4.content.ContextCompat
import android.support.v4.content.FileProvider
import android.support.v7.app.AlertDialog
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.widget.EditText
import android.widget.RadioGroup
import android.widget.SeekBar
import android.widget.Toast
import com.simplemobiletools.commons.dialogs.ColorPickerDialog
import com.simplemobiletools.commons.extensions.beVisibleIf
import com.simplemobiletools.commons.extensions.hasWriteStoragePermission
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.commons.extensions.value
import com.simplemobiletools.commons.helpers.LICENSE_KOTLIN
import com.simplemobiletools.draw.BuildConfig
import com.simplemobiletools.draw.MyCanvas
@ -43,7 +42,6 @@ class MainActivity : SimpleActivity(), MyCanvas.PathsChangedListener {
private var strokeWidth = 0f
companion object {
private val TAG = MainActivity::class.java.simpleName
private val FOLDER_NAME = "images"
private val FILE_NAME = "simple-draw.png"
private val SAVE_FOLDER_NAME = "Simple Draw"
@ -64,7 +62,7 @@ class MainActivity : SimpleActivity(), MyCanvas.PathsChangedListener {
stroke_width_bar.progress = strokeWidth.toInt()
color_picker.setOnClickListener { pickColor() }
undo.setOnClickListener { undo() }
undo.setOnClickListener { my_canvas.undo() }
}
override fun onResume() {
@ -80,11 +78,6 @@ class MainActivity : SimpleActivity(), MyCanvas.PathsChangedListener {
config.brushSize = strokeWidth
}
override fun onDestroy() {
super.onDestroy()
config.isFirstRun = false
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu, menu)
return true
@ -92,36 +85,15 @@ class MainActivity : SimpleActivity(), MyCanvas.PathsChangedListener {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.menu_save -> {
saveImage()
return true
}
R.id.menu_share -> {
shareImage()
return true
}
R.id.settings -> {
startActivity(Intent(applicationContext, SettingsActivity::class.java))
return true
}
R.id.clear -> {
my_canvas.clearCanvas()
return true
}
R.id.change_background -> {
val oldColor = (my_canvas.background as ColorDrawable).color
ColorPickerDialog(this, oldColor) {
setBackgroundColor(it)
config.canvasBackgroundColor = it
}
return true
}
R.id.about -> {
launchAbout()
return true
}
R.id.menu_save -> saveImage()
R.id.menu_share -> shareImage()
R.id.clear -> my_canvas.clearCanvas()
R.id.change_background -> changeBackgroundClicked()
R.id.settings -> launchSettings()
R.id.about -> launchAbout()
else -> return super.onOptionsItemSelected(item)
}
return true
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
@ -131,17 +103,29 @@ class MainActivity : SimpleActivity(), MyCanvas.PathsChangedListener {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
saveImage()
} else {
Toast.makeText(this, resources.getString(R.string.no_permissions), Toast.LENGTH_SHORT).show()
toast(R.string.no_permissions)
}
}
}
private fun launchSettings() {
startActivity(Intent(applicationContext, SettingsActivity::class.java))
}
private fun launchAbout() {
startAboutActivity(R.string.app_name, LICENSE_KOTLIN, BuildConfig.VERSION_NAME)
}
private fun changeBackgroundClicked() {
val oldColor = (my_canvas.background as ColorDrawable).color
ColorPickerDialog(this, oldColor) {
setBackgroundColor(it)
config.canvasBackgroundColor = it
}
}
private fun saveImage() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
if (!hasWriteStoragePermission()) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), STORAGE_PERMISSION)
return
}
@ -163,28 +147,28 @@ class MainActivity : SimpleActivity(), MyCanvas.PathsChangedListener {
builder.setPositiveButton(R.string.ok, null)
builder.setNegativeButton(R.string.cancel, null)
val alertDialog = builder.create()
alertDialog.show()
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
val fileName = fileNameET.text.toString().trim { it <= ' ' }
if (!fileName.isEmpty()) {
val extension: String
when (fileExtensionRG.checkedRadioButtonId) {
R.id.extension_radio_svg -> extension = ".svg"
else -> extension = ".png"
}
builder.create().apply {
show()
getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
val fileName = fileNameET.value
if (!fileName.isEmpty()) {
val extension = when (fileExtensionRG.checkedRadioButtonId) {
R.id.extension_radio_svg -> ".svg"
else -> ".png"
}
if (saveFile(fileName, extension)) {
curFileName = fileName
curExtensionId = fileExtensionRG.checkedRadioButtonId
if (saveFile(fileName, extension)) {
curFileName = fileName
curExtensionId = fileExtensionRG.checkedRadioButtonId
toast(R.string.saving_ok)
alertDialog.dismiss()
toast(R.string.saving_ok)
dismiss()
} else {
toast(R.string.saving_error)
}
} else {
toast(R.string.saving_error)
toast(R.string.enter_file_name)
}
} else {
toast(R.string.enter_file_name)
}
}
}
@ -201,20 +185,17 @@ class MainActivity : SimpleActivity(), MyCanvas.PathsChangedListener {
val file = File(directory, fileName + extension)
when (extension) {
".png" -> {
val bitmap = my_canvas.bitmap
var out: FileOutputStream? = null
try {
out = FileOutputStream(file)
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out)
my_canvas.getBitmap().compress(Bitmap.CompressFormat.PNG, 100, out)
MediaScannerConnection.scanFile(applicationContext, arrayOf(file.absolutePath), null, null)
} catch (e: Exception) {
Log.e(TAG, "MainActivity SaveFile (.png) " + e.message)
return false
} finally {
try {
out?.close()
} catch (e: IOException) {
Log.e(TAG, "MainActivity SaveFile (.png) 2 " + e.message)
}
}
@ -223,7 +204,6 @@ class MainActivity : SimpleActivity(), MyCanvas.PathsChangedListener {
try {
Svg.saveSvg(file, my_canvas)
} catch (e: Exception) {
Log.e(TAG, "MainActivity SaveFile (.svg) " + e.message)
return false
}
@ -236,16 +216,16 @@ class MainActivity : SimpleActivity(), MyCanvas.PathsChangedListener {
private fun shareImage() {
val shareTitle = resources.getString(R.string.share_via)
val bitmap = my_canvas.bitmap
val sendIntent = Intent()
val uri = getImageUri(bitmap) ?: return
val uri = getImageUri(my_canvas.getBitmap()) ?: return
sendIntent.action = Intent.ACTION_SEND
sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
sendIntent.setDataAndType(uri, contentResolver.getType(uri))
sendIntent.putExtra(Intent.EXTRA_STREAM, uri)
sendIntent.type = "image/*"
startActivity(Intent.createChooser(sendIntent, shareTitle))
Intent().apply {
action = Intent.ACTION_SEND
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
setDataAndType(uri, contentResolver.getType(uri))
putExtra(Intent.EXTRA_STREAM, uri)
type = "image/*"
startActivity(Intent.createChooser(this, shareTitle))
}
}
private fun getImageUri(bitmap: Bitmap): Uri? {
@ -264,23 +244,16 @@ class MainActivity : SimpleActivity(), MyCanvas.PathsChangedListener {
fileOutputStream = FileOutputStream(file)
fileOutputStream.write(bytes.toByteArray())
} catch (e: Exception) {
Log.e(TAG, "getImageUri 1 " + e.message)
} finally {
try {
fileOutputStream?.close()
} catch (e: IOException) {
Log.e(TAG, "getImageUri 2 " + e.message)
} catch (e: Exception) {
}
}
return FileProvider.getUriForFile(this, "com.simplemobiletools.draw.fileprovider", file)
}
fun undo() {
my_canvas.undo()
}
fun pickColor() {
ColorPickerDialog(this, color) {
setColor(it)