Skip to content

Commit

Permalink
PAINTROID-396 Multiline tool with movable intermediate points
Browse files Browse the repository at this point in the history
  • Loading branch information
Lenkomotive committed Jul 4, 2023
1 parent b34cc9b commit 0bc32bf
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ class DynamicLineToolIntegrationTest {

@Test
fun testIfCurrentToolIsShownInBottomNavigation() {
ToolBarViewInteraction.onToolBarView().performSelectTool(ToolType.DYNALINE)
BottomNavigationViewInteraction.onBottomNavigationView().checkShowsCurrentTool(ToolType.DYNALINE)

ToolBarViewInteraction.onToolBarView().performSelectTool(ToolType.DYNAMICLINE)
BottomNavigationViewInteraction.onBottomNavigationView().checkShowsCurrentTool(ToolType.DYNAMICLINE)
}
}
11 changes: 10 additions & 1 deletion Paintroid/src/main/java/org/catrobat/paintroid/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,16 @@ import org.catrobat.paintroid.tools.ToolPaint
import org.catrobat.paintroid.tools.ToolReference
import org.catrobat.paintroid.tools.ToolType
import org.catrobat.paintroid.tools.Workspace
import org.catrobat.paintroid.tools.implementation.*
import org.catrobat.paintroid.tools.implementation.BaseToolWithShape
import org.catrobat.paintroid.tools.implementation.ClippingTool
import org.catrobat.paintroid.tools.implementation.DefaultContextCallback
import org.catrobat.paintroid.tools.implementation.DefaultToolFactory
import org.catrobat.paintroid.tools.implementation.DefaultToolPaint
import org.catrobat.paintroid.tools.implementation.DefaultToolReference
import org.catrobat.paintroid.tools.implementation.DefaultWorkspace
import org.catrobat.paintroid.tools.implementation.LineTool
import org.catrobat.paintroid.tools.implementation.TransformTool
import org.catrobat.paintroid.tools.implementation.DynamicLineTool
import org.catrobat.paintroid.tools.options.ToolOptionsViewController
import org.catrobat.paintroid.ui.DrawingSurface
import org.catrobat.paintroid.ui.KeyboardListener
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,8 @@ class PathCommand(val paint: Paint, path: Path) : Command {
override fun freeResources() {
// No resources to free
}

fun updatePath(newPath: Path) {
this.path = newPath
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.catrobat.paintroid.tools.helper

import android.graphics.Color
import android.graphics.Paint
import android.graphics.PointF
import android.graphics.RectF
import org.catrobat.paintroid.command.Command

const val VERTEX_WIDTH = 30.0f

class DynamicLineToolVertex(vertexCenter: PointF?, outgoingPathCommand: Command?, ingoingPathCommand: Command?) {
var vertexCenter: PointF? = vertexCenter
var vertex: RectF? = null
var outgoingPathCommand: Command? = outgoingPathCommand
var ingoingPathCommand: Command? = ingoingPathCommand

init {
if (vertexCenter != null) {
vertex = RectF(
vertexCenter.x - VERTEX_WIDTH,
vertexCenter.y - VERTEX_WIDTH,
vertexCenter.x + VERTEX_WIDTH,
vertexCenter.y + VERTEX_WIDTH
)
}
}

fun updateVertex(newCenter: PointF) {
vertexCenter = newCenter
vertex = RectF(
newCenter.x - VERTEX_WIDTH,
newCenter.y - VERTEX_WIDTH,
newCenter.x + VERTEX_WIDTH,
newCenter.y + VERTEX_WIDTH
)
}

companion object {
private const val RECT_PAINT_ALPHA = 128
private const val RECT_PAINT_STROKE_WIDTH = 2f

fun getPaint(): Paint {
val paint = Paint()
paint.run {
style = Paint.Style.FILL
color = Color.GRAY
alpha = RECT_PAINT_ALPHA
strokeWidth = RECT_PAINT_STROKE_WIDTH
}
return paint
}

fun isInsideVertex(clickedCoordinate: PointF, rectF: RectF): Boolean =
clickedCoordinate.x < rectF.right &&
rectF.left < clickedCoordinate.x &&
clickedCoordinate.y < rectF.bottom &&
rectF.top < clickedCoordinate.y
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,28 @@ package org.catrobat.paintroid.tools.implementation

import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Path
import android.graphics.PointF
import android.util.Log
import android.view.View
import androidx.test.espresso.idling.CountingIdlingResource
import org.catrobat.paintroid.MainActivity
import org.catrobat.paintroid.command.CommandManager
import org.catrobat.paintroid.command.implementation.PathCommand
import org.catrobat.paintroid.command.serialization.SerializablePath
import org.catrobat.paintroid.tools.ContextCallback
import org.catrobat.paintroid.tools.ToolPaint
import org.catrobat.paintroid.tools.ToolType
import org.catrobat.paintroid.tools.Workspace
import org.catrobat.paintroid.tools.common.CommonBrushChangedListener
import org.catrobat.paintroid.tools.common.CommonBrushPreviewListener
import org.catrobat.paintroid.tools.helper.DynamicLineToolVertex
import org.catrobat.paintroid.tools.options.BrushToolOptionsView
import org.catrobat.paintroid.tools.options.ToolOptionsViewController
import org.catrobat.paintroid.ui.viewholder.TopBarViewHolder
import java.util.*
import java.util.ArrayDeque

class DynamicLineTool (
class DynamicLineTool(
private val brushToolOptionsView: BrushToolOptionsView,
contextCallback: ContextCallback,
toolOptionsViewController: ToolOptionsViewController,
Expand All @@ -36,9 +41,12 @@ class DynamicLineTool (
commandManager
) {
override var toolType: ToolType = ToolType.DYNAMICLINE
var startCoordinate: PointF? = null
var endCoordinate: PointF? = null
var startCoordinateIsSet: Boolean = false
private var startCoordinate: PointF? = null
private var endCoordinate: PointF? = null
private var startCoordinateIsSet: Boolean = false
private var vertexStack: Deque<DynamicLineToolVertex> = ArrayDeque()
private var lineIsFinal: Boolean = false
private var currentPathCommand: PathCommand? = null

init {
brushToolOptionsView.setBrushChangedListener(CommonBrushChangedListener(this))
Expand All @@ -51,7 +59,6 @@ class DynamicLineTool (
brushToolOptionsView.setCurrentPaint(toolPaint.paint)
brushToolOptionsView.setStrokeCapButtonChecked(toolPaint.strokeCap)
topBarViewHolder?.hidePlusButton()

}

override fun handleUpAnimations(coordinate: PointF?) {
Expand Down Expand Up @@ -85,11 +92,15 @@ class DynamicLineTool (
override fun onClickOnButton() {
Log.e(TAG, " ✓ clicked")
startCoordinateIsSet = false
lineIsFinal = true
currentPathCommand = null
}

fun onClickOnPlus() {
startCoordinate = endCoordinate?.let { copyPointF(it) }
lineIsFinal = true
currentPathCommand = null
Log.e(TAG, "+ clicked")

}

private fun hideToolOptions() {
Expand Down Expand Up @@ -135,28 +146,41 @@ class DynamicLineTool (
override fun handleDown(coordinate: PointF?): Boolean {
coordinate ?: return false
topBarViewHolder?.showPlusButton()
super.handleDown(coordinate)
startCoordinate = if (!startCoordinateIsSet) {
copyPointF(coordinate).also { startCoordinateIsSet = true }
} else {
startCoordinate
}
super.handleDown(coordinate)
return true
}

override fun handleMove(coordinate: PointF?): Boolean {
coordinate ?: return false
hideToolOptions()
super.handleMove(coordinate)

endCoordinate = copyPointF(coordinate)
Log.e(TAG, endCoordinate!!.x.toString() + " " + endCoordinate!!.y.toString())
Log.e(TAG, "Startcoordinate x: " + startCoordinate!!.x.toString() + " y: " + startCoordinate!!.y.toString())
Log.e(TAG, "Endcoordinate x: " + endCoordinate!!.x.toString() + " y: " + endCoordinate!!.y.toString())
return true
}

override fun handleUp(coordinate: PointF?): Boolean {
coordinate ?: return false
showToolOptions()
super.handleUp(coordinate)

var currentlyDrawnPath = createPath(startCoordinate, coordinate)
// This would mean we are updating an existing path
if (currentPathCommand != null) {
// either update an existing command
(currentPathCommand as PathCommand).updatePath(currentlyDrawnPath)
commandManager.executeAllCommands()
} else {
// or create a new one
currentPathCommand = commandFactory.createPathCommand(toolPaint.paint, currentlyDrawnPath) as PathCommand
commandManager.addCommand(currentPathCommand)
}
return true
}

Expand All @@ -175,12 +199,19 @@ class DynamicLineTool (
brushToolOptionsView.invalidate()
}

private fun copyPointF(coordinate: PointF): PointF{
return PointF(coordinate.x, coordinate.y)
private fun copyPointF(coordinate: PointF): PointF = PointF(coordinate.x, coordinate.y)

private fun createPath(startCoordinate: PointF?, endCoordinate: PointF): SerializablePath {
return SerializablePath().apply {
if (startCoordinate != null && endCoordinate != null) {
moveTo(startCoordinate.x, startCoordinate.y)
lineTo(endCoordinate.x, endCoordinate.y)
}
}
}

companion object {
var topBarViewHolder: TopBarViewHolder? = null
const val TAG = "DynamicLineTool"
}
}
}

0 comments on commit 0bc32bf

Please sign in to comment.