From 1769bb062e26dffc30a3ca053f059014b37e8083 Mon Sep 17 00:00:00 2001 From: Julian Raphael Jautz Date: Sat, 23 Apr 2022 15:41:12 +0200 Subject: [PATCH 01/17] PAINTROID-408 minimum rectangle size of rectangle shape tools decreased changed minimum box size for rectangle shape * decreased the minimum box size from 20 to 3 (smaller than 3 doesn't provide good results) * adapted ShapeTool offset calculation for high zoom levels as margin was too high --- .../tools/BaseToolWithRectangleShapeToolTest.java | 12 ++++++------ .../implementation/BaseToolWithRectangleShape.kt | 10 ++++++---- .../paintroid/tools/implementation/ShapeTool.kt | 6 +++++- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/BaseToolWithRectangleShapeToolTest.java b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/BaseToolWithRectangleShapeToolTest.java index fd95f4448c..02c4a83d83 100644 --- a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/BaseToolWithRectangleShapeToolTest.java +++ b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/BaseToolWithRectangleShapeToolTest.java @@ -40,7 +40,7 @@ import org.mockito.junit.MockitoJUnitRunner; import org.mockito.stubbing.Answer; -import static org.catrobat.paintroid.tools.implementation.BaseToolWithRectangleShapeKt.DEFAULT_BOX_RESIZE_MARGIN; +import static org.catrobat.paintroid.tools.implementation.BaseToolWithRectangleShapeKt.MINIMAL_BOX_SIZE; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.is; @@ -130,7 +130,7 @@ public void testResizeRectangleMinimumSizeBiggerThanMargin() { float newWidth = toolToTest.boxWidth; float newHeight = toolToTest.boxHeight; - float boxResizeMargin = DEFAULT_BOX_RESIZE_MARGIN; + float boxResizeMargin = MINIMAL_BOX_SIZE; assertThat(newHeight, is(greaterThanOrEqualTo(boxResizeMargin))); assertThat(newWidth, is(greaterThanOrEqualTo(boxResizeMargin))); @@ -235,8 +235,8 @@ public void testRotateRectangleRight() { // try rotate right toolToTest.handleDown(topLeftRotationPoint); - toolToTest.handleMove(new PointF(screenWidth / 2, topLeftRotationPoint.y)); - toolToTest.handleUp(new PointF(screenWidth / 2, topLeftRotationPoint.y)); + toolToTest.handleMove(new PointF(screenWidth / 2f, topLeftRotationPoint.y)); + toolToTest.handleUp(new PointF(screenWidth / 2f, topLeftRotationPoint.y)); float newRotation = toolToTest.boxRotation; assertThat(newRotation, is(greaterThan(rotation))); } @@ -353,8 +353,8 @@ public void testIsClickInsideBoxCalculatedCorrect() { //rotate right toolToTest.handleDown(topLeftRotationPoint); - toolToTest.handleMove(new PointF(screenWidth / 2, topLeftRotationPoint.y)); - toolToTest.handleUp(new PointF(screenWidth / 2, topLeftRotationPoint.y)); + toolToTest.handleMove(new PointF(screenWidth / 2f, topLeftRotationPoint.y)); + toolToTest.handleUp(new PointF(screenWidth / 2f, topLeftRotationPoint.y)); assertFalse(toolToTest.boxContainsPoint(topLeftCorner)); assertTrue(toolToTest.boxContainsPoint(pointInRotatedRectangle)); diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/BaseToolWithRectangleShape.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/BaseToolWithRectangleShape.kt index b2c325212b..5874edf209 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/BaseToolWithRectangleShape.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/BaseToolWithRectangleShape.kt @@ -55,6 +55,8 @@ import kotlin.math.sin const val MAXIMUM_BORDER_RATIO = 2f @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) +const val MINIMAL_BOX_SIZE = 3 + const val DEFAULT_BOX_RESIZE_MARGIN = 20 const val DEFAULT_ANTIALIASING_ON = true @@ -628,12 +630,12 @@ abstract class BaseToolWithRectangleShape( resizeWidth(deltaXCorrected.toFloat(), rotationRadian) // prevent that box gets too small - if (boxWidth < DEFAULT_BOX_RESIZE_MARGIN) { - boxWidth = DEFAULT_BOX_RESIZE_MARGIN.toFloat() + if (boxWidth < MINIMAL_BOX_SIZE) { + boxWidth = MINIMAL_BOX_SIZE.toFloat() toolPosition.x = oldPosX } - if (boxHeight < DEFAULT_BOX_RESIZE_MARGIN) { - boxHeight = DEFAULT_BOX_RESIZE_MARGIN.toFloat() + if (boxHeight < MINIMAL_BOX_SIZE) { + boxHeight = MINIMAL_BOX_SIZE.toFloat() toolPosition.y = oldPosY } if (respectMaximumBoxResolution && maximumBoxResolution > 0 && boxWidth * boxHeight > maximumBoxResolution) { diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/ShapeTool.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/ShapeTool.kt index 47dc68d12d..9c365bed40 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/ShapeTool.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/ShapeTool.kt @@ -35,6 +35,7 @@ import org.catrobat.paintroid.tools.options.ShapeToolOptionsView import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController private const val SHAPE_OFFSET = 10f +private const val MIN_SHAPE_OFFSET = 0.75f private const val DEFAULT_OUTLINE_WIDTH = 25 private const val BUNDLE_BASE_SHAPE = "BASE_SHAPE" private const val BUNDLE_SHAPE_DRAW_TYPE = "SHAPE_DRAW_TYPE" @@ -134,7 +135,10 @@ class ShapeTool( private fun prepareShapeRectangle(shapeRect: RectF, boxWidth: Float, boxHeight: Float) { shapeRect.setEmpty() - shapeRect.inset(SHAPE_OFFSET - boxWidth / 2, SHAPE_OFFSET - boxHeight / 2) + val zoomScaling = if (workspace.scale > 1) workspace.scale else 1f + var shapeOffset = SHAPE_OFFSET / zoomScaling + shapeOffset = if (shapeOffset > MIN_SHAPE_OFFSET) shapeOffset else MIN_SHAPE_OFFSET + shapeRect.inset(shapeOffset - boxWidth / 2, shapeOffset - boxHeight / 2) if (shapePreviewPaint.style == Paint.Style.STROKE) { shapeRect.inset(shapeOutlineWidth / 2f, shapeOutlineWidth / 2f) } From 12e1f8265e9d2c176af33fc79738dce2903c65ff Mon Sep 17 00:00:00 2001 From: David Moling Date: Sun, 1 May 2022 12:00:34 +0200 Subject: [PATCH 02/17] PAINTRDID-146 set center tool with algorithm similar to scratch --- .../tools/TransformToolIntegrationTest.kt | 38 ++++ .../util/DrawingSurfaceLocationProvider.java | 12 ++ .../TransformToolOptionsViewInteraction.java | 6 + .../BaseToolWithRectangleShapeToolTest.java | 7 +- .../test/junit/tools/BrushToolTest.java | 4 +- .../test/junit/tools/CursorToolTest.java | 4 +- .../test/junit/tools/FillToolTest.java | 4 +- .../test/junit/tools/ImportToolTest.java | 4 +- .../test/junit/tools/LineToolTest.kt | 6 +- .../test/junit/tools/PipetteToolTest.java | 4 +- .../test/junit/tools/ShapeToolTest.java | 4 +- .../test/junit/tools/SprayToolTest.kt | 4 +- .../test/junit/tools/StampToolTest.java | 4 +- .../tools/helper/JavaCropAlgorithm.kt | 13 +- .../tools/helper/SetCenterAlgorithm.kt | 80 ++++++++ .../tools/implementation/BaseTool.kt | 4 +- .../BaseToolWithRectangleShape.kt | 11 +- .../tools/implementation/BaseToolWithShape.kt | 4 +- .../tools/implementation/BrushTool.kt | 4 +- .../tools/implementation/CursorTool.kt | 4 +- .../tools/implementation/EraserTool.kt | 4 +- .../tools/implementation/FillTool.kt | 4 +- .../tools/implementation/ImportTool.kt | 4 +- .../tools/implementation/LineTool.kt | 4 +- .../tools/implementation/PipetteTool.kt | 4 +- .../tools/implementation/ShapeTool.kt | 4 +- .../tools/implementation/SprayTool.kt | 4 +- .../tools/implementation/StampTool.kt | 4 +- .../tools/implementation/TextTool.kt | 3 +- .../tools/implementation/TransformTool.kt | 193 +++++++++++++++++- .../tools/implementation/WatercolorTool.kt | 4 +- .../tools/options/TransformToolOptionsView.kt | 2 + .../tools/DefaultTransformToolOptionsView.kt | 4 + ...c_pocketpaint_tool_center_focus_strong.xml | 12 ++ .../dialog_pocketpaint_transform_tool.xml | 58 ++++-- Paintroid/src/main/res/values/string.xml | 7 +- 36 files changed, 455 insertions(+), 81 deletions(-) create mode 100644 Paintroid/src/main/java/org/catrobat/paintroid/tools/helper/SetCenterAlgorithm.kt create mode 100644 Paintroid/src/main/res/drawable/ic_pocketpaint_tool_center_focus_strong.xml diff --git a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/tools/TransformToolIntegrationTest.kt b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/tools/TransformToolIntegrationTest.kt index 736456303f..bad7cfde37 100644 --- a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/tools/TransformToolIntegrationTest.kt +++ b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/tools/TransformToolIntegrationTest.kt @@ -1334,6 +1334,44 @@ class TransformToolIntegrationTest { assertEquals(scale, perspective.scale, 0.0001f) } + @Test + fun testTransformToolSetCenterCloseCenter() { + drawPlus(layerModel.currentLayer!!.bitmap!!, initialWidth / 2) + onToolBarView() + .performSelectTool(ToolType.TRANSFORM) + + runBlocking { + onTransformToolOptionsView().performSetCenterClick() + } + onDrawingSurfaceView() + .perform(UiInteractions.touchAt(DrawingSurfaceLocationProvider.BOTTOM_RIGHT_CLOSE_CENTER)) + runBlocking { + TopBarViewInteraction.onTopBarView().performClickCheckmark() + delay(1500) + } + assertThat(toolSelectionBoxWidth, lessThan(initialWidth.toFloat())) + assertThat(toolSelectionBoxHeight, lessThan(initialHeight.toFloat())) + } + + @Test + fun testTransformToolSetCenterFarCenter() { + drawPlus(layerModel.currentLayer!!.bitmap!!, initialWidth / 2) + onToolBarView() + .performSelectTool(ToolType.TRANSFORM) + + runBlocking { + onTransformToolOptionsView().performSetCenterClick() + } + onDrawingSurfaceView() + .perform(UiInteractions.touchAt(DrawingSurfaceLocationProvider.BOTTOM_RIGHT_CORNER)) + runBlocking { + TopBarViewInteraction.onTopBarView().performClickCheckmark() + delay(1500) + } + assertThat(toolSelectionBoxWidth, greaterThan(initialWidth.toFloat())) + assertThat(toolSelectionBoxHeight, greaterThan(initialHeight.toFloat())) + } + companion object { private fun drawPlus(bitmap: Bitmap, lineLength: Int) { val horizontalStartX = bitmap.width / 4 diff --git a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/util/DrawingSurfaceLocationProvider.java b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/util/DrawingSurfaceLocationProvider.java index 3ed99f836c..39af0c3434 100644 --- a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/util/DrawingSurfaceLocationProvider.java +++ b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/util/DrawingSurfaceLocationProvider.java @@ -104,6 +104,18 @@ public float[] calculateCoordinates(View view) { return calculatePercentageOffset(view, .75f, .75f); } }, + BOTTOM_RIGHT_CLOSE_CENTER { + @Override + public float[] calculateCoordinates(View view) { + return calculatePercentageOffset(view, .55f, .55f); + } + }, + BOTTOM_RIGHT_CORNER { + @Override + public float[] calculateCoordinates(View view) { + return calculatePercentageOffset(view, 1f, 1f); + } + }, BOTTOM_MIDDLE { @Override public float[] calculateCoordinates(View view) { diff --git a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/util/wrappers/TransformToolOptionsViewInteraction.java b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/util/wrappers/TransformToolOptionsViewInteraction.java index 91f64abb4a..3705ce9b09 100644 --- a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/util/wrappers/TransformToolOptionsViewInteraction.java +++ b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/util/wrappers/TransformToolOptionsViewInteraction.java @@ -47,6 +47,12 @@ public static TransformToolOptionsViewInteraction onTransformToolOptionsView() { return new TransformToolOptionsViewInteraction(); } + public TransformToolOptionsViewInteraction performSetCenterClick() { + onView(withId(R.id.pocketpaint_transform_set_center_btn)) + .perform(click()); + return this; + } + public TransformToolOptionsViewInteraction performAutoCrop() { onView(withId(R.id.pocketpaint_transform_auto_crop_btn)) .perform(click()); diff --git a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/BaseToolWithRectangleShapeToolTest.java b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/BaseToolWithRectangleShapeToolTest.java index fd95f4448c..70f7b4854f 100644 --- a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/BaseToolWithRectangleShapeToolTest.java +++ b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/BaseToolWithRectangleShapeToolTest.java @@ -30,7 +30,7 @@ import org.catrobat.paintroid.tools.ToolType; import org.catrobat.paintroid.tools.Workspace; import org.catrobat.paintroid.tools.implementation.BaseToolWithRectangleShape; -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController; +import org.catrobat.paintroid.tools.options.ToolOptionsViewController; import org.catrobat.paintroid.ui.Perspective; import org.junit.Before; import org.junit.Test; @@ -69,7 +69,7 @@ public class BaseToolWithRectangleShapeToolTest { @Mock private CommandManager commandManager; @Mock - private ToolOptionsVisibilityController toolOptionsViewController; + private ToolOptionsViewController toolOptionsViewController; @Mock private ContextCallback contextCallback; @Mock @@ -376,8 +376,7 @@ public void testToolPreciseMovementTest() { private class BaseToolWithRectangleShapeImpl extends BaseToolWithRectangleShape { private final ToolType toolType; - BaseToolWithRectangleShapeImpl(ContextCallback contextCallback, - ToolOptionsVisibilityController toolOptionsViewController, ToolType toolType, ToolPaint toolPaint, Workspace layerModelWrapper, CommandManager commandManager) { + BaseToolWithRectangleShapeImpl(ContextCallback contextCallback, ToolOptionsViewController toolOptionsViewController, ToolType toolType, ToolPaint toolPaint, Workspace layerModelWrapper, CommandManager commandManager) { super(contextCallback, toolOptionsViewController, toolPaint, layerModelWrapper, commandManager); this.toolType = toolType; } diff --git a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/BrushToolTest.java b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/BrushToolTest.java index 53ddc5bf72..6e6331aac7 100644 --- a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/BrushToolTest.java +++ b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/BrushToolTest.java @@ -37,7 +37,7 @@ import org.catrobat.paintroid.tools.common.ConstantsKt; import org.catrobat.paintroid.tools.implementation.BrushTool; import org.catrobat.paintroid.tools.options.BrushToolOptionsView; -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController; +import org.catrobat.paintroid.tools.options.ToolOptionsViewController; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -68,7 +68,7 @@ public class BrushToolTest { @Mock private BrushToolOptionsView brushToolOptionsView; @Mock - private ToolOptionsVisibilityController toolOptionsViewController; + private ToolOptionsViewController toolOptionsViewController; @Mock private Workspace workspace; @Mock diff --git a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/CursorToolTest.java b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/CursorToolTest.java index 95a02919c0..536216affc 100644 --- a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/CursorToolTest.java +++ b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/CursorToolTest.java @@ -35,7 +35,7 @@ import org.catrobat.paintroid.tools.common.ConstantsKt; import org.catrobat.paintroid.tools.implementation.CursorTool; import org.catrobat.paintroid.tools.options.BrushToolOptionsView; -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController; +import org.catrobat.paintroid.tools.options.ToolOptionsViewController; import org.catrobat.paintroid.ui.Perspective; import org.junit.Before; import org.junit.Test; @@ -68,7 +68,7 @@ public class CursorToolTest { @Mock private BrushToolOptionsView brushToolOptionsView; @Mock - private ToolOptionsVisibilityController toolOptionsViewController; + private ToolOptionsViewController toolOptionsViewController; @Mock private ContextCallback contextCallback; diff --git a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/FillToolTest.java b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/FillToolTest.java index c8832d1b80..a5fe2c0826 100644 --- a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/FillToolTest.java +++ b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/FillToolTest.java @@ -28,7 +28,7 @@ import org.catrobat.paintroid.tools.Workspace; import org.catrobat.paintroid.tools.implementation.FillTool; import org.catrobat.paintroid.tools.options.FillToolOptionsView; -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController; +import org.catrobat.paintroid.tools.options.ToolOptionsViewController; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; @@ -44,7 +44,7 @@ public class FillToolTest { @Mock public ContextCallback contextCallback; @Mock - public ToolOptionsVisibilityController toolOptionsViewController; + public ToolOptionsViewController toolOptionsViewController; @Mock public Workspace workspace; @Mock diff --git a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/ImportToolTest.java b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/ImportToolTest.java index 622e0fb1e8..ff7131be4b 100644 --- a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/ImportToolTest.java +++ b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/ImportToolTest.java @@ -27,7 +27,7 @@ import org.catrobat.paintroid.tools.ToolPaint; import org.catrobat.paintroid.tools.Workspace; import org.catrobat.paintroid.tools.implementation.ImportTool; -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController; +import org.catrobat.paintroid.tools.options.ToolOptionsViewController; import org.catrobat.paintroid.ui.Perspective; import org.junit.Before; import org.junit.Test; @@ -51,7 +51,7 @@ public class ImportToolTest { @Mock private ToolPaint toolPaint; @Mock - private ToolOptionsVisibilityController toolOptionsViewController; + private ToolOptionsViewController toolOptionsViewController; @Mock private ContextCallback contextCallback; @Mock diff --git a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/LineToolTest.kt b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/LineToolTest.kt index 53f5d61418..c687dc6339 100644 --- a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/LineToolTest.kt +++ b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/LineToolTest.kt @@ -33,7 +33,7 @@ import org.catrobat.paintroid.tools.ToolPaint import org.catrobat.paintroid.tools.Workspace import org.catrobat.paintroid.tools.implementation.LineTool import org.catrobat.paintroid.tools.options.BrushToolOptionsView -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController +import org.catrobat.paintroid.tools.options.ToolOptionsViewController import org.catrobat.paintroid.ui.Perspective import org.catrobat.paintroid.ui.viewholder.TopBarViewHolder import org.junit.Assert @@ -47,7 +47,7 @@ class LineToolTest { private val commandManager = Mockito.mock(CommandManager::class.java) private var workspace = Mockito.mock(Workspace::class.java) private val brushToolOptions = Mockito.mock(BrushToolOptionsView::class.java) - private val toolOptionsController = Mockito.mock(ToolOptionsVisibilityController::class.java) + private val toolOptionsViewController = Mockito.mock(ToolOptionsViewController::class.java) private val contextCallback = Mockito.mock(ContextCallback::class.java) private lateinit var tool: LineTool private var screenWidth = 1920 @@ -84,7 +84,7 @@ class LineToolTest { tool = LineTool( brushToolOptions, contextCallback, - toolOptionsController, + toolOptionsViewController, toolPaint, workspace, commandManager, diff --git a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/PipetteToolTest.java b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/PipetteToolTest.java index 999214398f..da51388021 100644 --- a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/PipetteToolTest.java +++ b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/PipetteToolTest.java @@ -30,7 +30,7 @@ import org.catrobat.paintroid.tools.ToolType; import org.catrobat.paintroid.tools.Workspace; import org.catrobat.paintroid.tools.implementation.PipetteTool; -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController; +import org.catrobat.paintroid.tools.options.ToolOptionsViewController; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -64,7 +64,7 @@ public class PipetteToolTest { @Mock private Workspace workspace; @Mock - private ToolOptionsVisibilityController toolOptionsViewController; + private ToolOptionsViewController toolOptionsViewController; @Mock private ContextCallback contextCallback; diff --git a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/ShapeToolTest.java b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/ShapeToolTest.java index d0406868cb..9c5151bfac 100644 --- a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/ShapeToolTest.java +++ b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/ShapeToolTest.java @@ -29,7 +29,7 @@ import org.catrobat.paintroid.tools.drawable.DrawableShape; import org.catrobat.paintroid.tools.implementation.ShapeTool; import org.catrobat.paintroid.tools.options.ShapeToolOptionsView; -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController; +import org.catrobat.paintroid.tools.options.ToolOptionsViewController; import org.catrobat.paintroid.ui.Perspective; import org.junit.Before; import org.junit.Rule; @@ -58,7 +58,7 @@ public class ShapeToolTest { @Mock private ShapeToolOptionsView shapeToolOptions; @Mock - private ToolOptionsVisibilityController toolOptionsViewController; + private ToolOptionsViewController toolOptionsViewController; @Mock private ContextCallback contextCallback; @Mock diff --git a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/SprayToolTest.kt b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/SprayToolTest.kt index f1f25c1bac..754d7a4a6e 100644 --- a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/SprayToolTest.kt +++ b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/SprayToolTest.kt @@ -33,7 +33,7 @@ import org.catrobat.paintroid.tools.Workspace import org.catrobat.paintroid.tools.implementation.STROKE_25 import org.catrobat.paintroid.tools.implementation.SprayTool import org.catrobat.paintroid.tools.options.SprayToolOptionsView -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController +import org.catrobat.paintroid.tools.options.ToolOptionsViewController import org.junit.After import org.junit.Assert import org.junit.Before @@ -48,7 +48,7 @@ class SprayToolTest { private val workspace = Mockito.mock(Workspace::class.java) private val sprayToolOptionsView = Mockito.mock(SprayToolOptionsView::class.java) private val toolOptionsViewController = - Mockito.mock(ToolOptionsVisibilityController::class.java) + Mockito.mock(ToolOptionsViewController::class.java) private val contextCallback = Mockito.mock(ContextCallback::class.java) private lateinit var tool: SprayTool diff --git a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/StampToolTest.java b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/StampToolTest.java index 7dee28a710..8ffb34a12b 100644 --- a/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/StampToolTest.java +++ b/Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/StampToolTest.java @@ -33,7 +33,7 @@ import org.catrobat.paintroid.tools.Workspace; import org.catrobat.paintroid.tools.implementation.StampTool; import org.catrobat.paintroid.tools.options.StampToolOptionsView; -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController; +import org.catrobat.paintroid.tools.options.ToolOptionsViewController; import org.catrobat.paintroid.ui.Perspective; import org.junit.Before; import org.junit.Test; @@ -60,7 +60,7 @@ public class StampToolTest { @Mock private StampToolOptionsView stampToolOptions; @Mock - private ToolOptionsVisibilityController toolOptionsViewController; + private ToolOptionsViewController toolOptionsViewController; @Mock private ContextCallback contextCallback; @Mock diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/helper/JavaCropAlgorithm.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/helper/JavaCropAlgorithm.kt index 28e2c6ee57..d23bfce320 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/helper/JavaCropAlgorithm.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/helper/JavaCropAlgorithm.kt @@ -32,30 +32,35 @@ class JavaCropAlgorithm : CropAlgorithm { private fun isOpaquePixel(x: Int, y: Int): Boolean = bitmap.getPixel(x, y) != Color.TRANSPARENT - private fun getTopmostCellWithOpaquePixel(): Int? = + fun getTopmostCellWithOpaquePixel(): Int? = bounds.yRange().firstOrNull { y -> bounds.xRange() .firstOrNull { x -> isOpaquePixel(x, y) } != null } - private fun getBottommostCellWithOpaquePixel(): Int? = + fun getBottommostCellWithOpaquePixel(): Int? = bounds.yRange().lastOrNull { y -> bounds.xRange() .firstOrNull { x -> isOpaquePixel(x, y) } != null } - private fun getLeftmostCellWithOpaquePixel(): Int? = + fun getLeftmostCellWithOpaquePixel(): Int? = bounds.xRange().firstOrNull { x -> bounds.yRange() .firstOrNull { y -> isOpaquePixel(x, y) } != null } - private fun getRightmostCellWithOpaquePixel(): Int? = + fun getRightmostCellWithOpaquePixel(): Int? = bounds.xRange().lastOrNull { x -> bounds.yRange() .firstOrNull { y -> isOpaquePixel(x, y) } != null } + fun init(bitmap: Bitmap) { + this.bitmap = bitmap + bounds = Rect(0, 0, bitmap.width - 1, bitmap.height - 1) + } + override fun crop(bitmap: Bitmap?): Rect? { this.bitmap = bitmap ?: return null bounds = Rect(0, 0, bitmap.width - 1, bitmap.height - 1) diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/helper/SetCenterAlgorithm.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/helper/SetCenterAlgorithm.kt new file mode 100644 index 0000000000..eb864826d5 --- /dev/null +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/helper/SetCenterAlgorithm.kt @@ -0,0 +1,80 @@ +/* + * Paintroid: An image manipulation application for Android. + * Copyright (C) 2010-2021 The Catrobat Team + * () + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.catrobat.paintroid.tools.helper + +import android.graphics.Bitmap +import android.graphics.PointF +import android.graphics.Rect + +class SetCenterAlgorithm(javaCropAlgorithm: JavaCropAlgorithm) { + private var cropAlgorithm: JavaCropAlgorithm = javaCropAlgorithm + + private lateinit var bounds: Rect + private lateinit var position: PointF + private lateinit var bitmap: Bitmap + + private fun getDistanceLeft(): Int { + val leftmostCell = cropAlgorithm.getLeftmostCellWithOpaquePixel() ?: return Int.MIN_VALUE + return this.position.x.toInt() - leftmostCell + } + + private fun getDistanceRight(): Int { + val rightmostCell = cropAlgorithm.getRightmostCellWithOpaquePixel() ?: return Int.MIN_VALUE + return rightmostCell - this.position.x.toInt() + } + + private fun getDistanceTop(): Int { + val topmostCell = cropAlgorithm.getTopmostCellWithOpaquePixel() ?: return Int.MIN_VALUE + return this.position.y.toInt() - topmostCell + } + + private fun getDistanceBottom(): Int { + val bottommostCell = + cropAlgorithm.getBottommostCellWithOpaquePixel() ?: return Int.MIN_VALUE + return bottommostCell - this.position.y.toInt() + } + + private fun checkIfNothingFound(): Boolean = + cropAlgorithm.getLeftmostCellWithOpaquePixel() == null + + fun crop(bitmap: Bitmap?, position: PointF?): Rect? { + this.bitmap = bitmap ?: return null + this.position = position ?: return null + cropAlgorithm.init(bitmap) + + if (checkIfNothingFound()) return null + + val distanceLeft = getDistanceLeft() + val distanceRight = getDistanceRight() + val distanceTop = getDistanceTop() + val distanceBottom = getDistanceBottom() + + bounds = Rect(0, 0, 0, 0) + + val distanceVertical = if (distanceTop > distanceBottom) distanceTop else distanceBottom + val distanceHorizontal = if (distanceLeft > distanceRight) distanceLeft else distanceRight + + bounds.top = position.y.toInt() - distanceVertical + bounds.bottom = position.y.toInt() + distanceVertical + bounds.left = position.x.toInt() - distanceHorizontal + bounds.right = position.x.toInt() + distanceHorizontal + + return bounds + } +} diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/BaseTool.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/BaseTool.kt index f07596495c..ff3b875d53 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/BaseTool.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/BaseTool.kt @@ -35,13 +35,13 @@ import org.catrobat.paintroid.tools.ToolPaint import org.catrobat.paintroid.tools.Workspace import org.catrobat.paintroid.tools.common.PointScrollBehavior import org.catrobat.paintroid.tools.common.ScrollBehavior -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController +import org.catrobat.paintroid.tools.options.ToolOptionsViewController abstract class BaseTool( @JvmField open var contextCallback: ContextCallback, @JvmField - protected var toolOptionsViewController: ToolOptionsVisibilityController, + protected var toolOptionsViewController: ToolOptionsViewController, @JvmField protected var toolPaint: ToolPaint, @JvmField diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/BaseToolWithRectangleShape.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/BaseToolWithRectangleShape.kt index b2c325212b..43380fc7e7 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/BaseToolWithRectangleShape.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/BaseToolWithRectangleShape.kt @@ -40,7 +40,7 @@ import org.catrobat.paintroid.tools.ContextCallback import org.catrobat.paintroid.tools.ContextCallback.ScreenOrientation import org.catrobat.paintroid.tools.ToolPaint import org.catrobat.paintroid.tools.Workspace -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController +import org.catrobat.paintroid.tools.options.ToolOptionsViewController import java.lang.Math.toDegrees import java.lang.Math.toRadians import kotlin.math.PI @@ -85,7 +85,7 @@ private const val BUNDLE_BOX_ROTATION = "BOX_ROTATION" abstract class BaseToolWithRectangleShape( contextCallback: ContextCallback, - toolOptionsViewController: ToolOptionsVisibilityController, + toolOptionsViewController: ToolOptionsViewController, toolPaint: ToolPaint, workspace: Workspace, commandManager: CommandManager @@ -149,6 +149,9 @@ abstract class BaseToolWithRectangleShape( @JvmField var rectangleShrinkingOnHighlight: Int + @JvmField + var shouldDrawRectangle = true + private var boxResizeMargin: Float? = 0f private var rotationSymbolWidth: Float? = 0f private var currentAction: FloatingBoxAction? = null @@ -323,7 +326,9 @@ abstract class BaseToolWithRectangleShape( if (overlayDrawable != null) { drawOverlayDrawable(canvas, boxWidth, boxHeight, boxRotation) } - drawRectangle(canvas, boxWidth, boxHeight) + if (shouldDrawRectangle) { + drawRectangle(canvas, boxWidth, boxHeight) + } drawToolSpecifics(canvas, boxWidth, boxHeight) canvas.restore() } diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/BaseToolWithShape.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/BaseToolWithShape.kt index f04fb4141b..21b692c380 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/BaseToolWithShape.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/BaseToolWithShape.kt @@ -31,7 +31,7 @@ import org.catrobat.paintroid.command.CommandManager import org.catrobat.paintroid.tools.ContextCallback import org.catrobat.paintroid.tools.ToolPaint import org.catrobat.paintroid.tools.Workspace -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController +import org.catrobat.paintroid.tools.options.ToolOptionsViewController import kotlin.math.max import kotlin.math.min @@ -40,7 +40,7 @@ private const val BUNDLE_TOOL_POSITION_X = "TOOL_POSITION_X" abstract class BaseToolWithShape @SuppressLint("VisibleForTests") constructor( contextCallback: ContextCallback, - toolOptionsViewController: ToolOptionsVisibilityController, + toolOptionsViewController: ToolOptionsViewController, toolPaint: ToolPaint, workspace: Workspace, commandManager: CommandManager diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/BrushTool.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/BrushTool.kt index 382ac2d1dc..8bd9dd7a00 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/BrushTool.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/BrushTool.kt @@ -36,7 +36,7 @@ import org.catrobat.paintroid.tools.helper.AdvancedSettingsAlgorithms import org.catrobat.paintroid.tools.helper.AdvancedSettingsAlgorithms.smoothing import org.catrobat.paintroid.tools.helper.AdvancedSettingsAlgorithms.threshold import org.catrobat.paintroid.tools.options.BrushToolOptionsView -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController +import org.catrobat.paintroid.tools.options.ToolOptionsViewController import kotlin.math.abs import kotlin.math.max import kotlin.math.sqrt @@ -44,7 +44,7 @@ import kotlin.math.sqrt open class BrushTool( val brushToolOptionsView: BrushToolOptionsView, contextCallback: ContextCallback, - toolOptionsViewController: ToolOptionsVisibilityController, + toolOptionsViewController: ToolOptionsViewController, toolPaint: ToolPaint, workspace: Workspace, commandManager: CommandManager, diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/CursorTool.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/CursorTool.kt index 00e5453db8..8b54948125 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/CursorTool.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/CursorTool.kt @@ -40,7 +40,7 @@ import org.catrobat.paintroid.tools.helper.AdvancedSettingsAlgorithms.smoothing import org.catrobat.paintroid.tools.helper.AdvancedSettingsAlgorithms.smoothingAlgorithm import org.catrobat.paintroid.tools.helper.AdvancedSettingsAlgorithms.threshold import org.catrobat.paintroid.tools.options.BrushToolOptionsView -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController +import org.catrobat.paintroid.tools.options.ToolOptionsViewController import kotlin.math.abs import kotlin.math.max import kotlin.math.min @@ -54,7 +54,7 @@ private const val CURSOR_LINES = 4 open class CursorTool( private val brushToolOptionsView: BrushToolOptionsView, contextCallback: ContextCallback, - toolOptionsViewController: ToolOptionsVisibilityController, + toolOptionsViewController: ToolOptionsViewController, toolPaint: ToolPaint, workspace: Workspace, commandManager: CommandManager, diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/EraserTool.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/EraserTool.kt index d654bfd9c1..1607511f8d 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/EraserTool.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/EraserTool.kt @@ -26,12 +26,12 @@ import org.catrobat.paintroid.tools.ToolPaint import org.catrobat.paintroid.tools.ToolType import org.catrobat.paintroid.tools.Workspace import org.catrobat.paintroid.tools.options.BrushToolOptionsView -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController +import org.catrobat.paintroid.tools.options.ToolOptionsViewController class EraserTool( brushToolOptionsView: BrushToolOptionsView, contextCallback: ContextCallback, - toolOptionsViewController: ToolOptionsVisibilityController, + toolOptionsViewController: ToolOptionsViewController, toolPaint: ToolPaint, workspace: Workspace, commandManager: CommandManager, diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/FillTool.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/FillTool.kt index 4b369affbd..500a981ad7 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/FillTool.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/FillTool.kt @@ -27,7 +27,7 @@ import org.catrobat.paintroid.tools.ToolPaint import org.catrobat.paintroid.tools.ToolType import org.catrobat.paintroid.tools.Workspace import org.catrobat.paintroid.tools.options.FillToolOptionsView -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController +import org.catrobat.paintroid.tools.options.ToolOptionsViewController private const val HUNDRED = 100f const val DEFAULT_TOLERANCE_IN_PERCENT = 12 @@ -36,7 +36,7 @@ const val MAX_ABSOLUTE_TOLERANCE = 510 class FillTool( fillToolOptionsView: FillToolOptionsView, contextCallback: ContextCallback, - toolOptionsViewController: ToolOptionsVisibilityController, + toolOptionsViewController: ToolOptionsViewController, toolPaint: ToolPaint, workspace: Workspace, commandManager: CommandManager, diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/ImportTool.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/ImportTool.kt index ca7a010476..4a60c3f41b 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/ImportTool.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/ImportTool.kt @@ -26,7 +26,7 @@ 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.options.ToolOptionsVisibilityController +import org.catrobat.paintroid.tools.options.ToolOptionsViewController import kotlin.math.max import kotlin.math.min @@ -34,7 +34,7 @@ private const val BUNDLE_TOOL_DRAWING_BITMAP = "BUNDLE_TOOL_DRAWING_BITMAP" class ImportTool( contextCallback: ContextCallback, - toolOptionsViewController: ToolOptionsVisibilityController, + toolOptionsViewController: ToolOptionsViewController, toolPaint: ToolPaint, workspace: Workspace, commandManager: CommandManager, diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/LineTool.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/LineTool.kt index ecb9c904a0..83d1a35872 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/LineTool.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/LineTool.kt @@ -33,13 +33,13 @@ 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.options.BrushToolOptionsView -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController +import org.catrobat.paintroid.tools.options.ToolOptionsViewController import org.catrobat.paintroid.ui.viewholder.TopBarViewHolder class LineTool( private val brushToolOptionsView: BrushToolOptionsView, contextCallback: ContextCallback, - toolOptionsViewController: ToolOptionsVisibilityController, + toolOptionsViewController: ToolOptionsViewController, toolPaint: ToolPaint, workspace: Workspace, commandManager: CommandManager, diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/PipetteTool.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/PipetteTool.kt index a29c5c004d..5ec739f5fd 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/PipetteTool.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/PipetteTool.kt @@ -27,11 +27,11 @@ 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.options.ToolOptionsVisibilityController +import org.catrobat.paintroid.tools.options.ToolOptionsViewController class PipetteTool( contextCallback: ContextCallback, - toolOptionsViewController: ToolOptionsVisibilityController, + toolOptionsViewController: ToolOptionsViewController, toolPaint: ToolPaint, workspace: Workspace, commandManager: CommandManager, diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/ShapeTool.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/ShapeTool.kt index 47dc68d12d..4c28646229 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/ShapeTool.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/ShapeTool.kt @@ -32,7 +32,7 @@ import org.catrobat.paintroid.tools.drawable.DrawableShape import org.catrobat.paintroid.tools.drawable.DrawableStyle import org.catrobat.paintroid.tools.helper.toPoint import org.catrobat.paintroid.tools.options.ShapeToolOptionsView -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController +import org.catrobat.paintroid.tools.options.ToolOptionsViewController private const val SHAPE_OFFSET = 10f private const val DEFAULT_OUTLINE_WIDTH = 25 @@ -43,7 +43,7 @@ private const val BUNDLE_OUTLINE_WIDTH = "OUTLINE_WIDTH" class ShapeTool( shapeToolOptionsView: ShapeToolOptionsView, contextCallback: ContextCallback, - toolOptionsViewController: ToolOptionsVisibilityController, + toolOptionsViewController: ToolOptionsViewController, toolPaint: ToolPaint, workspace: Workspace, commandManager: CommandManager, diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/SprayTool.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/SprayTool.kt index 8925f84bc7..e79a9e0069 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/SprayTool.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/SprayTool.kt @@ -35,7 +35,7 @@ import org.catrobat.paintroid.tools.ToolPaint import org.catrobat.paintroid.tools.ToolType import org.catrobat.paintroid.tools.Workspace import org.catrobat.paintroid.tools.options.SprayToolOptionsView -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController +import org.catrobat.paintroid.tools.options.ToolOptionsViewController import java.util.concurrent.ConcurrentLinkedQueue import kotlin.math.cos import kotlin.math.pow @@ -50,7 +50,7 @@ private const val CONSTANT_1 = 0.5f class SprayTool( var stampToolOptionsView: SprayToolOptionsView, override var contextCallback: ContextCallback, - toolOptionsViewController: ToolOptionsVisibilityController, + toolOptionsViewController: ToolOptionsViewController, toolPaint: ToolPaint, workspace: Workspace, commandManager: CommandManager, diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/StampTool.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/StampTool.kt index 0ff027cad4..dcac608fd3 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/StampTool.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/StampTool.kt @@ -29,7 +29,7 @@ import org.catrobat.paintroid.tools.ToolPaint import org.catrobat.paintroid.tools.ToolType import org.catrobat.paintroid.tools.Workspace import org.catrobat.paintroid.tools.options.StampToolOptionsView -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController +import org.catrobat.paintroid.tools.options.ToolOptionsViewController private const val BUNDLE_TOOL_READY_FOR_PASTE = "BUNDLE_TOOL_READY_FOR_PASTE" private const val BUNDLE_TOOL_DRAWING_BITMAP = "BUNDLE_TOOL_DRAWING_BITMAP" @@ -37,7 +37,7 @@ private const val BUNDLE_TOOL_DRAWING_BITMAP = "BUNDLE_TOOL_DRAWING_BITMAP" class StampTool( stampToolOptionsView: StampToolOptionsView, contextCallback: ContextCallback, - toolOptionsViewController: ToolOptionsVisibilityController, + toolOptionsViewController: ToolOptionsViewController, toolPaint: ToolPaint, workspace: Workspace, commandManager: CommandManager, diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/TextTool.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/TextTool.kt index b2c48804eb..68aad3663b 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/TextTool.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/TextTool.kt @@ -34,6 +34,7 @@ import org.catrobat.paintroid.tools.ToolPaint import org.catrobat.paintroid.tools.ToolType import org.catrobat.paintroid.tools.Workspace import org.catrobat.paintroid.tools.options.TextToolOptionsView +import org.catrobat.paintroid.tools.options.ToolOptionsViewController import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController import kotlin.Exception import kotlin.math.max @@ -63,7 +64,7 @@ private const val TAG = "Can't set custom font" class TextTool( private val textToolOptionsView: TextToolOptionsView, contextCallback: ContextCallback, - toolOptionsViewController: ToolOptionsVisibilityController, + toolOptionsViewController: ToolOptionsViewController, toolPaint: ToolPaint, workspace: Workspace, commandManager: CommandManager, diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/TransformTool.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/TransformTool.kt index 6adcbb8af5..20845621ec 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/TransformTool.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/TransformTool.kt @@ -19,9 +19,14 @@ package org.catrobat.paintroid.tools.implementation import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint import android.graphics.PointF import android.graphics.RectF import androidx.annotation.VisibleForTesting +import kotlin.math.floor +import kotlin.math.max +import kotlin.math.min import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -37,11 +42,11 @@ import org.catrobat.paintroid.tools.Workspace import org.catrobat.paintroid.tools.helper.CropAlgorithm import org.catrobat.paintroid.tools.helper.DefaultNumberRangeFilter import org.catrobat.paintroid.tools.helper.JavaCropAlgorithm +import org.catrobat.paintroid.tools.helper.SetCenterAlgorithm +import org.catrobat.paintroid.tools.options.ToolOptionsViewController import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController import org.catrobat.paintroid.tools.options.TransformToolOptionsView import org.catrobat.paintroid.ui.tools.NumberRangeFilter -import kotlin.math.floor -import kotlin.math.min @VisibleForTesting const val MAXIMUM_BITMAP_SIZE_FACTOR = 4.0f @@ -54,11 +59,15 @@ private const val ROTATION_ENABLED = false private const val RESIZE_POINTS_VISIBLE = false private const val RESPECT_MAXIMUM_BORDER_RATIO = false private const val RESPECT_MAXIMUM_BOX_RESOLUTION = true +private const val DEFAULT_CURSOR_STROKE_WIDTH = 5f +private const val MINIMAL_CURSOR_STROKE_WIDTH = 1f +private const val MAXIMAL_CURSOR_STROKE_WIDTH = 10f +private const val CURSOR_LINES = 4 class TransformTool( private val transformToolOptionsView: TransformToolOptionsView, contextCallback: ContextCallback, - toolOptionsViewController: ToolOptionsVisibilityController, + toolOptionsViewController: ToolOptionsViewController, toolPaint: ToolPaint, workspace: Workspace, commandManager: CommandManager, @@ -89,9 +98,11 @@ class TransformTool( private var cropRunFinished = false private var maxImageResolutionInformationAlreadyShown = false private var zeroSizeBitmap = false + private var isSetCenter = false private val rangeFilterHeight: NumberRangeFilter private val rangeFilterWidth: NumberRangeFilter private val cropAlgorithm: CropAlgorithm + private val setCenterCropAlgorithm: SetCenterAlgorithm override val toolType: ToolType get() = ToolType.TRANSFORM @@ -105,6 +116,7 @@ class TransformTool( toolPosition.x = boxWidth / 2f toolPosition.y = boxHeight / 2f cropAlgorithm = JavaCropAlgorithm() + setCenterCropAlgorithm = SetCenterAlgorithm(cropAlgorithm) cropRunFinished = true maximumBoxResolution = metrics.widthPixels * metrics.heightPixels * MAXIMUM_BITMAP_SIZE_FACTOR @@ -112,7 +124,12 @@ class TransformTool( initResizeBounds() toolOptionsViewController.setCallback(object : ToolOptionsVisibilityController.Callback { override fun onHide() { - if (!zeroSizeBitmap) { + if (isSetCenter) { + contextCallback.showNotificationWithDuration( + R.string.set_center_info_text, + ContextCallback.NotificationDuration.LONG + ) + } else if (!zeroSizeBitmap) { contextCallback.showNotificationWithDuration( R.string.transform_info_text, ContextCallback.NotificationDuration.LONG @@ -131,6 +148,10 @@ class TransformTool( autoCrop() } + override fun setCenterClicked() { + setCenter() + } + override fun rotateCounterClockwiseClicked() { rotateCounterClockWise() } @@ -175,12 +196,43 @@ class TransformTool( initialiseResizingState() } + override fun handleDown(coordinate: PointF?): Boolean { + coordinate ?: return false + if (!isSetCenter) { + return super.handleDown(coordinate) + } + + CoroutineScope(Dispatchers.Default).launch { + toolPosition.x = coordinate.x + toolPosition.y = coordinate.y + withContext(Dispatchers.Main) { + workspace.invalidate() + } + } + return true + } + + override fun handleMove(coordinate: PointF?): Boolean { + if (isSetCenter) { + return false + } + return super.handleMove(coordinate) + } + override fun drawToolSpecifics(canvas: Canvas, boxWidth: Float, boxHeight: Float) { + + if (isSetCenter) { + drawCursor(canvas) + return + } + var width = boxWidth var height = boxHeight + if (cropRunFinished) { linePaint.color = primaryShapeColor linePaint.strokeWidth = toolStrokeWidth * 2 + val rightTopPoint = PointF(-width / 2, -height / 2) repeat(SIDES) { val resizeLineLengthHeight = height / CONSTANT_1 @@ -246,6 +298,28 @@ class TransformTool( updateToolOptions() } + private fun executeSetCenterCommand() { + CoroutineScope(Dispatchers.Default).launch { + val shapeBounds = setCenterCropAlgorithm.crop(workspace.bitmapOfAllLayers, toolPosition) + if (shapeBounds != null) { + boxWidth = shapeBounds.width() + 1f + boxHeight = shapeBounds.height() + 1f + toolPosition.x = shapeBounds.left + (shapeBounds.width() + 1) / 2.0f + toolPosition.y = shapeBounds.top + (shapeBounds.height() + 1) / 2.0f + } else { + toolPosition.x = boxWidth / 2.0f + toolPosition.y = boxHeight / 2.0f + } + + withContext(Dispatchers.Main) { + isSetCenter = false + shouldDrawRectangle = true + workspace.invalidate() + toolOptionsViewController.hide() + } + } + } + private fun executeResizeCommand() { if (cropRunFinished) { cropRunFinished = false @@ -326,6 +400,111 @@ class TransformTool( } } + private fun setCenter() { + CoroutineScope(Dispatchers.Default).launch { + isSetCenter = true + shouldDrawRectangle = false + withContext(Dispatchers.Main) { + toolOptionsViewController.hide() + } + workspace.invalidate() + } + } + + private fun drawCursor(canvas: Canvas) { + val positionX = 0.0f + val positionY = 0.0f + val brushStrokeWidth = max(toolPaint.strokeWidth / 2f, 1f) + val strokeWidth = getStrokeWidthForZoom( + DEFAULT_CURSOR_STROKE_WIDTH, + MINIMAL_CURSOR_STROKE_WIDTH, MAXIMAL_CURSOR_STROKE_WIDTH + ) + val cursorPartLength = strokeWidth * 2 + val innerCircleRadius = brushStrokeWidth + strokeWidth / 2f + val outerCircleRadius = innerCircleRadius + strokeWidth + linePaint.apply { + color = + contextCallback.getColor(R.color.pocketpaint_main_cursor_tool_inactive_primary_color) + style = Paint.Style.STROKE + this.strokeWidth = strokeWidth + } + drawCursorCircle( + canvas, + strokeWidth, + outerCircleRadius, + innerCircleRadius, + positionX, + positionY + ) + + linePaint.style = Paint.Style.FILL + var startLineLengthAddition = strokeWidth / 2f + var endLineLengthAddition = cursorPartLength + strokeWidth + var lineNr = 0 + while (lineNr < CURSOR_LINES) { + if (lineNr % 2 == 0) { + linePaint.color = Color.LTGRAY + } else { + linePaint.color = + contextCallback.getColor(R.color.pocketpaint_main_cursor_tool_inactive_primary_color) + } + + canvas.drawLine( + positionX - outerCircleRadius - startLineLengthAddition, + positionY, + positionX - outerCircleRadius - endLineLengthAddition, + positionY, + linePaint + ) + canvas.drawLine( + positionX + outerCircleRadius + startLineLengthAddition, + positionY, + positionX + outerCircleRadius + endLineLengthAddition, + positionY, + linePaint + ) + canvas.drawLine( + positionX, + positionY + outerCircleRadius + startLineLengthAddition, + positionX, + positionY + outerCircleRadius + endLineLengthAddition, + linePaint + ) + canvas.drawLine( + positionX, + positionY - outerCircleRadius - startLineLengthAddition, + positionX, + positionY - outerCircleRadius - endLineLengthAddition, + linePaint + ) + lineNr++ + startLineLengthAddition = strokeWidth / 2f + cursorPartLength * lineNr + endLineLengthAddition = strokeWidth + cursorPartLength * (lineNr + 1f) + } + linePaint.style = Paint.Style.STROKE + } + + private fun drawCursorCircle( + canvas: Canvas, + strokeWidth: Float, + outerCircleRadius: Float, + innerCircleRadius: Float, + positionX: Float, + positionY: Float, + ) { + canvas.drawCircle(positionX, positionY, outerCircleRadius, linePaint) + linePaint.color = Color.LTGRAY + canvas.drawCircle(positionX, positionY, innerCircleRadius, linePaint) + linePaint.color = Color.TRANSPARENT + linePaint.style = Paint.Style.FILL + canvas.drawCircle( + positionX, + positionY, + innerCircleRadius - strokeWidth / 2f, + linePaint + ) + } + private fun areResizeBordersValid(): Boolean { if (resizeBoundWidthXRight < resizeBoundWidthXLeft || resizeBoundHeightYTop > resizeBoundHeightYBottom @@ -361,7 +540,11 @@ class TransformTool( } override fun onClickOnButton() { - executeResizeCommand() + if (isSetCenter) { + executeSetCenterCommand() + } else { + executeResizeCommand() + } } override fun preventThatBoxGetsTooLarge( diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/WatercolorTool.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/WatercolorTool.kt index 3023fde6d9..816b62746c 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/WatercolorTool.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/implementation/WatercolorTool.kt @@ -25,7 +25,7 @@ import org.catrobat.paintroid.tools.ToolPaint import org.catrobat.paintroid.tools.ToolType import org.catrobat.paintroid.tools.Workspace import org.catrobat.paintroid.tools.options.BrushToolOptionsView -import org.catrobat.paintroid.tools.options.ToolOptionsVisibilityController +import org.catrobat.paintroid.tools.options.ToolOptionsViewController private const val MAX_ALPHA_VALUE = 255 private const val MAX_NEW_RANGE = 150 @@ -34,7 +34,7 @@ private const val MIN_NEW_RANGE = 20 class WatercolorTool( brushToolOptionsView: BrushToolOptionsView, contextCallback: ContextCallback, - toolOptionsViewController: ToolOptionsVisibilityController, + toolOptionsViewController: ToolOptionsViewController, toolPaint: ToolPaint, workspace: Workspace, commandManager: CommandManager, diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/tools/options/TransformToolOptionsView.kt b/Paintroid/src/main/java/org/catrobat/paintroid/tools/options/TransformToolOptionsView.kt index 74c553e7d7..54a8d9d411 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/tools/options/TransformToolOptionsView.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/tools/options/TransformToolOptionsView.kt @@ -34,6 +34,8 @@ interface TransformToolOptionsView { interface Callback { fun autoCropClicked() + fun setCenterClicked() + fun rotateCounterClockwiseClicked() fun rotateClockwiseClicked() diff --git a/Paintroid/src/main/java/org/catrobat/paintroid/ui/tools/DefaultTransformToolOptionsView.kt b/Paintroid/src/main/java/org/catrobat/paintroid/ui/tools/DefaultTransformToolOptionsView.kt index 9971e04293..5ea52028c6 100644 --- a/Paintroid/src/main/java/org/catrobat/paintroid/ui/tools/DefaultTransformToolOptionsView.kt +++ b/Paintroid/src/main/java/org/catrobat/paintroid/ui/tools/DefaultTransformToolOptionsView.kt @@ -74,6 +74,10 @@ class DefaultTransformToolOptionsView(rootView: ViewGroup) : TransformToolOption .setOnClickListener { callback?.autoCropClicked() } + optionsView.findViewById(R.id.pocketpaint_transform_set_center_btn) + .setOnClickListener { + callback?.setCenterClicked() + } optionsView.findViewById(R.id.pocketpaint_transform_rotate_left_btn) .setOnClickListener { callback?.rotateCounterClockwiseClicked() diff --git a/Paintroid/src/main/res/drawable/ic_pocketpaint_tool_center_focus_strong.xml b/Paintroid/src/main/res/drawable/ic_pocketpaint_tool_center_focus_strong.xml new file mode 100644 index 0000000000..04da4972b9 --- /dev/null +++ b/Paintroid/src/main/res/drawable/ic_pocketpaint_tool_center_focus_strong.xml @@ -0,0 +1,12 @@ + + + + diff --git a/Paintroid/src/main/res/layout/dialog_pocketpaint_transform_tool.xml b/Paintroid/src/main/res/layout/dialog_pocketpaint_transform_tool.xml index f9abe5c9f0..9590c61830 100644 --- a/Paintroid/src/main/res/layout/dialog_pocketpaint_transform_tool.xml +++ b/Paintroid/src/main/res/layout/dialog_pocketpaint_transform_tool.xml @@ -37,19 +37,9 @@ -