Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:

# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
- image: circleci/android:api-26-alpha
- image: circleci/android:api-28-alpha

working_directory: ~/repo

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ protected void drawSegment(Canvas canvas, RectF bounds, Segment seg, SegmentForm
canvas.drawLine(r1Inner.x, r1Inner.y, r1Outer.x, r1Outer.y, f.getRadialEdgePaint());
canvas.drawLine(r2Inner.x, r2Inner.y, r2Outer.x, r2Outer.y, f.getRadialEdgePaint());
} else {
canvas.save(Canvas.CLIP_SAVE_FLAG);
canvas.save();
Path chart = new Path();
chart.addCircle(cx, cy, outerRad, Path.Direction.CW);
Path inside = new Path();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public void draw(Canvas canvas) throws PlotRenderException {
}
for (Widget widget : elements()) {
try {
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.save();
PositionMetrics metrics = widget.getPositionMetrics();
float elementWidth = widget.getWidthPix(displayDims.paddedRect.width());
float elementHeight = widget.getHeightPix(displayDims.paddedRect.height());
Expand Down Expand Up @@ -140,7 +140,7 @@ public void draw(Canvas canvas) throws PlotRenderException {

private static void drawSpacing(Canvas canvas, RectF outer, RectF inner, Paint paint) {
try {
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.save();
canvas.clipRect(inner, Region.Op.DIFFERENCE);
canvas.drawRect(outer, paint);
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ protected abstract void onRender(Canvas canvas, RectF plotArea, SeriesType serie

public void drawSeriesLegendIcon(Canvas canvas, RectF rect, SeriesFormatterType formatter) {
try {
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.save();
canvas.clipRect(rect, Region.Op.INTERSECT);
doDrawLegendIcon(canvas, rect, formatter);
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public void doOnDraw(Canvas canvas, RectF widgetRect) {
Anchor.CENTER);

try {
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.save();
canvas.translate(start.x, start.y);
switch (orientation) {
case HORIZONTAL:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ protected void renderPath(Canvas canvas, RectF plotArea, Path path, PointF first
RectF thisRegionRectF = thisRegionTransformed.asRectF();
if (thisRegionRectF != null) {
try {
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.save();
canvas.clipPath(path);
canvas.drawRect(thisRegionRectF, regionFormatter.getPaint());
} finally {
Expand Down
82 changes: 69 additions & 13 deletions androidplot-core/src/main/java/com/androidplot/xy/PanZoom.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

import android.graphics.RectF;
import android.graphics.PointF;
import android.support.annotation.NonNull;
import android.view.*;

import com.androidplot.*;
import com.androidplot.util.*;

import java.io.Serializable;
import java.util.*;

/**
Expand Down Expand Up @@ -35,6 +37,7 @@ public class PanZoom implements View.OnTouchListener {
// rectangle created by the space between two fingers
protected RectF fingersRect;
private View.OnTouchListener delegate;
private State state = new State();

// Definition of the touch states
protected enum DragState {
Expand Down Expand Up @@ -95,29 +98,83 @@ public enum ZoomLimit {
MIN_TICKS
}

protected PanZoom(XYPlot plot, Pan pan, Zoom zoom) {
// TODO: consider making this immutable / threadsafe
public static class State implements Serializable {
private Number domainLowerBoundary;
private Number domainUpperBoundary;
private Number rangeLowerBoundary;
private Number rangeUpperBoundary;
private BoundaryMode domainBoundaryMode;
private BoundaryMode rangeBoundaryMode;

public void setDomainBoundaries(Number lowerBoundary, Number upperBoundary, BoundaryMode mode) {
this.domainLowerBoundary = lowerBoundary;
this.domainUpperBoundary = upperBoundary;
this.domainBoundaryMode = mode;
}

public void setRangeBoundaries(Number lowerBoundary, Number upperBoundary, BoundaryMode mode) {
this.rangeLowerBoundary = lowerBoundary;
this.rangeUpperBoundary = upperBoundary;
this.rangeBoundaryMode = mode;
}

public void applyDomainBoundaries(@NonNull XYPlot plot) {
plot.setDomainBoundaries(domainLowerBoundary, domainUpperBoundary, domainBoundaryMode);
}

public void applyRangeBoundaries(@NonNull XYPlot plot) {
plot.setRangeBoundaries(rangeLowerBoundary, rangeUpperBoundary, rangeBoundaryMode);
}

public void apply(@NonNull XYPlot plot) {
applyDomainBoundaries(plot);
applyRangeBoundaries(plot);
}
}

protected PanZoom(@NonNull XYPlot plot, Pan pan, Zoom zoom) {
this.plot = plot;
this.pan = pan;
this.zoom = zoom;
this.zoomLimit = ZoomLimit.OUTER;
}

// additional constructor not to break api
protected PanZoom(XYPlot plot, Pan pan, Zoom zoom, ZoomLimit limit) {
protected PanZoom(@NonNull XYPlot plot, Pan pan, Zoom zoom, ZoomLimit limit) {
this.plot = plot;
this.pan = pan;
this.zoom = zoom;
this.zoomLimit = limit;
}

public State getState() {
return this.state;
}

public void setState(@NonNull State state) {
this.state = state;
state.apply(plot);
}

protected void adjustRangeBoundary(Number lower, Number upper, BoundaryMode mode) {
state.setRangeBoundaries(lower, upper, mode);
state.applyRangeBoundaries(plot);
}

protected void adjustDomainBoundary(Number lower, Number upper, BoundaryMode mode) {
state.setDomainBoundaries(lower, upper, mode);
state.applyDomainBoundaries(plot);
}

/**
* Convenience method for enabling pan/zoom behavior on an instance of {@link XYPlot}, using
* a default behavior of {@link Pan#BOTH} and {@link Zoom#SCALE}.
* Use {@link PanZoom#attach(XYPlot, Pan, Zoom, ZoomLimit)} for finer grain control of this behavior.
* @param plot
* @return
*/
public static PanZoom attach(XYPlot plot) {
public static PanZoom attach(@NonNull XYPlot plot) {
return attach(plot, Pan.BOTH, Zoom.SCALE);
}

Expand All @@ -130,7 +187,7 @@ public static PanZoom attach(XYPlot plot) {
* @param zoom
* @return
*/
public static PanZoom attach(XYPlot plot, Pan pan, Zoom zoom) {
public static PanZoom attach(@NonNull XYPlot plot, @NonNull Pan pan, @NonNull Zoom zoom) {
return attach(plot,pan,zoom, ZoomLimit.OUTER);
}

Expand All @@ -142,7 +199,7 @@ public static PanZoom attach(XYPlot plot, Pan pan, Zoom zoom) {
* @param limit
* @return
*/
public static PanZoom attach(XYPlot plot, Pan pan, Zoom zoom, ZoomLimit limit) {
public static PanZoom attach(@NonNull XYPlot plot, @NonNull Pan pan, @NonNull Zoom zoom, @NonNull ZoomLimit limit) {
PanZoom pz = new PanZoom(plot, pan, zoom, limit);
plot.setOnTouchListener(pz);
return pz;
Expand Down Expand Up @@ -237,12 +294,12 @@ protected void pan(final MotionEvent motionEvent) {
if (EnumSet.of(Pan.HORIZONTAL, Pan.BOTH).contains(pan)) {
Region newBounds = new Region();
calculatePan(oldFirstFinger, newBounds, true);
plot.setDomainBoundaries(newBounds.getMin(), newBounds.getMax(), BoundaryMode.FIXED);
adjustDomainBoundary(newBounds.getMin(), newBounds.getMax(), BoundaryMode.FIXED);
}
if (EnumSet.of(Pan.VERTICAL, Pan.BOTH).contains(pan)) {
Region newBounds = new Region();
calculatePan(oldFirstFinger, newBounds, false);
plot.setRangeBoundaries(newBounds.getMin(), newBounds.getMax(), BoundaryMode.FIXED);
adjustRangeBoundary(newBounds.getMin(), newBounds.getMax(), BoundaryMode.FIXED);
}

plot.redraw();
Expand Down Expand Up @@ -291,10 +348,9 @@ protected void calculatePan(final PointF oldFirstFinger, Region bounds, final bo
}

protected boolean isValidScale(float scale) {
if (Float.isInfinite(scale) || Float.isNaN(scale) || scale > -0.001 && scale < 0.001) {
return false;
}
return true;
return !Float.isInfinite(scale)
&& !Float.isNaN(scale)
&& (!(scale > -0.001) || !(scale < 0.001));
}

protected void zoom(final MotionEvent motionEvent) {
Expand Down Expand Up @@ -349,14 +405,14 @@ protected void zoom(final MotionEvent motionEvent) {
Zoom.STRETCH_BOTH,
Zoom.SCALE).contains(zoom)) {
calculateZoom(newRect, scaleX, true);
plot.setDomainBoundaries(newRect.left, newRect.right, BoundaryMode.FIXED);
adjustDomainBoundary(newRect.left, newRect.right, BoundaryMode.FIXED);
}
if (EnumSet.of(
Zoom.STRETCH_VERTICAL,
Zoom.STRETCH_BOTH,
Zoom.SCALE).contains(zoom)) {
calculateZoom(newRect, scaleY, false);
plot.setRangeBoundaries(newRect.top, newRect.bottom, BoundaryMode.FIXED);
adjustRangeBoundary(newRect.top, newRect.bottom, BoundaryMode.FIXED);
}
plot.redraw();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,7 @@ protected void drawData(Canvas canvas) throws PlotRenderException {
}
try {
if (isGridClippingEnabled) {
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.save();
canvas.clipRect(gridRect, android.graphics.Region.Op.INTERSECT);
}

Expand Down
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ allprojects {
}

ext {
theCompileSdkVersion = 26
theTargetSdkVersion = 26
theCompileSdkVersion = 28
theTargetSdkVersion = 28
theMinSdkVersion = 5
theVersionName = '1.5.5'
theVersionName = '1.5.6'
theVersionCode = 0
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015 AndroidPlot.com
* Copyright 2018 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -21,7 +21,6 @@
import android.os.Bundle;
import android.support.annotation.NonNull;

import com.androidplot.ui.Insets;
import com.androidplot.util.PixelUtils;
import com.androidplot.xy.CatmullRomInterpolator;
import com.androidplot.xy.LineAndPointFormatter;
Expand Down Expand Up @@ -49,7 +48,7 @@ public void onCreate(Bundle savedInstanceState)
setContentView(R.layout.simple_xy_plot_example);

// initialize our XYPlot reference:
plot = (XYPlot) findViewById(R.id.plot);
plot = findViewById(R.id.plot);

// create a couple arrays of y-values to plot:
final Number[] domainLabels = {1, 2, 3, 6, 7, 8, 9, 10, 13, 14};
Expand Down Expand Up @@ -101,19 +100,5 @@ public Object parseObject(String source, @NonNull ParsePosition pos) {
return null;
}
});

new Thread(new Runnable() {

@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
plot.getGraph().setGridInsets(new Insets(120, 120, 120, 120));
plot.redraw();
}
}).start();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ public void onNothingSelected(AdapterView<?> parent) {
}
});


zoomSpinner.setAdapter(
new ArrayAdapter<>(this, R.layout.spinner_item, PanZoom.Zoom.values()));
zoomSpinner.setSelection(panZoom.getZoom().ordinal());
Expand All @@ -167,5 +168,19 @@ public void onNothingSelected(AdapterView<?> parent) {
}
});
}

// (optional) save the current pan/zoom state
@Override
public void onSaveInstanceState(Bundle bundle) {
bundle.putSerializable("pan-zoom-state", panZoom.getState());
}

// (optional) restore the previously saved pan/zoom state
@Override
public void onRestoreInstanceState(Bundle bundle) {
PanZoom.State state = (PanZoom.State) bundle.getSerializable("pan-zoom-state");
panZoom.setState(state);
plot.redraw();
}
}

2 changes: 1 addition & 1 deletion docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ To use the library in your gradle project add the following to your build.gradle

```groovy
dependencies {
compile "com.androidplot:androidplot-core:1.5.5"
compile "com.androidplot:androidplot-core:1.5.6"
}
```

Expand Down
5 changes: 5 additions & 0 deletions docs/release_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
For details on what to expect in general when updating to a new version of Androiplot, check out the
[versioning doc](versioning.md).

# 1.5.6

* Adds convenience methods for saving / restoring `PanZoom` state.
* (#80) Targets SDK 28, fixing compatibility issues.

# 1.5.5

* (#76) Fixed a bug that could cause a deadlock when grid steps are much larger than actual plot range.
Expand Down
19 changes: 19 additions & 0 deletions docs/xyplot.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,25 @@ then the plot will pan and zoom on both axes infinitely. To set the plot's oute
plot.getOuterLimits().set(0, 100, 0, 100);
```

# Saving & Restoring PanZoom State
The `PanZoom` class provides convenience methods for saving and restoring state from your `Activity`:

```java
// save the current pan/zoom state
@Override
public void onSaveInstanceState(Bundle bundle) {
bundle.putSerializable("pan-zoom-state", panZoom.getState());
}

// restore the previously saved pan/zoom state
@Override
public void onRestoreInstanceState(Bundle bundle) {
PanZoom.State state = (PanZoom.State) bundle.getSerializable("pan-zoom-state");
panZoom.setState(state);
plot.redraw();
}
```

For a more detailed look at pan & zoom behavior, check out the [Touch Zoom Example source code](../demoapp/src/main/java/com/androidplot/demos/TouchZoomExampleActivity.java).

# Series Renderers
Expand Down