Skip to content

Commit

Permalink
Add mouse actions.
Browse files Browse the repository at this point in the history
  • Loading branch information
rolfl committed Sep 10, 2015
1 parent 3ebb59a commit b76e137
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 8 deletions.
80 changes: 74 additions & 6 deletions src/net/tuis/mandelbrot/Mandy.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ComponentAdapter;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayDeque;
import java.util.Deque;
Expand Down Expand Up @@ -45,17 +48,18 @@ public static void main(String[] args) {

private final BlockingQueue<WindowState> stateq = new LinkedBlockingQueue<>();
private final JLabel canvas = new JLabel();
private final JSpinner zoom = new JSpinner(new SpinnerNumberModel(0.0, -1.0, 150, 0.1));
private final JSpinner limit = new JSpinner(new SpinnerNumberModel(100, 10, 100000, 10));
private final SpinnerNumberModel zoomModel = new SpinnerNumberModel(0.0, -1.0, 150, 0.1);
private final SpinnerNumberModel realModel = new SpinnerNumberModel(0.0, -2.5, 1.0, 0.1);
private final SpinnerNumberModel imaginaryModel = new SpinnerNumberModel(0.0, -1.5, 1.5, 0.1);
private final JSpinner limit = new JSpinner(new SpinnerNumberModel(100, 10, 100000, 10));
private final JSpinner zoom = new JSpinner(zoomModel);
private final JSpinner real = new JSpinner(realModel);
private final JSpinner imaginary = new JSpinner(imaginaryModel);
private final JLabel actualSpan = new JLabel();
private final JLabel actualZoom = new JLabel();

// only ever changed on the EDT
private final AtomicReference<WindowState> currentState = new AtomicReference<>(new WindowState(0, 0, 0, 0, 0, 0));
private final AtomicReference<WindowState> currentState = new AtomicReference<>(new WindowState(0, 0, 0, 0, 0, 0, 0));

Mandy() {
super("Mandelbrot Navigator");
Expand Down Expand Up @@ -98,6 +102,70 @@ public void componentResized(java.awt.event.ComponentEvent e) {
}
});

MouseAdapter mouse = new MouseAdapter() {
private int sx, sy;
private boolean active = false;
@Override
public void mouseDragged(MouseEvent e) {
if (!active) {
return;
}
int x = e.getX();
int y = e.getY();
int dx = x - sx;
int dy = y - sy;
WindowState state = currentState.get();
if (state == null) {
return;
}
realModel.setValue(state.getFocusX() - dx * state.getStep());
imaginaryModel.setValue(state.getFocusY() - dy * state.getStep());
sx = x;
sy = y;
checkState();
}
@Override
public void mousePressed(MouseEvent e) {
active = e.getModifiersEx() == MouseEvent.BUTTON1_DOWN_MASK;
sx = e.getX();
sy = e.getY();
}

@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2 && e.getButton() == 1) {
// center on click point.
WindowState state = currentState.get();
if (state == null) {
return;
}
int dx = state.getPixWidth() / 2 - e.getX();
int dy = state.getPixHeight() / 2 - e.getY();
double mx = state.getFocusX() - state.getStep() * dx;
double my = state.getFocusY() - state.getStep() * dy;
realModel.setValue(mx);
imaginaryModel.setValue(my);
checkState();
}
}

@Override
public void mouseWheelMoved(MouseWheelEvent e) {
WindowState state = currentState.get();
if (state == null) {
return;
}
double val = (double)zoomModel.getValue();
double nv = val - e.getWheelRotation() * zoomModel.getStepSize().doubleValue();
zoomModel.setValue(Math.min((double)zoomModel.getMaximum(), Math.max((double)zoomModel.getMinimum(), nv)));
checkState();
}
};

canvas.addMouseMotionListener(mouse);
canvas.addMouseListener(mouse);
canvas.addMouseWheelListener(mouse);

root.add(canvas, BorderLayout.CENTER);
filler.add(controls, BorderLayout.NORTH);
root.add(filler, BorderLayout.EAST);
Expand Down Expand Up @@ -144,7 +212,7 @@ private void checkState() {
final double span = 3.5 / z;
final double step = span / w;

final WindowState now = new WindowState(w, h, lim, x, y, z);
final WindowState now = new WindowState(w, h, lim, x, y, z, step);

if (currentState.getAndSet(now).equals(now)) {
// previous value is same as current.
Expand All @@ -155,8 +223,8 @@ private void checkState() {
if (!stateq.offer(now)) {
throw new IllegalStateException("Unable to process current state.");
}
realModel.setStepSize(step);
imaginaryModel.setStepSize(step);
realModel.setStepSize(step * 5);
imaginaryModel.setStepSize(step * 5);
actualZoom.setText(String.format("%8g", z));
actualSpan.setText(String.format("%8g", span));

Expand Down
9 changes: 7 additions & 2 deletions src/net/tuis/mandelbrot/WindowState.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@

final class WindowState {
private final int pixWidth, pixHeight, limit;
private final double focusX, focusY, zoom;
private final double focusX, focusY, zoom, step;

public WindowState(int pixWidth, int pixHeight, int limit, double focusX, double focusY, double zoom) {
public WindowState(int pixWidth, int pixHeight, int limit, double focusX, double focusY, double zoom, double step) {
super();
this.pixWidth = pixWidth;
this.pixHeight = pixHeight;
this.limit = limit;
this.focusX = focusX;
this.focusY = focusY;
this.zoom = zoom;
this.step = step;
}

public int getPixWidth() {
Expand All @@ -38,6 +39,10 @@ public double getFocusY() {
public double getZoom() {
return zoom;
}

public double getStep() {
return step;
}

@Override
public int hashCode() {
Expand Down

0 comments on commit b76e137

Please sign in to comment.