Skip to content

Commit 4a4bee5

Browse files
authored
Merge pull request #1084 from Catrobat/hotfix-release-v2.8.3
Hotfix release v2.8.3
2 parents 5cce665 + f9e741d commit 4a4bee5

File tree

22 files changed

+304
-151
lines changed

22 files changed

+304
-151
lines changed

Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/LayerIntegrationTest.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ package org.catrobat.paintroid.test.espresso
2121
import android.app.Activity
2222
import android.app.Instrumentation.ActivityResult
2323
import android.content.Intent
24+
import android.content.pm.ActivityInfo
2425
import android.graphics.Bitmap
2526
import android.graphics.Canvas
2627
import android.graphics.Color
@@ -74,10 +75,12 @@ class LayerIntegrationTest {
7475

7576
private var bitmapHeight = 0
7677
private var bitmapWidth = 0
78+
private lateinit var activity: Activity
7779
private lateinit var deletionFileList: ArrayList<File?>
7880

7981
@Before
8082
fun setUp() {
83+
activity = launchActivityRule.activity
8184
deletionFileList = ArrayList()
8285
val workspace = launchActivityRule.activity.workspace
8386
bitmapHeight = workspace.height
@@ -540,6 +543,22 @@ class LayerIntegrationTest {
540543
.checkMatchesColorResource(R.color.pocketpaint_color_picker_green1)
541544
}
542545

546+
@Test
547+
fun testLayerPreviewKeepsBitmapAfterOrientationChange() {
548+
ToolBarViewInteraction.onToolBarView()
549+
.performSelectTool(ToolType.FILL)
550+
DrawingSurfaceInteraction.onDrawingSurfaceView()
551+
.perform(UiInteractions.touchAt(DrawingSurfaceLocationProvider.MIDDLE))
552+
LayerMenuViewInteraction.onLayerMenuView()
553+
.performOpen()
554+
.checkLayerAtPositionHasTopLeftPixelWithColor(0, Color.BLACK)
555+
556+
activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
557+
558+
LayerMenuViewInteraction.onLayerMenuView()
559+
.checkLayerAtPositionHasTopLeftPixelWithColor(0, Color.BLACK)
560+
}
561+
543562
@Test
544563
fun testUndoRedoLayerRotate() {
545564
ToolBarViewInteraction.onToolBarView()

Paintroid/src/androidTest/java/org/catrobat/paintroid/test/espresso/util/wrappers/LayerMenuViewInteraction.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,20 @@
1919

2020
package org.catrobat.paintroid.test.espresso.util.wrappers;
2121

22+
import android.graphics.Bitmap;
23+
import android.graphics.Canvas;
24+
import android.graphics.drawable.Drawable;
2225
import android.view.Gravity;
2326
import android.view.View;
27+
import android.widget.ImageView;
2428

2529
import org.catrobat.paintroid.R;
2630
import org.catrobat.paintroid.model.Layer;
2731
import org.hamcrest.Description;
2832
import org.hamcrest.Matcher;
2933
import org.hamcrest.TypeSafeMatcher;
3034

35+
import androidx.annotation.ColorInt;
3136
import androidx.test.espresso.DataInteraction;
3237
import androidx.test.espresso.ViewInteraction;
3338
import androidx.test.espresso.contrib.DrawerActions;
@@ -87,7 +92,7 @@ public LayerMenuViewInteraction performOpen() {
8792
public LayerMenuViewInteraction performClose() {
8893
check(matches(isDisplayed()));
8994
onView(withId(R.id.pocketpaint_drawer_layout))
90-
.perform(DrawerActions.close(Gravity.END));
95+
.perform(DrawerActions.close(Gravity.END));
9196
return this;
9297
}
9398

@@ -142,4 +147,34 @@ public boolean matchesSafely(View view) {
142147
}
143148
};
144149
}
150+
151+
public LayerMenuViewInteraction checkLayerAtPositionHasTopLeftPixelWithColor(int listPosition, @ColorInt final int expectedColor) {
152+
onData(instanceOf(Layer.class))
153+
.inAdapterView(withId(R.id.pocketpaint_layer_side_nav_list))
154+
.atPosition(listPosition)
155+
.onChildView(withId(R.id.pocketpaint_item_layer_image))
156+
.check(matches(new TypeSafeMatcher<View>() {
157+
@Override
158+
public void describeTo(Description description) {
159+
description.appendText("Color at coordinates is " + Integer.toHexString(expectedColor));
160+
}
161+
162+
@Override
163+
protected boolean matchesSafely(View view) {
164+
Bitmap bitmap = getBitmap(((ImageView) view).getDrawable());
165+
int actualColor = bitmap.getPixel(0, 0);
166+
return actualColor == expectedColor;
167+
}
168+
}));
169+
170+
return this;
171+
}
172+
173+
private Bitmap getBitmap(Drawable drawable) {
174+
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
175+
Canvas canvas = new Canvas(bitmap);
176+
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
177+
drawable.draw(canvas);
178+
return bitmap;
179+
}
145180
}

Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/BaseToolWithRectangleShapeToolTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -361,16 +361,16 @@ public void testIsClickInsideBoxCalculatedCorrect() {
361361
}
362362

363363
@Test
364-
public void testToolClicksOnTouchDownPosition() {
364+
public void testToolPreciseMovementTest() {
365365
float initialToolPositionX = toolToTest.toolPosition.x;
366366
float initialToolPositionY = toolToTest.toolPosition.y;
367367

368368
toolToTest.handleDown(new PointF(initialToolPositionX, initialToolPositionY));
369369
toolToTest.handleMove(new PointF(initialToolPositionX + 9, initialToolPositionY + 9));
370370
toolToTest.handleUp(new PointF(initialToolPositionX + 9, initialToolPositionY + 9));
371371

372-
assertEquals(toolToTest.toolPosition.x, initialToolPositionX, 0);
373-
assertEquals(toolToTest.toolPosition.y, initialToolPositionY, 0);
372+
assertEquals(toolToTest.toolPosition.x, initialToolPositionX + 9, 0);
373+
assertEquals(toolToTest.toolPosition.y, initialToolPositionY + 9, 0);
374374
}
375375

376376
private class BaseToolWithRectangleShapeImpl extends BaseToolWithRectangleShape {

Paintroid/src/androidTest/java/org/catrobat/paintroid/test/junit/tools/StampToolTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ public void testShouldReturnCorrectToolType() {
118118
}
119119

120120
@Test
121-
public void testToolClicksOnTouchDownPosition() {
121+
public void testToolPreciseMovementTest() {
122122
Looper.prepare();
123123

124124
float initialToolPositionX = tool.toolPosition.x;
@@ -128,7 +128,7 @@ public void testToolClicksOnTouchDownPosition() {
128128
tool.handleMove(new PointF(initialToolPositionX + 9, initialToolPositionY + 9));
129129
tool.handleUp(new PointF(initialToolPositionX + 9, initialToolPositionY + 9));
130130

131-
assertEquals(tool.toolPosition.x, initialToolPositionX, 0);
132-
assertEquals(tool.toolPosition.y, initialToolPositionY, 0);
131+
assertEquals(tool.toolPosition.x, initialToolPositionX + 9, 0);
132+
assertEquals(tool.toolPosition.y, initialToolPositionY + 9, 0);
133133
}
134134
}

Paintroid/src/main/java/org/catrobat/paintroid/FileIO.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import org.catrobat.paintroid.common.IS_NO_FILE
4444
import org.catrobat.paintroid.common.IS_ORA
4545
import org.catrobat.paintroid.common.IS_PNG
4646
import org.catrobat.paintroid.common.MAX_LAYERS
47+
import org.catrobat.paintroid.common.TEMP_PICTURE_NAME
4748
import org.catrobat.paintroid.iotasks.BitmapReturnValue
4849
import org.catrobat.paintroid.presenter.MainActivityPresenter
4950
import java.io.File
@@ -160,7 +161,7 @@ object FileIO {
160161
val compressor = Compressor(mainActivity)
161162
compressor.setQuality(compressQuality)
162163
compressor.setCompressFormat(compressFormat)
163-
val tempFileName = "tmp"
164+
val tempFileName = TEMP_PICTURE_NAME
164165
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
165166
var compressed: File? = null
166167
try {

Paintroid/src/main/java/org/catrobat/paintroid/MainActivity.kt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import androidx.appcompat.widget.TooltipCompat
4141
import androidx.core.widget.ContentLoadingProgressBar
4242
import androidx.drawerlayout.widget.DrawerLayout
4343
import com.google.android.material.bottomnavigation.BottomNavigationView
44+
import com.google.android.material.navigation.NavigationView
4445
import org.catrobat.paintroid.command.CommandFactory
4546
import org.catrobat.paintroid.command.CommandManager
4647
import org.catrobat.paintroid.command.CommandManager.CommandListener
@@ -56,7 +57,6 @@ import org.catrobat.paintroid.contract.MainActivityContracts
5657
import org.catrobat.paintroid.contract.MainActivityContracts.MainView
5758
import org.catrobat.paintroid.controller.DefaultToolController
5859
import org.catrobat.paintroid.iotasks.OpenRasterFileFormatConversion
59-
import org.catrobat.paintroid.listener.DrawerLayoutListener
6060
import org.catrobat.paintroid.listener.PresenterColorPickedListener
6161
import org.catrobat.paintroid.model.LayerModel
6262
import org.catrobat.paintroid.model.MainActivityModel
@@ -411,7 +411,7 @@ class MainActivity : AppCompatActivity(), MainView, CommandListener {
411411
}
412412

413413
private fun onCreateLayerMenu() {
414-
val layerLayout = findViewById<ViewGroup>(R.id.pocketpaint_layer_side_nav_menu)
414+
val layerLayout = findViewById<NavigationView>(R.id.pocketpaint_nav_view_layer)
415415
val layerListView = findViewById<DragAndDropListView>(R.id.pocketpaint_layer_side_nav_list)
416416
val layerMenuViewHolder = LayerMenuViewHolder(layerLayout)
417417
val layerNavigator = LayerNavigator(applicationContext)
@@ -422,9 +422,6 @@ class MainActivity : AppCompatActivity(), MainView, CommandListener {
422422
val layerAdapter = LayerAdapter(layerPresenter)
423423
presenterMain.setLayerAdapter(layerAdapter)
424424
layerPresenter.setAdapter(layerAdapter)
425-
findViewById<DrawerLayout>(R.id.pocketpaint_drawer_layout).also {
426-
it.addDrawerListener(DrawerLayoutListener(it, layerAdapter))
427-
}
428425
layerListView.setPresenter(layerPresenter)
429426
layerListView.adapter = layerAdapter
430427
layerPresenter.refreshLayerMenuViewHolder()

Paintroid/src/main/java/org/catrobat/paintroid/command/implementation/StampCommand.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ package org.catrobat.paintroid.command.implementation
2121

2222
import android.graphics.Bitmap
2323
import android.graphics.Canvas
24-
import android.graphics.Paint
2524
import android.graphics.Point
2625
import android.graphics.RectF
2726
import androidx.annotation.VisibleForTesting
@@ -59,7 +58,7 @@ class StampCommand(bitmap: Bitmap, position: Point, width: Float, height: Float,
5958
save()
6059
translate(coordinates.x.toFloat(), coordinates.y.toFloat())
6160
rotate(boxRotation)
62-
drawBitmap(bitmapToDraw, null, rect, Paint(Paint.DITHER_FLAG))
61+
drawBitmap(bitmapToDraw, null, rect, null)
6362
restore()
6463
}
6564

Paintroid/src/main/java/org/catrobat/paintroid/contract/LayerContracts.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ interface LayerContracts {
3030
fun notifyDataSetChanged()
3131

3232
fun getViewHolderAt(position: Int): LayerViewHolder?
33-
34-
fun setDrawerLayoutOpen(isOpen: Boolean)
3533
}
3634

3735
interface Presenter {
@@ -67,6 +65,8 @@ interface LayerContracts {
6765
fun setDefaultToolController(defaultToolController: DefaultToolController)
6866

6967
fun setBottomNavigationViewHolder(bottomNavigationViewHolder: BottomNavigationViewHolder)
68+
69+
fun isShown(): Boolean
7070
}
7171

7272
interface LayerViewHolder {
@@ -83,7 +83,7 @@ interface LayerContracts {
8383

8484
fun setDeselected()
8585

86-
fun updateImageView(bitmap: Bitmap?, isDrawerLayoutOpen: Boolean)
86+
fun updateImageView(bitmap: Bitmap?)
8787

8888
fun setMergable()
8989

@@ -100,6 +100,8 @@ interface LayerContracts {
100100
fun disableRemoveLayerButton()
101101

102102
fun enableRemoveLayerButton()
103+
104+
fun isShown(): Boolean
103105
}
104106

105107
interface Layer {

Paintroid/src/main/java/org/catrobat/paintroid/listener/DrawerLayoutListener.kt

Lines changed: 0 additions & 29 deletions
This file was deleted.

Paintroid/src/main/java/org/catrobat/paintroid/listener/DrawingSurfaceListener.kt

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,20 @@ import org.catrobat.paintroid.tools.ToolType
3030
import org.catrobat.paintroid.tools.options.ToolOptionsViewController
3131
import org.catrobat.paintroid.ui.DrawingSurface
3232
import java.util.EnumSet
33+
import kotlin.collections.ArrayList
34+
import kotlin.collections.MutableList
35+
import kotlin.collections.mutableListOf
3336
import kotlin.math.hypot
3437

3538
private const val DRAWER_EDGE_SIZE = 20f
3639
private const val CONSTANT_1 = 0.5f
40+
private const val JITTER_DELAY_THRESHOLD: Long = 30
41+
private const val JITTER_DISTANCE_THRESHOLD = 50f
3742

3843
open class DrawingSurfaceListener(
3944
private val autoScrollTask: AutoScrollTask,
4045
private val callback: DrawingSurfaceListenerCallback,
41-
displayDensity: Float
46+
private val displayDensity: Float
4247
) : OnTouchListener {
4348
private var touchMode: TouchMode
4449
private var pointerDistance = 0f
@@ -52,6 +57,10 @@ open class DrawingSurfaceListener(
5257
private var autoScroll = true
5358
private var timerStartDraw = 0.toLong()
5459

60+
private var recentTouchEventsData: MutableList<TouchEventData> = mutableListOf()
61+
62+
private data class TouchEventData constructor(val timeStamp: Long, val xCoordinate: Float, val yCoordinate: Float)
63+
5564
internal enum class TouchMode {
5665
DRAW, PINCH
5766
}
@@ -99,6 +108,8 @@ open class DrawingSurfaceListener(
99108
val yOld: Float
100109
if (event.pointerCount == 1) {
101110
currentTool ?: return
111+
recentTouchEventsData.add(TouchEventData(event.eventTime, event.x, event.y))
112+
removeObsoleteTouchEventsData(event.eventTime)
102113
if (currentTool.handToolMode()) {
103114
disableAutoScroll()
104115
if (touchMode == TouchMode.PINCH) {
@@ -155,6 +166,7 @@ open class DrawingSurfaceListener(
155166
return false
156167
}
157168
timerStartDraw = System.currentTimeMillis()
169+
recentTouchEventsData.add(TouchEventData(event.eventTime, event.x, event.y))
158170
currentTool?.handleDown(canvasTouchPoint)
159171
if (autoScroll) {
160172
setEvenPointAndViewDimensionsForAutoScrollTask(view)
@@ -168,6 +180,22 @@ open class DrawingSurfaceListener(
168180
}
169181
if (touchMode == TouchMode.DRAW) {
170182
val drawingTime = System.currentTimeMillis() - timerStartDraw
183+
removeObsoleteTouchEventsData(event.eventTime)
184+
var dX = 0f
185+
var dY = 0f
186+
if (recentTouchEventsData.size > 1) {
187+
val oldestEntry = recentTouchEventsData[0]
188+
val distanceCorrectionX = event.x - oldestEntry.xCoordinate
189+
val distanceCorrectionY = event.y - oldestEntry.yCoordinate
190+
val distance = distanceCorrectionX * distanceCorrectionX + distanceCorrectionY * distanceCorrectionY
191+
if (distance < JITTER_DISTANCE_THRESHOLD * displayDensity && distance != 0f) {
192+
dX = distanceCorrectionX
193+
dY = distanceCorrectionY
194+
}
195+
}
196+
canvasTouchPoint.x = event.x - dX
197+
canvasTouchPoint.y = event.y - dY
198+
callback.convertToCanvasFromSurface(canvasTouchPoint)
171199
currentTool?.drawTime = drawingTime
172200
currentTool?.handleUp(canvasTouchPoint)
173201
} else {
@@ -185,6 +213,18 @@ open class DrawingSurfaceListener(
185213
return true
186214
}
187215

216+
private fun removeObsoleteTouchEventsData(timeStamp: Long) {
217+
val obsoleteTouchEventsData: MutableList<TouchEventData> = ArrayList()
218+
for (touchEventData in recentTouchEventsData) {
219+
if (timeStamp - touchEventData.timeStamp > JITTER_DELAY_THRESHOLD) {
220+
obsoleteTouchEventsData.add(touchEventData)
221+
} else {
222+
break
223+
}
224+
}
225+
recentTouchEventsData.removeAll(obsoleteTouchEventsData)
226+
}
227+
188228
open class AutoScrollTask(
189229
private val handler: Handler,
190230
private val callback: AutoScrollTaskCallback

0 commit comments

Comments
 (0)