Skip to content

Commit

Permalink
implement translation mode
Browse files Browse the repository at this point in the history
  • Loading branch information
creme332 committed Jul 18, 2024
1 parent 11f9af1 commit 7e29fa6
Show file tree
Hide file tree
Showing 3 changed files with 186 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import com.github.creme332.controller.canvas.drawing.DrawIrregularPolygon;
import com.github.creme332.controller.canvas.drawing.DrawLine;
import com.github.creme332.controller.canvas.drawing.DrawRegularPolygon;
import com.github.creme332.controller.canvas.transform.Translator;
import com.github.creme332.model.AppState;
import com.github.creme332.model.CanvasModel;
import com.github.creme332.model.Mode;
Expand Down Expand Up @@ -75,6 +76,9 @@ public CanvasController(AppState app, Canvas canvas) {
drawControllers.add(new DrawRegularPolygon(app, canvas));
drawControllers.add(new DrawIrregularPolygon(app, canvas));

// initialize other canvas sub-controllers
new Translator(app, canvas);

// when canvas is resized, update dimensions and reset zoom
canvas.addComponentListener(new ComponentAdapter() {
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.github.creme332.controller.canvas.transform;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.util.List;

import com.github.creme332.model.AppState;
import com.github.creme332.model.CanvasModel;
import com.github.creme332.model.Mode;
import com.github.creme332.model.ShapeWrapper;
import com.github.creme332.view.Canvas;

public abstract class AbstractTransformer {
protected Canvas canvas;
protected CanvasModel canvasModel;
private AppState app;

protected AbstractTransformer(AppState app, Canvas canvas) {
this.app = app;
this.canvas = canvas;
this.canvasModel = app.getCanvasModel();

canvas.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (!shouldDraw())
return;
Point2D polyspaceMousePosition = canvasModel.toPolySpace(e.getPoint());
int selectedShapeIndex = getSelectedShapeIndex(polyspaceMousePosition);
if (selectedShapeIndex < 0)
return;
handleShapeSelection(selectedShapeIndex);
}
});
}

/**
*
* @param polyspaceMousePosition Coordinate of point lying inside shape
* @return Index of first shape that contains polyspaceMousePosition. -1 if no
* such shape found.
*/
private int getSelectedShapeIndex(Point2D polyspaceMousePosition) {
List<ShapeWrapper> shapes = canvasModel.getShapeManager().getShapes();
for (int i = 0; i < shapes.size(); i++) {
ShapeWrapper wrapper = shapes.get(i);
if (wrapper.getShape().contains(polyspaceMousePosition)) {
return i;
}
}
return -1;
}

/**
*
* @return Current canvas mode
*/
public Mode getCanvasMode() {
return app.getMode();
}

/**
* This method only gets called when shouldDraw() returns true and mouse
* clicked.
*
* @param shapeIndex A valid index representing selected shape
*/
public abstract void handleShapeSelection(int shapeIndex);

/**
* Determines whether current controller should be allowed to handle event or
* not.
*
* @return
*/
public abstract boolean shouldDraw();

/**
* Reset current controller to its initial state. For example, this method will
* be invoked when mode changes while drawing was ongoing.
*/
public void disposePreview() {
// delete any preview shape
canvasModel.getShapeManager().setShapePreview(null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.github.creme332.controller.canvas.transform;

import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.util.List;

import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

import com.github.creme332.model.AppState;
import com.github.creme332.model.Mode;
import com.github.creme332.model.ShapeWrapper;
import com.github.creme332.view.Canvas;

public class Translator extends AbstractTransformer {

public Translator(AppState app, Canvas canvas) {
super(app, canvas);
}

@Override
public void handleShapeSelection(int shapeIndex) {
/**
* A copy of the shape selected
*/
final ShapeWrapper selectedWrapperCopy = canvasModel.getShapeManager().getShapes().get(shapeIndex);

// request user for translation vector
final Point2D translationVector = requestTranslationVector();

// apply transformation on shape
final AffineTransform transform = new AffineTransform();
transform.translate(translationVector.getX(), translationVector.getY());
final Shape transformedShape = transform.createTransformedShape(selectedWrapperCopy.getShape());

// save transformed shape
selectedWrapperCopy.setShape(transformedShape);
canvasModel.getShapeManager().editShape(shapeIndex, selectedWrapperCopy);

// translate plotted points
final List<Point2D> originalPlottedPoints = selectedWrapperCopy.getPlottedPoints();
for (int i = 0; i < originalPlottedPoints.size(); i++) {
Point2D oldPoint = originalPlottedPoints.get(i);
originalPlottedPoints.set(i,
new Point2D.Double(oldPoint.getX() + translationVector.getX(),
oldPoint.getY() + translationVector.getY()));
}

// repaint canvas
canvas.repaint();
}

@Override
public boolean shouldDraw() {
return getCanvasMode() == Mode.TRANSLATION;
}

/**
* Asks user to enter the radii for the ellipse. If input values are invalid
* or if the operation is cancelled, null is returned.
*
* @return array with radii [rx, ry]
*/
private Point2D requestTranslationVector() {
final Point2D zeroVector = new Point2D.Double(0, 0);

JTextField rxField = new JTextField(5);
JTextField ryField = new JTextField(5);
JPanel panel = new JPanel();
panel.add(new JLabel("X:"));
panel.add(rxField);
panel.add(new JLabel("Y:"));
panel.add(ryField);

int result = JOptionPane.showConfirmDialog(null, panel, "Enter translation vector",
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.PLAIN_MESSAGE);

// Request focus again otherwise keyboard shortcuts will not work
canvas.getTopLevelAncestor().requestFocus();

if (result == JOptionPane.OK_OPTION) {
try {
return new Point2D.Double(Integer.parseInt(rxField.getText()), Integer.parseInt(ryField.getText()));
} catch (NumberFormatException e) {
return zeroVector;
}
}
return zeroVector;
}

}

0 comments on commit 7e29fa6

Please sign in to comment.