Skip to content

Commit

Permalink
Split into components, expose scaledPan (#97)
Browse files Browse the repository at this point in the history
* Split into components

* Create MatrixManager

* Add documentation, rename classes

* Use @realZoOm for everything, compute zoom from rects

* Fix typo

* Create MatrixUpdate class and single function for applying updates

* Remove temporary comments

* Improvements

* Expose scaledPan, simplify updates

* Remove interfaces
  • Loading branch information
natario1 authored Mar 22, 2019
1 parent 8f37cfa commit 77ae189
Show file tree
Hide file tree
Showing 18 changed files with 1,957 additions and 1,286 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -340,8 +340,12 @@ In any case the current scale is not considered, so your system won't change if

|API|Description|Default value|
|---|-----------|-------------|
|`getPan()`|Returns the current pan as a point.|`-`|
|`getPanX()`|Returns the current horizontal pan.|`-`|
|`getPanY()`|Returns the current vertical pan.|`-`|
|`getScaledPan()`|Returns the current scaled pan as a point (pan * realZoom).|`-`|
|`getScaledPanX()`|Returns the current scaled horizontal pan (panX * realZoom).|`-`|
|`getScaledPanY()`|Returns the current scaled vertical pan (panY * realZoom).|`-`|
|`setOverScrollHorizontal(boolean)`|If true, the content will be allowed to pan outside its horizontal bounds, then return to its position.|`true`|
|`setOverScrollVertical(boolean)`|If true, the content will be allowed to pan outside its vertical bounds, then return to its position.|`true`|
|`setHorizontalPanEnabled(boolean)`|If true, the content will be allowed to pan **horizontally** by user input.|`true`|
Expand Down
14 changes: 13 additions & 1 deletion library/src/main/java/com/otaliastudios/zoom/AbsolutePoint.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.otaliastudios.zoom

/**
* This class represents an absolute point on the ZoomEngine canvas (or beyond it's bounds)
* This class represents a point on the [ZoomEngine] content surface.
*
* It is absolute because it is defined with respect to the content own size & coordinate system,
* meaning that 0, 0 represents the content top-left corner.
*/
data class AbsolutePoint(
@ZoomApi.AbsolutePan var x: Float = 0F,
Expand Down Expand Up @@ -72,4 +75,13 @@ data class AbsolutePoint(
return AbsolutePoint(factor.toFloat() * this.x, factor.toFloat() * this.y)
}

/**
* Returns a [ScaledPoint] for this point, assuming that
* the current zoom level is [scale].
*/
internal fun toScaled(scale: Float, outPoint: ScaledPoint = ScaledPoint()): ScaledPoint {
outPoint.set(x * scale, y * scale)
return outPoint
}

}
14 changes: 12 additions & 2 deletions library/src/main/java/com/otaliastudios/zoom/ScaledPoint.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package com.otaliastudios.zoom

/**
* This class represents a scaled point on the ZoomEngine canvas (or beyond it's bounds)
* This class represents a point on the [ZoomEngine] content surface.
*
* Note that these values depend on the current zoomlevel
* It is scaled because, unlike [AbsolutePoint], it is affected by the current zoom level.
* If content is zoomed in, the exact same content point will have bigger [ScaledPoint] coordinates.
*/
data class ScaledPoint(
@ZoomApi.ScaledPan var x: Float = 0F,
Expand Down Expand Up @@ -74,4 +75,13 @@ data class ScaledPoint(
return ScaledPoint(factor.toFloat() * this.x, factor.toFloat() * this.y)
}

/**
* Returns a [AbsolutePoint] for this point, assuming that
* the current zoom level is [scale].
*/
internal fun toAbsolute(scale: Float, outPoint: AbsolutePoint = AbsolutePoint()): AbsolutePoint {
outPoint.set(x / scale, y / scale)
return outPoint
}

}
52 changes: 48 additions & 4 deletions library/src/main/java/com/otaliastudios/zoom/ZoomApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ interface ZoomApi {
*/
@Zoom
val zoom: Float
// TODO (v2) rename to e.g. transformedZoom

/**
* Gets the current zoom value, including the base zoom that was eventually applied when
Expand All @@ -36,16 +37,15 @@ interface ZoomApi {
*/
@RealZoom
val realZoom: Float

// TODO (v2) rename to zoom

/**
* The current pan as an [AbsolutePoint].
* This field will be updated according to current pan when accessed.
*/
val pan: AbsolutePoint

/**
* Returns the current horizontal pan value, in content coordinates
* Returns the current horizontal pan value, in content absolute coordinates
* (that is, as if there was no zoom at all).
*
* @return the current horizontal pan
Expand All @@ -54,14 +54,40 @@ interface ZoomApi {
val panX: Float

/**
* Returns the current vertical pan value, in content coordinates
* Returns the current vertical pan value, in content absolute coordinates
* (that is, as if there was no zoom at all).
*
* @return the current vertical pan
*/
@AbsolutePan
val panY: Float

/**
* The current pan as a [ScaledPoint], that is, taking into account the current zoom.
* This basically returns the [pan] value multiplied by the current [realZoom].
*/
val scaledPan: ScaledPoint

/**
* Returns the current horizontal pan value, in content scaled coordinates
* (that is, including the current zoom).
* This is equivalent to [panX] multiplied by [realZoom].
*
* @return the current horizontal pan
*/
@ScaledPan
val scaledPanX: Float

/**
* Returns the current vertical pan value, in content scaled coordinates
* (that is, including the current zoom).
* This is equivalent to [panY] multiplied by [realZoom].
*
* @return the current vertical pan
*/
@ScaledPan
val scaledPanY: Float

/**
* Annotation to indicate a RealZoom value.
*
Expand All @@ -70,6 +96,7 @@ interface ZoomApi {
@Target(AnnotationTarget.FIELD, AnnotationTarget.FUNCTION, AnnotationTarget.LOCAL_VARIABLE, AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER)
@Retention(AnnotationRetention.SOURCE)
annotation class RealZoom
// TODO (v2) rename to Zoom

/**
* Annotation to indicate a zoom value.
Expand All @@ -79,6 +106,7 @@ interface ZoomApi {
@Target(AnnotationTarget.FIELD, AnnotationTarget.FUNCTION, AnnotationTarget.LOCAL_VARIABLE, AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER)
@Retention(AnnotationRetention.SOURCE)
annotation class Zoom
// TODO (v2) rename to e.g. TransformedZoom

/**
* Annotation to indicate an AbsolutePan value.
Expand Down Expand Up @@ -147,6 +175,7 @@ interface ZoomApi {
* @param overScroll whether to allow horizontal over scrolling
*/
fun setOverScrollHorizontal(overScroll: Boolean)
// TODO (v2) rename to var isHorizontalOverPanEnabled

/**
* Controls whether the content should be over-scrollable vertically.
Expand All @@ -156,20 +185,23 @@ interface ZoomApi {
* @param overScroll whether to allow vertical over scrolling
*/
fun setOverScrollVertical(overScroll: Boolean)
// TODO (v2) rename to var isVerticalOverPanEnabled

/**
* Controls whether horizontal panning using gestures is enabled.
*
* @param enabled true enables horizontal panning, false disables it
*/
fun setHorizontalPanEnabled(enabled: Boolean)
// TODO (v2) rename to var isHorizontalPanEnabled

/**
* Controls whether vertical panning using gestures is enabled.
*
* @param enabled true enables vertical panning, false disables it
*/
fun setVerticalPanEnabled(enabled: Boolean)
// TODO (v2) rename to var isVerticalPanEnabled

/**
* Controls whether the content should be overPinchable.
Expand All @@ -179,27 +211,31 @@ interface ZoomApi {
* @param overPinchable whether to allow over pinching
*/
fun setOverPinchable(overPinchable: Boolean)
// TODO (v2) rename to var isOverZoomEnabled

/**
* Controls whether zoom using pinch gesture is enabled or not.
*
* @param enabled true enables zooming, false disables it
*/
fun setZoomEnabled(enabled: Boolean)
// TODO (v2) rename to var isZoomEnabled

/**
* Controls whether fling gesture is enabled or not.
*
* @param enabled true enables fling gesture, false disables it
*/
fun setFlingEnabled(enabled: Boolean)
// TODO (v2) rename to var isFlingEnabled or isGestureFlingEnabled to clearly differentiate gestures and engine movements (pan/zoom)

/**
* Controls whether fling events are allowed when the view is in an overscrolled state.
*
* @param allow true allows fling in overscroll, false disables it
*/
fun setAllowFlingInOverscroll(allow: Boolean)
// TODO (v2) see what to do with this, either it works or it doesn't

/**
* Sets the base transformation to be applied to the content.
Expand Down Expand Up @@ -244,6 +280,7 @@ interface ZoomApi {
* @param animate whether to animate the transition
*/
fun moveTo(@Zoom zoom: Float, @AbsolutePan x: Float, @AbsolutePan y: Float, animate: Boolean)
// TODO (v2) revisit these control APIs, possibly leveraging MatrixUpdate syntax and using AbsolutePoint

/**
* Pans the content until the top-left coordinates match the given x-y
Expand Down Expand Up @@ -277,6 +314,7 @@ interface ZoomApi {
* @param animate whether to animate the transition
*/
fun zoomTo(@Zoom zoom: Float, animate: Boolean)
// TODO (v2) if not removed, rename to e.g. transformedZoomTo

/**
* Applies the given factor to the current zoom.
Expand All @@ -303,6 +341,7 @@ interface ZoomApi {
* @param animate whether to animate the transition
*/
fun realZoomTo(@RealZoom realZoom: Float, animate: Boolean)
// TODO (v2) if not removed, rename to zoomTo

/**
* Which is the max zoom that should be allowed.
Expand Down Expand Up @@ -355,6 +394,7 @@ interface ZoomApi {
* @see realZoom
*/
const val TYPE_ZOOM = 0
// TODO (v2) rename to e.g. TYPE_TRANSFORMED_ZOOM

/**
* Flag for zoom constraints and settings.
Expand All @@ -365,6 +405,7 @@ interface ZoomApi {
* @see realZoom
*/
const val TYPE_REAL_ZOOM = 1
// TODO (v2) rename to e.g. TYPE_ZOOM

/**
* Constant for [ZoomApi.setTransformation].
Expand Down Expand Up @@ -393,6 +434,9 @@ interface ZoomApi {
*/
const val TRANSFORMATION_GRAVITY_AUTO = 0


// TODO (v2) move these below into the engine as they are engine defaults

/**
* The default [setMinZoom] applied by the engine if none is specified.
*/
Expand Down
Loading

0 comments on commit 77ae189

Please sign in to comment.