mirror of https://github.com/NekoX-Dev/NekoX.git
302 lines
11 KiB
Java
302 lines
11 KiB
Java
package org.telegram.ui.Charts;
|
|
|
|
import android.animation.ValueAnimator;
|
|
import android.graphics.Rect;
|
|
import android.view.MotionEvent;
|
|
|
|
import org.telegram.messenger.AndroidUtilities;
|
|
|
|
public class ChartPickerDelegate {
|
|
|
|
public boolean disabled;
|
|
Listener view;
|
|
|
|
public ChartPickerDelegate(Listener view) {
|
|
this.view = view;
|
|
}
|
|
|
|
|
|
private final static int CAPTURE_NONE = 0;
|
|
private final static int CAPTURE_LEFT = 1;
|
|
private final static int CAPTURE_RIGHT = 1 << 1;
|
|
private final static int CAPTURE_MIDDLE = 1 << 2;
|
|
public int pickerWidth;
|
|
public boolean tryMoveTo;
|
|
public float moveToX;
|
|
public float moveToY;
|
|
public long startTapTime;
|
|
ValueAnimator moveToAnimator;
|
|
|
|
public Rect leftPickerArea = new Rect();
|
|
public Rect rightPickerArea = new Rect();
|
|
public Rect middlePickerArea = new Rect();
|
|
|
|
|
|
public float pickerStart = 0.7f;
|
|
public float pickerEnd = 1f;
|
|
|
|
public float minDistance = 0.1f;
|
|
|
|
|
|
public CapturesData getMiddleCaptured() {
|
|
if (capturedStates[0] != null && capturedStates[0].state == CAPTURE_MIDDLE)
|
|
return capturedStates[0];
|
|
if (capturedStates[1] != null && capturedStates[1].state == CAPTURE_MIDDLE)
|
|
return capturedStates[1];
|
|
return null;
|
|
}
|
|
|
|
public CapturesData getLeftCaptured() {
|
|
if (capturedStates[0] != null && capturedStates[0].state == CAPTURE_LEFT)
|
|
return capturedStates[0];
|
|
if (capturedStates[1] != null && capturedStates[1].state == CAPTURE_LEFT)
|
|
return capturedStates[1];
|
|
return null;
|
|
}
|
|
|
|
public CapturesData getRightCaptured() {
|
|
if (capturedStates[0] != null && capturedStates[0].state == CAPTURE_RIGHT)
|
|
return capturedStates[0];
|
|
if (capturedStates[1] != null && capturedStates[1].state == CAPTURE_RIGHT)
|
|
return capturedStates[1];
|
|
return null;
|
|
}
|
|
|
|
|
|
class CapturesData {
|
|
public final int state;
|
|
public int capturedX;
|
|
public int lastMovingX;
|
|
public float start;
|
|
public float end;
|
|
|
|
ValueAnimator a;
|
|
ValueAnimator jumpToAnimator;
|
|
public float aValue = 0f;
|
|
|
|
public CapturesData(int state) {
|
|
this.state = state;
|
|
}
|
|
|
|
public void captured() {
|
|
a = ValueAnimator.ofFloat(0, 1f);
|
|
a.setDuration(600);
|
|
a.setInterpolator(BaseChartView.INTERPOLATOR);
|
|
a.addUpdateListener(animation -> {
|
|
aValue = (float) animation.getAnimatedValue();
|
|
view.invalidate();
|
|
});
|
|
a.start();
|
|
}
|
|
|
|
public void uncapture() {
|
|
if (a != null) a.cancel();
|
|
if (jumpToAnimator != null) jumpToAnimator.cancel();
|
|
}
|
|
}
|
|
|
|
CapturesData[] capturedStates = {null, null};
|
|
|
|
public boolean capture(int x, int y, int pointerIndex) {
|
|
if (disabled) {
|
|
return false;
|
|
}
|
|
if (pointerIndex == 0) {
|
|
if (leftPickerArea.contains(x, y)) {
|
|
if (capturedStates[0] != null) capturedStates[1] = capturedStates[0];
|
|
capturedStates[0] = new CapturesData(CAPTURE_LEFT);
|
|
capturedStates[0].start = pickerStart;
|
|
capturedStates[0].capturedX = x;
|
|
capturedStates[0].lastMovingX = x;
|
|
capturedStates[0].captured();
|
|
|
|
if (moveToAnimator != null) {
|
|
moveToAnimator.cancel();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if (rightPickerArea.contains(x, y)) {
|
|
if (capturedStates[0] != null) capturedStates[1] = capturedStates[0];
|
|
capturedStates[0] = new CapturesData(CAPTURE_RIGHT);
|
|
capturedStates[0].end = pickerEnd;
|
|
capturedStates[0].capturedX = x;
|
|
capturedStates[0].lastMovingX = x;
|
|
capturedStates[0].captured();
|
|
|
|
if (moveToAnimator != null) moveToAnimator.cancel();
|
|
return true;
|
|
}
|
|
|
|
|
|
if (middlePickerArea.contains(x, y)) {
|
|
capturedStates[0] = new CapturesData(CAPTURE_MIDDLE);
|
|
capturedStates[0].end = pickerEnd;
|
|
capturedStates[0].start = pickerStart;
|
|
capturedStates[0].capturedX = x;
|
|
capturedStates[0].lastMovingX = x;
|
|
capturedStates[0].captured();
|
|
if (moveToAnimator != null) moveToAnimator.cancel();
|
|
return true;
|
|
}
|
|
|
|
|
|
if (y < leftPickerArea.bottom && y > leftPickerArea.top) {
|
|
tryMoveTo = true;
|
|
moveToX = x;
|
|
moveToY = y;
|
|
startTapTime = System.currentTimeMillis();
|
|
if (moveToAnimator != null) {
|
|
if (moveToAnimator.isRunning()) {
|
|
view.onPickerJumpTo(pickerStart, pickerEnd, true);
|
|
}
|
|
moveToAnimator.cancel();
|
|
}
|
|
return true;
|
|
}
|
|
} else if (pointerIndex == 1) {
|
|
if (capturedStates[0] == null) return false;
|
|
if (capturedStates[0].state == CAPTURE_MIDDLE) return false;
|
|
|
|
|
|
if (leftPickerArea.contains(x, y) && capturedStates[0].state != CAPTURE_LEFT) {
|
|
capturedStates[1] = new CapturesData(CAPTURE_LEFT);
|
|
capturedStates[1].start = pickerStart;
|
|
capturedStates[1].capturedX = x;
|
|
capturedStates[1].lastMovingX = x;
|
|
capturedStates[1].captured();
|
|
if (moveToAnimator != null) moveToAnimator.cancel();
|
|
return true;
|
|
}
|
|
|
|
if (rightPickerArea.contains(x, y)) {
|
|
if (capturedStates[0].state == CAPTURE_RIGHT) return false;
|
|
capturedStates[1] = new CapturesData(CAPTURE_RIGHT);
|
|
capturedStates[1].end = pickerEnd;
|
|
capturedStates[1].capturedX = x;
|
|
capturedStates[1].lastMovingX = x;
|
|
capturedStates[1].captured();
|
|
if (moveToAnimator != null) moveToAnimator.cancel();
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public boolean captured() {
|
|
return capturedStates[0] != null || tryMoveTo;
|
|
}
|
|
|
|
public boolean move(int x, int y, int pointer) {
|
|
if (tryMoveTo) {
|
|
return false;
|
|
}
|
|
CapturesData d = capturedStates[pointer];
|
|
if (d == null) return false;
|
|
int capturedState = d.state;
|
|
float capturedStart = d.start;
|
|
float capturedEnd = d.end;
|
|
int capturedX = d.capturedX;
|
|
d.lastMovingX = x;
|
|
|
|
boolean notifyPicker = false;
|
|
if (capturedState == CAPTURE_LEFT) {
|
|
pickerStart = capturedStart - (capturedX - x) / (float) pickerWidth;
|
|
if (pickerStart < 0f) pickerStart = 0f;
|
|
if (pickerEnd - pickerStart < minDistance) pickerStart = pickerEnd - minDistance;
|
|
notifyPicker = true;
|
|
}
|
|
|
|
if (capturedState == CAPTURE_RIGHT) {
|
|
pickerEnd = capturedEnd - (capturedX - x) / (float) pickerWidth;
|
|
if (pickerEnd > 1f) pickerEnd = 1f;
|
|
if (pickerEnd - pickerStart < minDistance) pickerEnd = pickerStart + minDistance;
|
|
notifyPicker = true;
|
|
}
|
|
|
|
if (capturedState == CAPTURE_MIDDLE) {
|
|
pickerStart = capturedStart - (capturedX - x) / (float) pickerWidth;
|
|
pickerEnd = capturedEnd - (capturedX - x) / (float) pickerWidth;
|
|
if (pickerStart < 0f) {
|
|
pickerStart = 0f;
|
|
pickerEnd = capturedEnd - capturedStart;
|
|
}
|
|
|
|
if (pickerEnd > 1f) {
|
|
pickerEnd = 1f;
|
|
pickerStart = 1f - (capturedEnd - capturedStart);
|
|
}
|
|
|
|
notifyPicker = true;
|
|
}
|
|
if (notifyPicker) view.onPickerDataChanged();
|
|
return true;
|
|
}
|
|
|
|
public boolean uncapture(MotionEvent event, int pointerIndex) {
|
|
if (pointerIndex == 0) {
|
|
if (tryMoveTo) {
|
|
tryMoveTo = false;
|
|
float dx = moveToX - event.getX();
|
|
float dy = moveToY - event.getY();
|
|
if (event.getAction() == MotionEvent.ACTION_UP && System.currentTimeMillis() - startTapTime < 300 && Math.sqrt(dx * dx + dy * dy) < AndroidUtilities.dp(10)) {
|
|
|
|
float moveToX = (this.moveToX - BaseChartView.HORIZONTAL_PADDING) / pickerWidth;
|
|
float w = pickerEnd - pickerStart;
|
|
float moveToLeft = moveToX - w / 2f;
|
|
float moveToRight = moveToX + w / 2f;
|
|
if (moveToLeft < 0f) {
|
|
moveToLeft = 0;
|
|
moveToRight = w;
|
|
} else if (moveToRight > 1f) {
|
|
moveToLeft = 1f - w;
|
|
moveToRight = 1f;
|
|
|
|
}
|
|
float moveFromLeft = pickerStart;
|
|
float moveFromRight = pickerEnd;
|
|
|
|
moveToAnimator = ValueAnimator.ofFloat(0f, 1f);
|
|
float finalMoveToLeft = moveToLeft;
|
|
float finalMoveToRight = moveToRight;
|
|
view.onPickerJumpTo(finalMoveToLeft, finalMoveToRight,true);
|
|
moveToAnimator.addUpdateListener(animation -> {
|
|
float v = (float) animation.getAnimatedValue();
|
|
pickerStart = moveFromLeft + (finalMoveToLeft - moveFromLeft) * v;
|
|
pickerEnd = moveFromRight + (finalMoveToRight - moveFromRight) * v;
|
|
view.onPickerJumpTo(finalMoveToLeft, finalMoveToRight,false);
|
|
});
|
|
moveToAnimator.setInterpolator(BaseChartView.INTERPOLATOR);
|
|
moveToAnimator.start();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if (capturedStates[0] != null) capturedStates[0].uncapture();
|
|
capturedStates[0] = null;
|
|
if (capturedStates[1] != null) {
|
|
capturedStates[0] = capturedStates[1];
|
|
capturedStates[1] = null;
|
|
}
|
|
} else {
|
|
if (capturedStates[1] != null) capturedStates[1].uncapture();
|
|
capturedStates[1] = null;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public void uncapture() {
|
|
if (capturedStates[0] != null) capturedStates[0].uncapture();
|
|
if (capturedStates[1] != null) capturedStates[1].uncapture();
|
|
capturedStates[0] = null;
|
|
capturedStates[1] = null;
|
|
}
|
|
|
|
interface Listener {
|
|
void onPickerDataChanged();
|
|
void onPickerJumpTo(float start, float end, boolean force);
|
|
void invalidate();
|
|
}
|
|
|
|
}
|