blob: b7c5a8a328310e2117c312044a593d155706533f [file] [log] [blame]
/*
* Copyright 2012 AndroidPlot.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.androidplot.demos;
import java.text.DecimalFormat;
import java.util.Random;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Button;
import com.androidplot.Plot;
import com.androidplot.xy.BoundaryMode;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.SimpleXYSeries;
import com.androidplot.xy.XYPlot;
/***********************************
* @author David Buezas (david.buezas at gmail.com)
* Feel free to copy, modify and use the source as it fits you.
* 09/27/2012 nfellows - updated for 0.5.1 and made a few simplifications
*/
public class TouchZoomExampleActivity extends Activity implements OnTouchListener {
private static final int SERIES_SIZE = 200;
private XYPlot mySimpleXYPlot;
private Button resetButton;
private SimpleXYSeries[] series = null;
private PointF minXY;
private PointF maxXY;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.touch_zoom_example);
resetButton = (Button) findViewById(R.id.resetButton);
resetButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
minXY.x = series[0].getX(0).floatValue();
maxXY.x = series[3].getX(series[3].size() - 1).floatValue();
mySimpleXYPlot.setDomainBoundaries(minXY.x, maxXY.x, BoundaryMode.FIXED);
// pre 0.5.1 users should use postRedraw() instead.
mySimpleXYPlot.redraw();
}
});
mySimpleXYPlot = (XYPlot) findViewById(R.id.mySimpleXYPlot);
mySimpleXYPlot.setOnTouchListener(this);
mySimpleXYPlot.getGraphWidget().setTicksPerRangeLabel(2);
mySimpleXYPlot.getGraphWidget().setTicksPerDomainLabel(2);
mySimpleXYPlot.getGraphWidget().getBackgroundPaint().setColor(Color.TRANSPARENT);
mySimpleXYPlot.getGraphWidget().setRangeValueFormat(
new DecimalFormat("#####"));
mySimpleXYPlot.getGraphWidget().setDomainValueFormat(
new DecimalFormat("#####.#"));
mySimpleXYPlot.getGraphWidget().setRangeLabelWidth(25);
mySimpleXYPlot.setRangeLabel("");
mySimpleXYPlot.setDomainLabel("");
mySimpleXYPlot.setBorderStyle(Plot.BorderStyle.NONE, null, null);
//mySimpleXYPlot.disableAllMarkup();
series = new SimpleXYSeries[4];
int scale = 1;
for (int i = 0; i < 4; i++, scale *= 5) {
series[i] = new SimpleXYSeries("S" + i);
populateSeries(series[i], scale);
}
mySimpleXYPlot.addSeries(series[3],
new LineAndPointFormatter(Color.rgb(50, 0, 0), null,
Color.rgb(100, 0, 0), null));
mySimpleXYPlot.addSeries(series[2],
new LineAndPointFormatter(Color.rgb(50, 50, 0), null,
Color.rgb(100, 100, 0), null));
mySimpleXYPlot.addSeries(series[1],
new LineAndPointFormatter(Color.rgb(0, 50, 0), null,
Color.rgb(0, 100, 0), null));
mySimpleXYPlot.addSeries(series[0],
new LineAndPointFormatter(Color.rgb(0, 0, 0), null,
Color.rgb(0, 0, 150), null));
mySimpleXYPlot.redraw();
mySimpleXYPlot.calculateMinMaxVals();
minXY = new PointF(mySimpleXYPlot.getCalculatedMinX().floatValue(),
mySimpleXYPlot.getCalculatedMinY().floatValue());
maxXY = new PointF(mySimpleXYPlot.getCalculatedMaxX().floatValue(),
mySimpleXYPlot.getCalculatedMaxY().floatValue());
}
private void populateSeries(SimpleXYSeries series, int max) {
Random r = new Random();
for(int i = 0; i < SERIES_SIZE; i++) {
series.addLast(i, r.nextInt(max));
}
}
// Definition of the touch states
static final int NONE = 0;
static final int ONE_FINGER_DRAG = 1;
static final int TWO_FINGERS_DRAG = 2;
int mode = NONE;
PointF firstFinger;
float distBetweenFingers;
boolean stopThread = false;
@Override
public boolean onTouch(View arg0, MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: // Start gesture
firstFinger = new PointF(event.getX(), event.getY());
mode = ONE_FINGER_DRAG;
stopThread = true;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
case MotionEvent.ACTION_POINTER_DOWN: // second finger
distBetweenFingers = spacing(event);
// the distance check is done to avoid false alarms
if (distBetweenFingers > 5f) {
mode = TWO_FINGERS_DRAG;
}
break;
case MotionEvent.ACTION_MOVE:
if (mode == ONE_FINGER_DRAG) {
PointF oldFirstFinger = firstFinger;
firstFinger = new PointF(event.getX(), event.getY());
scroll(oldFirstFinger.x - firstFinger.x);
mySimpleXYPlot.setDomainBoundaries(minXY.x, maxXY.x,
BoundaryMode.FIXED);
mySimpleXYPlot.redraw();
} else if (mode == TWO_FINGERS_DRAG) {
float oldDist = distBetweenFingers;
distBetweenFingers = spacing(event);
zoom(oldDist / distBetweenFingers);
mySimpleXYPlot.setDomainBoundaries(minXY.x, maxXY.x,
BoundaryMode.FIXED);
mySimpleXYPlot.redraw();
}
break;
}
return true;
}
private void zoom(float scale) {
float domainSpan = maxXY.x - minXY.x;
float domainMidPoint = maxXY.x - domainSpan / 2.0f;
float offset = domainSpan * scale / 2.0f;
minXY.x = domainMidPoint - offset;
maxXY.x = domainMidPoint + offset;
minXY.x = Math.min(minXY.x, series[3].getX(series[3].size() - 3)
.floatValue());
maxXY.x = Math.max(maxXY.x, series[0].getX(1).floatValue());
clampToDomainBounds(domainSpan);
}
private void scroll(float pan) {
float domainSpan = maxXY.x - minXY.x;
float step = domainSpan / mySimpleXYPlot.getWidth();
float offset = pan * step;
minXY.x = minXY.x + offset;
maxXY.x = maxXY.x + offset;
clampToDomainBounds(domainSpan);
}
private void clampToDomainBounds(float domainSpan) {
float leftBoundary = series[0].getX(0).floatValue();
float rightBoundary = series[3].getX(series[3].size() - 1).floatValue();
// enforce left scroll boundary:
if (minXY.x < leftBoundary) {
minXY.x = leftBoundary;
maxXY.x = leftBoundary + domainSpan;
} else if (maxXY.x > series[3].getX(series[3].size() - 1).floatValue()) {
maxXY.x = rightBoundary;
minXY.x = rightBoundary - domainSpan;
}
}
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return (float) Math.hypot(x, y);
}
}