Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Paintroid 434: zoom window settings #1155

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Paintroid/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ dependencies {
implementation 'androidx.exifinterface:exifinterface:1.3.2'
implementation 'com.esotericsoftware:kryo:5.1.1'
implementation 'id.zelory:compressor:2.1.1'
androidTestImplementation project(path: ':Paintroid')
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'

debugImplementation 'androidx.multidex:multidex:2.0.0'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package org.catrobat.paintroid.test.espresso

import android.os.Build
import android.widget.RelativeLayout
import androidx.test.espresso.Espresso.onView
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.rule.ActivityTestRule
import org.catrobat.paintroid.MainActivity
import org.catrobat.paintroid.test.espresso.util.wrappers.DrawingSurfaceInteraction.onDrawingSurfaceView
import org.catrobat.paintroid.test.espresso.util.wrappers.ToolBarViewInteraction
import org.catrobat.paintroid.tools.ToolType
import org.junit.Before
import org.junit.Rule
import org.junit.runner.RunWith
import org.catrobat.paintroid.R
import org.junit.Test
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
import androidx.test.espresso.matcher.ViewMatchers.withId
import org.catrobat.paintroid.test.espresso.util.DrawingSurfaceLocationProvider
import org.catrobat.paintroid.test.espresso.util.UiInteractions.PressAndReleaseActions.tearDownPressAndRelease
import org.catrobat.paintroid.test.espresso.util.UiInteractions.PressAndReleaseActions.pressAction
import org.catrobat.paintroid.test.espresso.util.UiInteractions.PressAndReleaseActions.releaseAction
import org.catrobat.paintroid.test.espresso.util.wrappers.ZoomWindowInteraction.onZoomWindow
import org.junit.After

@RunWith(AndroidJUnit4::class)
class ZoomWindowIntegrationTest {

@get:Rule
val launchActivityRule = ActivityTestRule(MainActivity::class.java)
@Before
fun setUp() {
ToolBarViewInteraction.onToolBarView()
.performSelectTool(ToolType.BRUSH)
}

@After
fun tearDown() {
tearDownPressAndRelease()
}

@Test
fun windowAppearsWhenDrawingSurfaceIsTouched() {
onDrawingSurfaceView()
.perform(pressAction(DrawingSurfaceLocationProvider.MIDDLE))

onView(withId(R.id.pocketpaint_zoom_window))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))

onDrawingSurfaceView()
.perform(releaseAction())
}

@Test
fun windowDisappearsWhenDrawingSurfaceIsPressedAndReleased() {
onDrawingSurfaceView()
.perform(pressAction(DrawingSurfaceLocationProvider.MIDDLE))

onDrawingSurfaceView()
.perform(releaseAction())

onView(withId(R.id.pocketpaint_zoom_window))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
}

@Test
fun windowAppearsOnRightWhenClickedAtTheTopLeft() {
onDrawingSurfaceView()
.perform(pressAction(DrawingSurfaceLocationProvider.HALFWAY_TOP_LEFT))

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
onZoomWindow()
.checkAlignment(RelativeLayout.ALIGN_PARENT_RIGHT)
} else {
// Layout params rules for ALIGN_PARENT_LEFT and ALIGN_PARENT_RIGHT from
// https://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams#getRules()
// for API level less than M
onZoomWindow()
.checkAlignmentBelowM(11)
}

onDrawingSurfaceView()
.perform(releaseAction())
}

@Test
fun windowAppearsOnLeftWhenClickedAnywhere() {
onDrawingSurfaceView()
.perform(pressAction(DrawingSurfaceLocationProvider.MIDDLE))

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
onZoomWindow()
.checkAlignment(RelativeLayout.ALIGN_PARENT_LEFT)
} else {
onZoomWindow()
.checkAlignmentBelowM(9)
}

onDrawingSurfaceView()
.perform(releaseAction())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import static androidx.test.espresso.action.ViewActions.actionWithAssertions;
import static androidx.test.espresso.matcher.ViewMatchers.assertThat;
import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayingAtLeast;
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;

Expand Down Expand Up @@ -298,4 +299,72 @@ public Status sendTap(UiController uiController, float[] coordinates, float[] pr
MotionEvent.BUTTON_PRIMARY);
}
}

public static class PressAndReleaseActions {

static MotionEvent motionEvent = null;

public static PressAction pressAction(DrawingSurfaceLocationProvider coordinates) {
return new PressAction(coordinates);
}

public static ReleaseAction releaseAction() {
return new ReleaseAction();
}

public static void tearDownPressAndRelease() {
motionEvent = null;
}

public static class PressAction implements ViewAction {

DrawingSurfaceLocationProvider coordinates;

PressAction(DrawingSurfaceLocationProvider coords) {
this.coordinates = coords;
}

@Override
public Matcher<View> getConstraints() {
return isDisplayingAtLeast(90);
}

@Override
public String getDescription() {
return "Press Action";
}

@Override
public void perform(UiController uiController, View view) {
if (motionEvent != null) {
throw new AssertionError("Only one view can be held at a time");
}
float[] coords = coordinates.calculateCoordinates(view);
float[] precision = Press.FINGER.describePrecision();

motionEvent = MotionEvents.sendDown(uiController, coords, precision).down;
}
}

public static class ReleaseAction implements ViewAction {

@Override
public Matcher<View> getConstraints() {
return isDisplayingAtLeast(90);
}

@Override
public String getDescription() {
return "Release";
}

@Override
public void perform(UiController uiController, View view) {
if (motionEvent == null) {
throw new AssertionError("Only one view can be held at a time");
}
MotionEvents.sendUp(uiController, motionEvent);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package org.catrobat.paintroid.test.espresso.util.wrappers;

import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.withId;

import static org.catrobat.paintroid.test.espresso.util.MainActivityHelper.getMainActivityFromView;

import android.view.View;
import android.widget.RelativeLayout;

import org.catrobat.paintroid.MainActivity;
import org.catrobat.paintroid.R;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;

public final class ZoomWindowInteraction extends CustomViewInteraction {

private ZoomWindowInteraction() {
super(onView(withId(R.id.pocketpaint_zoom_window)));
}

public static ZoomWindowInteraction onZoomWindow() {
return new ZoomWindowInteraction();
}

public ZoomWindowInteraction checkAlignment(final int verb) {
check(matches(new TypeSafeMatcher<View>() {
@Override
protected boolean matchesSafely(View view) {
MainActivity activity = getMainActivityFromView(view);
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)
activity.findViewById(R.id.pocketpaint_zoom_window_inner).getLayoutParams();

int rulesFromLayout = layoutParams.getRule(verb);

return rulesFromLayout == -1;
}

@Override
public void describeTo(Description description) {
String alignedAccordingTo =
(verb == RelativeLayout.ALIGN_PARENT_LEFT) ? "left" : "right";
description.appendText("The zoom window is aligned to the " + alignedAccordingTo);
}
}));
return this;
}

public ZoomWindowInteraction checkAlignmentBelowM(final int index) {
check(matches(new TypeSafeMatcher<View>() {
@Override
protected boolean matchesSafely(View view) {
MainActivity activity = getMainActivityFromView(view);
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)
activity.findViewById(R.id.pocketpaint_zoom_window_inner).getLayoutParams();

int[] rulesFromLayout = layoutParams.getRules();

return rulesFromLayout[index] == -1;
}

@Override
public void describeTo(Description description) {
String alignedAccordingTo = index == 11 ? "right" : "left";
description.appendText("The zoom window is aligned to " + alignedAccordingTo);
}
}));
return this;
}
}
20 changes: 19 additions & 1 deletion Paintroid/src/main/java/org/catrobat/paintroid/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ import org.catrobat.paintroid.ui.viewholder.BottomNavigationViewHolder
import org.catrobat.paintroid.ui.viewholder.DrawerLayoutViewHolder
import org.catrobat.paintroid.ui.viewholder.LayerMenuViewHolder
import org.catrobat.paintroid.ui.viewholder.TopBarViewHolder
import org.catrobat.paintroid.ui.zoomwindow.DefaultZoomWindowController
import java.io.File
import java.util.Locale

Expand All @@ -128,6 +129,9 @@ class MainActivity : AppCompatActivity(), MainView, CommandListener {

var idlingResource: CountingIdlingResource = CountingIdlingResource("MainIdleResource")

@VisibleForTesting
lateinit var zoomWindowController: DefaultZoomWindowController

lateinit var commandManager: CommandManager
lateinit var toolPaint: ToolPaint
lateinit var bottomNavigationViewHolder: BottomNavigationViewHolder
Expand Down Expand Up @@ -371,6 +375,10 @@ class MainActivity : AppCompatActivity(), MainView, CommandListener {
R.id.pocketpaint_options_about -> presenterMain.showAboutClicked()
R.id.pocketpaint_share_image_button -> presenterMain.shareImageClicked()
R.id.pocketpaint_options_feedback -> presenterMain.sendFeedback()
R.id.pocketpaint_zoom_window_settings ->
presenterMain.showZoomWindowSettingsClicked(
UserPreferences(getPreferences(MODE_PRIVATE))
)
R.id.pocketpaint_advanced_settings -> presenterMain.showAdvancedSettingsClicked()
android.R.id.home -> presenterMain.backToPocketCodeClicked()
else -> return false
Expand Down Expand Up @@ -443,6 +451,14 @@ class MainActivity : AppCompatActivity(), MainView, CommandListener {
listener,
CommandSerializationUtilities(this, commandManager, model)
)
zoomWindowController = DefaultZoomWindowController(
this,
layerModel,
workspace,
toolReference,
UserPreferences(getPreferences(MODE_PRIVATE))
)
model = MainActivityModel()
defaultToolController = DefaultToolController(
toolReference,
toolOptionsViewController,
Expand Down Expand Up @@ -515,7 +531,9 @@ class MainActivity : AppCompatActivity(), MainView, CommandListener {
toolReference,
idlingResource,
supportFragmentManager,
toolOptionsViewController
toolOptionsViewController,
zoomWindowController,
UserPreferences(getPreferences(MODE_PRIVATE))
)
layerPresenter.setDrawingSurface(drawingSurface)
appFragment.perspective = perspective
Expand Down
27 changes: 27 additions & 0 deletions Paintroid/src/main/java/org/catrobat/paintroid/UserPreferences.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@ package org.catrobat.paintroid
import android.content.SharedPreferences
import org.catrobat.paintroid.common.IMAGE_NUMBER_SHARED_PREFERENCES_TAG
import org.catrobat.paintroid.common.SHOW_LIKE_US_DIALOG_SHARED_PREFERENCES_TAG
import org.catrobat.paintroid.common.ZOOM_WINDOW_ENABLED_SHARED_PREFERENCES_TAG
import org.catrobat.paintroid.common.ZOOM_WINDOW_ZOOM_PERCENTAGE_SHARED_PREFERENCES_TAG

open class UserPreferences(var preferences: SharedPreferences) {

open val preferenceLikeUsDialogValue: Boolean
get() = preferences.getBoolean(SHOW_LIKE_US_DIALOG_SHARED_PREFERENCES_TAG, false)
open var preferenceImageNumber: Int
Expand All @@ -33,11 +36,35 @@ open class UserPreferences(var preferences: SharedPreferences) {
.putInt(IMAGE_NUMBER_SHARED_PREFERENCES_TAG, value)
.apply()
}
open var preferenceZoomWindowEnabled: Boolean
get() = preferences.getBoolean(ZOOM_WINDOW_ENABLED_SHARED_PREFERENCES_TAG, true)
set(value) {
preferences
.edit()
.putBoolean(ZOOM_WINDOW_ENABLED_SHARED_PREFERENCES_TAG, value)
.apply()
}

open var preferenceZoomWindowZoomPercentage: Int
get() = preferences.getInt(
ZOOM_WINDOW_ZOOM_PERCENTAGE_SHARED_PREFERENCES_TAG,
initialZoomPercent
)
set(value) {
preferences
.edit()
.putInt(ZOOM_WINDOW_ZOOM_PERCENTAGE_SHARED_PREFERENCES_TAG, value)
.apply()
}

open fun setPreferenceLikeUsDialogValue() {
preferences
.edit()
.putBoolean(SHOW_LIKE_US_DIALOG_SHARED_PREFERENCES_TAG, true)
.apply()
}

companion object {
const val initialZoomPercent: Int = 100
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const val ABOUT_DIALOG_FRAGMENT_TAG = "aboutdialogfragment"
const val LIKE_US_DIALOG_FRAGMENT_TAG = "likeusdialogfragment"
const val RATE_US_DIALOG_FRAGMENT_TAG = "rateusdialogfragment"
const val FEEDBACK_DIALOG_FRAGMENT_TAG = "feedbackdialogfragment"
const val ZOOM_WINDOW_SETTINGS_DIALOG_FRAGMENT_TAG = "zoomwindowsettingsdialogfragment"
const val ADVANCED_SETTINGS_DIALOG_FRAGMENT_TAG = "advancedsettingsdialogfragment"
const val SAVE_DIALOG_FRAGMENT_TAG = "savedialogerror"
const val LOAD_DIALOG_FRAGMENT_TAG = "loadbitmapdialogerror"
Expand All @@ -43,6 +44,8 @@ const val CATROBAT_INFORMATION_DIALOG_TAG = "catrobatinformationdialogfragment"
const val CATROID_MEDIA_GALLERY_FRAGMENT_TAG = "catroidmediagalleryfragment"
const val PERMISSION_DIALOG_FRAGMENT_TAG = "permissiondialogfragment"
const val SHOW_LIKE_US_DIALOG_SHARED_PREFERENCES_TAG = "showlikeusdialog"
const val ZOOM_WINDOW_ENABLED_SHARED_PREFERENCES_TAG = "zoomwindowenabled"
const val ZOOM_WINDOW_ZOOM_PERCENTAGE_SHARED_PREFERENCES_TAG = "zoomwindowzoompercentage"
const val IMAGE_NUMBER_SHARED_PREFERENCES_TAG = "imagenumbertag"
const val SCALE_IMAGE_FRAGMENT_TAG = "showscaleimagedialog"
const val INDETERMINATE_PROGRESS_DIALOG_TAG = "indeterminateprogressdialogfragment"
Expand Down
Loading