diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/FileIO.kt b/Paintroid/src/main/java/org/catrobat/paintroid/FileIO.kt index 864f069b0c..190981aa0d 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/FileIO.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/FileIO.kt @@ -104,7 +104,8 @@ object FileIO { PNG("png"), JPG("jpg"), ORA("ora"), - CATROBAT("catrobat-image"); + CATROBAT("catrobat-image"), + GIF("gif"); fun toExtension(): String = ".$value" } @@ -132,7 +133,7 @@ object FileIO { } @Throws(IOException::class) - fun saveBitmapToUri(uri: Uri, bitmap: Bitmap?, context: Context): Uri { + fun saveBitmapToUri(uri: Uri, bitmap: Bitmap?, context: Context): Uri { val uid = UUID.randomUUID() val cachedImageUri = saveBitmapToCache(bitmap, context as MainActivity, uid.toString()) var cachedFile: File? = null diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/PaintroidApplication.kt b/Paintroid/src/main/java/org/catrobat/paintroid/PaintroidApplication.kt index b93795d6d6..cd9fec72c6 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/PaintroidApplication.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/PaintroidApplication.kt @@ -18,17 +18,31 @@ */ package org.catrobat.paintroid +import android.graphics.Bitmap +import org.catrobat.paintroid.ui.DrawingSurface import java.io.File import java.lang.IllegalArgumentException @SuppressWarnings("ThrowingExceptionsWithoutMessageOrCause") -class PaintroidApplication private constructor() { - companion object { - @JvmStatic - var cacheDir: File? = null - } +class PaintroidApplication() { + object DrawingSurface { + fun copyBitmap(): Bitmap { - init { - throw IllegalArgumentException() + return Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888) + } } } + + + + + +//@JvmStatic +// var cacheDir: File? = null +// } +// +// +// init { +// throw IllegalArgumentException() +// } +//} diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/contract/MainActivityContracts.kt b/Paintroid/src/main/java/org/catrobat/paintroid/contract/MainActivityContracts.kt index 84fef55bab..517bb8a02b 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/contract/MainActivityContracts.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/contract/MainActivityContracts.kt @@ -308,6 +308,7 @@ interface MainActivityContracts { fun checkForTemporaryFile(): Boolean fun setColorHistoryAfterLoadImage(colorHistory: ColorHistory?) + fun showGifInformationDialog() } interface Model { diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/dialog/AnimatedGifEncoder.kt b/Paintroid/src/main/java/org/catrobat/paintroid/dialog/AnimatedGifEncoder.kt new file mode 100644 index 0000000000..44dc4c96bb --- /dev/null +++ b/Paintroid/src/main/java/org/catrobat/paintroid/dialog/AnimatedGifEncoder.kt @@ -0,0 +1,151 @@ +package org.catrobat.paintroid.dialog + + + +import android.graphics.Bitmap +import android.graphics.Color +import java.io.BufferedOutputStream +import java.io.FileOutputStream +import java.io.IOException + +class AnimatedGifEncoder { + + private var width: Int = 0 + private var height: Int = 0 + private lateinit var indexedPixels: ByteArray + private var colorDepth: Int = 0 + private lateinit var colorTab: ByteArray + private lateinit var usedEntry: BooleanArray + private var palSize: Int = 0 + private var dispose: Int = -1 + private var closeStream: Boolean = false + private var firstFrame: Boolean = true + private var sample: Int = 10 + private var delay: Int = 0 + private lateinit var outputStream: FileOutputStream + private lateinit var bufferedOutputStream: BufferedOutputStream + private var transIndex: Int = 0 + private var started: Boolean = false + + fun start(fileOutputStream: FileOutputStream) { + if (!started) { + outputStream = fileOutputStream + bufferedOutputStream = BufferedOutputStream(outputStream) + writeString("GIF89a") // header + started = true + } + } + + fun setDelay(ms: Int) { + delay = Math.round(ms / 10.0f) + } + + fun addFrame(image: Bitmap) { + if (!started || image == null) return + + try { + if (!firstFrame) { + writeByte(0x21) + writeByte(0xF9) + writeByte(4) + writeByte((dispose shl 2) or 0x01) + writeShort(delay) + writeByte(transIndex) + writeByte(0) + } + val transparent = -1 + val width = image.width + val height = image.height + if (width != this.width || height != this.height) { + throw IllegalArgumentException("Gif frame dimension mismatch") + } + val pixels = IntArray(width * height) + image.getPixels(pixels, 0, width, 0, 0, width, height) + if (firstFrame) { + indexedPixels = ByteArray(width * height) + usedEntry = BooleanArray(256) + var nPix = 0 + for (i in 0 until height) { + for (j in 0 until width) { + val idx = i * width + j + val c = pixels[idx] + val r = Color.red(c) + val g = Color.green(c) + val b = Color.blue(c) + if (r == 255 && g == 255 && b == 255) { + transIndex = idx + } + if (!usedEntry[c]) { + usedEntry[c] = true + nPix++ + } + indexedPixels[idx] = c.toByte() + } + } + palSize = nPix + colorDepth = (Math.log(palSize.toDouble()) / Math.log(2.0) + 0.5).toInt() + if (transIndex != -1) { + transIndex = findClosest(transIndex) + } + } + // Further processing logic for pixels and palette + // Write pixels to GIF + // Write palette to GIF + // Write extension blocks if not first frame + firstFrame = false + } catch (e: IOException) { + e.printStackTrace() + } + } + + fun finish() { + if (!started) return + + try { + bufferedOutputStream.write(0x3b) // gif trailer + bufferedOutputStream.flush() + if (closeStream) { + bufferedOutputStream.close() + } + outputStream.close() + } catch (e: IOException) { + e.printStackTrace() + } + started = false + } + + private fun writeByte(value: Int) { + bufferedOutputStream.write(value) + } + + private fun writeShort(value: Int) { + bufferedOutputStream.write(value and 0xff) + bufferedOutputStream.write((value shr 8) and 0xff) + } + + private fun writeString(string: String) { + for (i in 0 until string.length) { + bufferedOutputStream.write(string[i].toInt()) + } + } + + private fun findClosest(color: Int): Int { + var minpos = 0 + var dmin = 256 * 256 * 256 + val len = colorTab.size + for (i in 0 until len step 3) { + val dr = Color.red(color) - (colorTab[i].toInt() and 0xff) + val dg = Color.green(color) - (colorTab[i + 1].toInt() and 0xff) + val db = Color.blue(color) - (colorTab[i + 2].toInt() and 0xff) + val d = dr * dr + dg * dg + db * db + val index = i / 3 + if (usedEntry[index] && d < dmin) { + dmin = d + minpos = index + } + } + return minpos + + } +} + diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/dialog/SaveInformationDialog.kt b/Paintroid/src/main/java/org/catrobat/paintroid/dialog/SaveInformationDialog.kt index b58f914105..0a77463762 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/dialog/SaveInformationDialog.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/dialog/SaveInformationDialog.kt @@ -22,6 +22,7 @@ import android.annotation.SuppressLint import android.app.Dialog import android.graphics.Bitmap import android.os.Bundle +import android.os.Environment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -36,18 +37,35 @@ import androidx.appcompat.widget.AppCompatEditText import androidx.appcompat.widget.AppCompatImageButton import androidx.appcompat.widget.AppCompatTextView import org.catrobat.paintroid.FileIO -import org.catrobat.paintroid.FileIO.FileType + import org.catrobat.paintroid.FileIO.FileType.PNG import org.catrobat.paintroid.FileIO.FileType.JPG import org.catrobat.paintroid.FileIO.FileType.CATROBAT import org.catrobat.paintroid.FileIO.FileType.ORA +import org.catrobat.paintroid.FileIO.FileType +import org.catrobat.paintroid.PaintroidApplication import org.catrobat.paintroid.R import java.util.Locale +import java.io.File +import java.io.FileOutputStream +import java.io.IOException + + + + + + + private const val STANDARD_FILE_NAME = "image" private const val SET_NAME = "setName" private const val PERMISSION = "permission" private const val IS_EXPORT = "isExport" +private lateinit var gifView: View +private lateinit var delaySeekBar: SeekBar +private lateinit var delayTextView: AppCompatTextView + + class SaveInformationDialog : MainActivityDialogFragment(), @@ -57,6 +75,7 @@ class SaveInformationDialog : private lateinit var inflater: LayoutInflater private lateinit var specificFormatLayout: ViewGroup private lateinit var jpgView: View + private lateinit var delaySeekBar: SeekBar private lateinit var percentage: AppCompatTextView private lateinit var imageName: AppCompatEditText private lateinit var fileName: String @@ -73,7 +92,7 @@ class SaveInformationDialog : if (isStandard) { FileIO.filename = STANDARD_FILE_NAME FileIO.compressFormat = Bitmap.CompressFormat.PNG - FileIO.fileType = PNG + FileIO.fileType = FileType.PNG } return SaveInformationDialog().apply { arguments = Bundle().apply { @@ -114,12 +133,15 @@ class SaveInformationDialog : .setTitle(R.string.dialog_save_image_title) .setView(customLayout) .setPositiveButton(R.string.save_button_text) { _, _ -> - FileIO.filename = imageName.text.toString() - FileIO.storeImageUri = null - if (FileIO.checkFileExists(FileIO.fileType, FileIO.defaultFileName, requireContext().contentResolver)) { - presenter.showOverwriteDialog(permission, isExport) + val selectedFileType = spinner.selectedItem.toString().toLowerCase(Locale.getDefault()) + if (selectedFileType == "gif") { + val delay = delaySeekBar.progress + val gifFileName = imageName.text.toString() + ".gif" + val gifFilePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).absolutePath + File.separator + gifFileName + val bitmap = PaintroidApplication.DrawingSurface.copyBitmap() + saveBitmapAsGif(bitmap, gifFilePath, delay) } else { - presenter.switchBetweenVersions(permission, isExport) + // Handle other file formats } dismiss() } @@ -127,8 +149,30 @@ class SaveInformationDialog : .create() } + private fun saveBitmapAsGif(bitmap: Bitmap, filePath: String, delay: Int) { + val outputStream: FileOutputStream + try { + outputStream = FileOutputStream(filePath) + + val encoder = AnimatedGifEncoder() + encoder.start(outputStream) + encoder.setDelay(delay * 10) + encoder.addFrame(bitmap) + encoder.finish() + outputStream.close() + + } catch (e: IOException) { + e.printStackTrace() + + } + } + private fun initViews(customLayout: View) { initSpecificFormatLayout(customLayout) + initGifView() + initDelaySeekBar() + initDelayTextView() + initJpgView() initSeekBar() initPercentage() @@ -141,6 +185,26 @@ class SaveInformationDialog : specificFormatLayout = view.findViewById(R.id.pocketpaint_save_format_specific_options) } + private fun initGifView() { + gifView = inflater.inflate(R.layout.dialog_pocketpaint_save_gif_sub_dialog, specificFormatLayout, false) + } + + private fun initDelaySeekBar() { + delaySeekBar = gifView.findViewById(R.id.pocketpaint_gif_delay_seekbar_save_info) + delaySeekBar.setOnSeekBarChangeListener(this) + } + + private fun initDelayTextView() { + delayTextView = gifView.findViewById(R.id.pocketpaint_gif_delay_text) + updateDelayTextView(delaySeekBar.progress) + } + + @SuppressLint("StringFormatInvalid") + private fun updateDelayTextView(delay: Int) { + val delayText = getString(R.string.gif_delay_text, delay) + delayTextView.text = delayText + } + private fun initJpgView() { jpgView = inflater.inflate( R.layout.dialog_pocketpaint_save_jpg_sub_dialog, @@ -168,16 +232,19 @@ class SaveInformationDialog : JPG -> presenter.showJpgInformationDialog() ORA -> presenter.showOraInformationDialog() CATROBAT -> presenter.showCatrobatInformationDialog() + FileType.GIF -> presenter.showGifInformationDialog() else -> presenter.showPngInformationDialog() } } } + + private fun initSpinner(view: View) { spinner = view.findViewById(R.id.pocketpaint_save_dialog_spinner) val spinnerArray = FileType.values().map { it.value } val adapter = ArrayAdapter(spinner.context, android.R.layout.simple_spinner_item, spinnerArray) - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) //xml file spinner.adapter = adapter spinner.onItemSelectedListener = this } @@ -204,6 +271,7 @@ class SaveInformationDialog : JPG -> spinner.setSelection(JPG.ordinal) ORA -> spinner.setSelection(ORA.ordinal) CATROBAT -> spinner.setSelection(CATROBAT.ordinal) + FileType.GIF -> spinner.setSelection(FileType.GIF.ordinal) else -> spinner.setSelection(PNG.ordinal) } } @@ -212,8 +280,10 @@ class SaveInformationDialog : when (parent?.getItemAtPosition(position).toString().toLowerCase(Locale.getDefault())) { JPG.value -> setFileDetails(Bitmap.CompressFormat.JPEG, JPG) PNG.value -> setFileDetails(Bitmap.CompressFormat.PNG, PNG) + ORA.value -> setFileDetails(Bitmap.CompressFormat.PNG, ORA) CATROBAT.value -> setFileDetails(Bitmap.CompressFormat.PNG, CATROBAT) + FileType.GIF.value-> setFileDetails(Bitmap.CompressFormat.PNG, FileType.GIF) } } @@ -226,3 +296,11 @@ class SaveInformationDialog : override fun onStartTrackingTouch(seekBar: SeekBar) = Unit override fun onStopTrackingTouch(seekBar: SeekBar) = Unit } + +object FileIO { + var filename: String = "" + var compressFormat: Bitmap.CompressFormat = Bitmap.CompressFormat.PNG + var fileType: FileType = FileType.PNG + var compressQuality: Int = 100 +} + diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/iotasks/SaveImage.kt b/Paintroid/src/main/java/org/catrobat/paintroid/iotasks/SaveImage.kt index 70de33a490..324b04c794 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/iotasks/SaveImage.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/iotasks/SaveImage.kt @@ -60,7 +60,7 @@ class SaveImage( val imageUri = FileIO.saveBitmapToFile(filename, bitmap, callback.contentResolver, context) imageUri } else { - uri?.let { FileIO.saveBitmapToUri(it, bitmap, context) } + uri?.let { FileIO.saveBitmapToUri(it, bitmap, context) } } } diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/drawable/DrawableFactory.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/drawable/DrawableFactory.kt index 0658b7e59d..ca32287827 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/drawable/DrawableFactory.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/drawable/DrawableFactory.kt @@ -25,6 +25,9 @@ class DrawableFactory { DrawableShape.OVAL -> OvalDrawable() DrawableShape.HEART -> HeartDrawable() DrawableShape.STAR -> StarDrawable() + DrawableShape.PENTAGON -> PentagonDrawable() + DrawableShape.TRIANGLE -> TriangleDrawable() + DrawableShape.HEXAGON -> HexagonDrawable() } } } diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/drawable/DrawableShape.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/drawable/DrawableShape.kt index cc76fae877..30eed1cb17 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/drawable/DrawableShape.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/drawable/DrawableShape.kt @@ -19,5 +19,5 @@ package org.catrobat.paintroid.tools.drawable enum class DrawableShape { - RECTANGLE, OVAL, HEART, STAR + RECTANGLE, OVAL, HEART, STAR , PENTAGON, TRIANGLE, HEXAGON } diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/drawable/HexagonDrawable.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/drawable/HexagonDrawable.kt new file mode 100644 index 0000000000..f48574fb96 --- /dev/null +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/drawable/HexagonDrawable.kt @@ -0,0 +1,31 @@ +package org.catrobat.paintroid.tools.drawable +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.Path +import android.graphics.RectF + +private const val CONSTANT_1 = 2f +private const val CONSTANT_2 = 1.7f +class HexagonDrawable:ShapeDrawable { + private val path = Path() + override fun draw(canvas: Canvas, shapeRect: RectF, drawPaint: Paint) { + val midWidth = shapeRect.width() / 2 + val midHeight = shapeRect.height() / 2 + val height = shapeRect.height() / CONSTANT_2 + val width = shapeRect.width() / CONSTANT_1 + path.run { + reset() + moveTo(midWidth - width, midHeight) + lineTo(midWidth - width/2, midHeight - height) + lineTo(midWidth + width/2, midHeight - height) + lineTo(midWidth + width, midHeight) + lineTo(midWidth + width/2, midHeight + height) + lineTo(midWidth - width/2, midHeight + height) + lineTo(midWidth - width, midHeight) + close() + offset(shapeRect.left, shapeRect.top) + } + canvas.drawPath(path, drawPaint) + } +} + diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/drawable/PentagonDrawable.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/drawable/PentagonDrawable.kt new file mode 100644 index 0000000000..3da3ce9fcb --- /dev/null +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/drawable/PentagonDrawable.kt @@ -0,0 +1,33 @@ +package org.catrobat.paintroid.tools.drawable + +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.Path +import android.graphics.RectF + +private const val CONSTANT_1 = 0.95f +private const val CONSTANT_2 = 0.31f +private const val CONSTANT_3 = 0.59f +class PentagonDrawable : ShapeDrawable{ + + private val path = Path() + + override fun draw(canvas: Canvas, shapeRect: RectF, drawPaint: Paint) { + val midWidth = shapeRect.width() / 2 + val midHeight = shapeRect.height() / 2 + val height = shapeRect.height() + val width = shapeRect.width() + path.run { + reset() + moveTo(midWidth, 0f) + lineTo(midWidth + CONSTANT_1 * width / 2, CONSTANT_2 * height) + lineTo(midWidth + CONSTANT_3 * width / 2, height) + lineTo(midWidth - CONSTANT_3 * width / 2, height) + lineTo(midWidth - CONSTANT_1 * width / 2, CONSTANT_2 * height) + lineTo(midWidth, 0f) + close() + offset(shapeRect.left, shapeRect.top) + } + canvas.drawPath(path, drawPaint) + } +} \ No newline at end of file diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/drawable/TriangleDrawable.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/drawable/TriangleDrawable.kt new file mode 100644 index 0000000000..b5346bb1ea --- /dev/null +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/drawable/TriangleDrawable.kt @@ -0,0 +1,22 @@ +package org.catrobat.paintroid.tools.drawable + +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.Path +import android.graphics.RectF +class TriangleDrawable :ShapeDrawable{ + private val path = Path() + + override fun draw(canvas: Canvas, shapeRect: RectF, drawPaint: Paint) { + path.run { + reset() + moveTo(shapeRect.left, shapeRect.bottom) + lineTo(shapeRect.right, shapeRect.bottom) + lineTo(shapeRect.centerX(), shapeRect.top) + lineTo(shapeRect.left, shapeRect.bottom) + close() + } + canvas.drawPath(path, drawPaint) + } + +} \ No newline at end of file diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/ui/DrawingSurface.kt b/Paintroid/src/main/java/org/catrobat/paintroid/ui/DrawingSurface.kt index 3a0eaecf3a..ae8512a08d 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/ui/DrawingSurface.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/ui/DrawingSurface.kt @@ -244,6 +244,10 @@ open class DrawingSurface : SurfaceView, SurfaceHolder.Callback { drawingThread?.stop() } + fun copyBitmap() { + + } + private inner class DrawLoop : Runnable { val holder: SurfaceHolder = getHolder() override fun run() { diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/ui/tools/DefaultShapeToolOptionsView.kt b/Paintroid/src/main/java/org/catrobat/paintroid/ui/tools/DefaultShapeToolOptionsView.kt index 44f78af782..097e12f197 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/ui/tools/DefaultShapeToolOptionsView.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/ui/tools/DefaultShapeToolOptionsView.kt @@ -57,6 +57,9 @@ class DefaultShapeToolOptionsView(rootView: ViewGroup) : ShapeToolOptionsView { private val outlineWidthEditText: AppCompatEditText private val shapeToolDialogTitle: AppCompatTextView private val shapeToolFillOutline: AppCompatTextView + private val triangleButton: AppCompatImageButton + private val pentagonButton: AppCompatImageButton + private val hexagonButton: AppCompatImageButton init { val inflater = LayoutInflater.from(rootView.context) @@ -74,6 +77,9 @@ class DefaultShapeToolOptionsView(rootView: ViewGroup) : ShapeToolOptionsView { outlineTextView = findViewById(R.id.pocketpaint_outline_view_text_view) outlineWidthSeekBar = findViewById(R.id.pocketpaint_shape_stroke_width_seek_bar) outlineWidthEditText = findViewById(R.id.pocketpaint_shape_outline_edit) + triangleButton = findViewById(R.id.pocketpaint_shapes_triangle_btn) + pentagonButton = findViewById(R.id.pocketpaint_shapes_pentagon_btn) + hexagonButton = findViewById(R.id.pocketpaint_shapes_hexagon_btn) } outlineWidthEditText.filters = arrayOf(DefaultNumberRangeFilter(MIN_VAL, MAX_VAL)) @@ -89,6 +95,10 @@ class DefaultShapeToolOptionsView(rootView: ViewGroup) : ShapeToolOptionsView { circleButton.setOnClickListener { onShapeClicked(DrawableShape.OVAL) } heartButton.setOnClickListener { onShapeClicked(DrawableShape.HEART) } starButton.setOnClickListener { onShapeClicked(DrawableShape.STAR) } + triangleButton.setOnClickListener { onShapeClicked(DrawableShape.TRIANGLE) } + pentagonButton.setOnClickListener { onShapeClicked(DrawableShape.PENTAGON) } + hexagonButton.setOnClickListener { onShapeClicked(DrawableShape.HEXAGON) } + fillButton.setOnClickListener { onDrawTypeClicked(DrawableStyle.FILL) } outlineButton.setOnClickListener { onDrawTypeClicked(DrawableStyle.STROKE) } outlineWidthSeekBar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener { @@ -141,7 +151,16 @@ class DefaultShapeToolOptionsView(rootView: ViewGroup) : ShapeToolOptionsView { } private fun resetShapeActivated() { - val buttons = arrayOf(squareButton, circleButton, heartButton, starButton) + //val buttons = arrayOf(squareButton, circleButton, heartButton, starButton,) + val buttons = arrayOf( + squareButton, + circleButton, + heartButton, + starButton, + triangleButton, + pentagonButton, + hexagonButton + ) for (button in buttons) { button.isSelected = false } @@ -175,6 +194,18 @@ class DefaultShapeToolOptionsView(rootView: ViewGroup) : ShapeToolOptionsView { starButton.isSelected = true setShapeToolDialogTitle(R.string.shape_tool_dialog_star_title) } + DrawableShape.TRIANGLE -> { + triangleButton.isSelected = true + setShapeToolDialogTitle(R.string.shape_tool_dialog_triangle_title) + } + DrawableShape.PENTAGON -> { + pentagonButton.isSelected = true + setShapeToolDialogTitle(R.string.shape_tool_dialog_pentagon_title) + } + DrawableShape.HEXAGON -> { + hexagonButton.isSelected = true + setShapeToolDialogTitle(R.string.shape_tool_dialog_hexagon_title) + } } } @@ -184,6 +215,10 @@ class DefaultShapeToolOptionsView(rootView: ViewGroup) : ShapeToolOptionsView { circleButtonResource: Int, heartButtonResource: Int, starButtonResource: Int, + triangleButtonResource: Int, + pentagonButtonResource: Int, + hexagonButtonResource: Int, + visibility: Int ) { shapeToolFillOutline.setText(fillTitle) @@ -191,6 +226,10 @@ class DefaultShapeToolOptionsView(rootView: ViewGroup) : ShapeToolOptionsView { circleButton.setImageResource(circleButtonResource) heartButton.setImageResource(heartButtonResource) starButton.setImageResource(starButtonResource) + triangleButton.setImageResource(triangleButtonResource) + pentagonButton.setImageResource(pentagonButtonResource) + hexagonButton.setImageResource(hexagonButtonResource) + outlineWidthSeekBar.visibility = visibility outlineWidthEditText.visibility = visibility outlineView.visibility = visibility @@ -208,6 +247,9 @@ class DefaultShapeToolOptionsView(rootView: ViewGroup) : ShapeToolOptionsView { R.drawable.ic_pocketpaint_circle, R.drawable.ic_pocketpaint_heart, R.drawable.ic_pocketpaint_star, + R.drawable.ic_pocketpaint_triangle, + R.drawable.ic_pocketpaint_pentagon, + R.drawable.ic_pocketpaint_hexagon, View.GONE ) } @@ -219,6 +261,9 @@ class DefaultShapeToolOptionsView(rootView: ViewGroup) : ShapeToolOptionsView { R.drawable.ic_pocketpaint_circle_out, R.drawable.ic_pocketpaint_heart_out, R.drawable.ic_pocketpaint_star_out, + R.drawable.ic_pocketpaint_triangle_out, + R.drawable.ic_pocketpaint_pentagon_out, + R.drawable.ic_pocketpaint_hexagon_out, View.VISIBLE ) } diff --git a/Paintroid/src/main/res/drawable/ic_pocketpaint_hexagon.xml b/Paintroid/src/main/res/drawable/ic_pocketpaint_hexagon.xml new file mode 100644 index 0000000000..1d44f876f2 --- /dev/null +++ b/Paintroid/src/main/res/drawable/ic_pocketpaint_hexagon.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/Paintroid/src/main/res/drawable/ic_pocketpaint_hexagon_out.xml b/Paintroid/src/main/res/drawable/ic_pocketpaint_hexagon_out.xml new file mode 100644 index 0000000000..8751339730 --- /dev/null +++ b/Paintroid/src/main/res/drawable/ic_pocketpaint_hexagon_out.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/Paintroid/src/main/res/drawable/ic_pocketpaint_pentagon.xml b/Paintroid/src/main/res/drawable/ic_pocketpaint_pentagon.xml new file mode 100644 index 0000000000..cad4566cb4 --- /dev/null +++ b/Paintroid/src/main/res/drawable/ic_pocketpaint_pentagon.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/Paintroid/src/main/res/drawable/ic_pocketpaint_pentagon_out.xml b/Paintroid/src/main/res/drawable/ic_pocketpaint_pentagon_out.xml new file mode 100644 index 0000000000..3ce29057b6 --- /dev/null +++ b/Paintroid/src/main/res/drawable/ic_pocketpaint_pentagon_out.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/Paintroid/src/main/res/drawable/ic_pocketpaint_triangle.xml b/Paintroid/src/main/res/drawable/ic_pocketpaint_triangle.xml new file mode 100644 index 0000000000..425c02b54e --- /dev/null +++ b/Paintroid/src/main/res/drawable/ic_pocketpaint_triangle.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/Paintroid/src/main/res/drawable/ic_pocketpaint_triangle_out.xml b/Paintroid/src/main/res/drawable/ic_pocketpaint_triangle_out.xml new file mode 100644 index 0000000000..2b197abfc2 --- /dev/null +++ b/Paintroid/src/main/res/drawable/ic_pocketpaint_triangle_out.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/Paintroid/src/main/res/layout/dialog_pocketpaint_save.xml b/Paintroid/src/main/res/layout/dialog_pocketpaint_save.xml index 3cb7da04bf..f4d85ca548 100644 --- a/Paintroid/src/main/res/layout/dialog_pocketpaint_save.xml +++ b/Paintroid/src/main/res/layout/dialog_pocketpaint_save.xml @@ -98,4 +98,21 @@ android:clipChildren="false" android:clipToPadding="false" /> + + + + + + + + diff --git a/Paintroid/src/main/res/layout/dialog_pocketpaint_save_gif_sub_dialog.xml b/Paintroid/src/main/res/layout/dialog_pocketpaint_save_gif_sub_dialog.xml new file mode 100644 index 0000000000..1c85a6521f --- /dev/null +++ b/Paintroid/src/main/res/layout/dialog_pocketpaint_save_gif_sub_dialog.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + diff --git a/Paintroid/src/main/res/layout/dialog_pocketpaint_shapes.xml b/Paintroid/src/main/res/layout/dialog_pocketpaint_shapes.xml index 53849476ed..a0fc963140 100644 --- a/Paintroid/src/main/res/layout/dialog_pocketpaint_shapes.xml +++ b/Paintroid/src/main/res/layout/dialog_pocketpaint_shapes.xml @@ -139,6 +139,33 @@ android:layout_weight="1" android:contentDescription="@string/shape_tool_dialog_star_title" android:src="@drawable/ic_pocketpaint_star" /> + + + + + + diff --git a/Paintroid/src/main/res/values/string.xml b/Paintroid/src/main/res/values/string.xml index de2ea72fb6..2ec01f42de 100644 --- a/Paintroid/src/main/res/values/string.xml +++ b/Paintroid/src/main/res/values/string.xml @@ -128,6 +128,9 @@ Ellipse Star Heart + Triangle + Pentagon + Hexagon Fill Outline diff --git a/Paintroid/src/main/res/values/strings.xml b/Paintroid/src/main/res/values/strings.xml new file mode 100644 index 0000000000..9d4b18e6b9 --- /dev/null +++ b/Paintroid/src/main/res/values/strings.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 2c7e76738b..b5ab9e4716 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -102,4 +102,5 @@ dependencies { implementation project(':Paintroid') implementation 'com.android.support:support-core-utils:28.0.0' + implementation 'com.example:library:1.0.0' }