Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mode #54

Merged
merged 21 commits into from
Jun 13, 2024
Merged

Mode #54

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
3,312 changes: 2,214 additions & 1,098 deletions media/wireframe.excalidraw

Large diffs are not rendered by default.

134 changes: 94 additions & 40 deletions src/main/java/com/github/creme332/controller/CanvasController.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,38 @@

import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.Point;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;

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 class CanvasController {
private Canvas canvas;
private Point initialClick;

public static final int MAX_CELL_SIZE = 500;
public static final int DEFAULT_CELL_SIZE = 100;
public static final int MIN_CELL_SIZE = 30;
public static final int ZOOM_INCREMENT = 10;
/**
* Used to store coordinate where mouse drag started
*/
private Point mouseDragStart;
private AppState app;
private CanvasModel model;

/**
* Wrapper for shape currently being drawn.
*/
private ShapeWrapper currentWrapper;

public CanvasController(Canvas canvas) {
public CanvasController(AppState app, Canvas canvas) {
this.app = app;
this.canvas = canvas;
this.model = app.getCanvasModel();

canvas.addComponentListener(new ComponentAdapter() {
@Override
Expand All @@ -37,7 +52,17 @@ public void mousePressed(MouseEvent e) {
canvas.addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
// TODO document why this method is empty
Point2D polySpaceMousePosition = model.toPolySpace(e.getPoint());

if ((app.getMode() == Mode.DRAW_LINE_BRESENHAM || app.getMode() == Mode.DRAW_LINE_DDA)
&& currentWrapper != null && currentWrapper.getPlottedPoints().size() == 1) {

Line2D line = new Line2D.Double(currentWrapper.getPlottedPoints().get(0),
polySpaceMousePosition);
currentWrapper.setShape(line);
canvas.repaint();
}

}
});

Expand All @@ -56,69 +81,98 @@ public void mouseWheelMoved(MouseWheelEvent e) {
});

// Add action listeners for the zoom panel buttons
canvas.getHomeButton().addActionListener(e -> handleHomeButton());
canvas.getZoomInButton().addActionListener(e -> handleZoomInButton());
canvas.getZoomOutButton().addActionListener(e -> handleZoomOutButton());
canvas.getHomeButton().addActionListener(e -> resetCanvasView());
canvas.getZoomInButton().addActionListener(e -> model.updateCanvasZoom(true));
canvas.getZoomOutButton().addActionListener(e -> model.updateCanvasZoom(false));
}

private void handleCanvasZoom(MouseWheelEvent e) {
if (e.getWheelRotation() == 1) {
// zoom out
canvas.setCellSize(Math.max(MIN_CELL_SIZE, canvas.getCellSize() - ZOOM_INCREMENT));

} else {
// zoom in
canvas.setCellSize(Math.min(MAX_CELL_SIZE, canvas.getCellSize() + ZOOM_INCREMENT));
}

model.updateCanvasZoom(e.getWheelRotation() != 1);
canvas.repaint();
}

private void handleMouseDragged(MouseEvent e) {
if (initialClick == null) {
initialClick = e.getPoint();
if (mouseDragStart == null) {
mouseDragStart = e.getPoint();
return;
}

Point currentDrag = e.getPoint();
int deltaX = currentDrag.x - initialClick.x;
int deltaY = currentDrag.y - initialClick.y;
if (app.getMode() == Mode.MOVE_GRAPHICS_VIEW || app.getMode() == Mode.MOVE_CANVAS) {
Point currentDrag = e.getPoint();
int deltaX = currentDrag.x - mouseDragStart.x;
int deltaY = currentDrag.y - mouseDragStart.y;

canvas.setYZero(canvas.getYZero() + deltaY);
canvas.setXZero(canvas.getXZero() + deltaX);
model.setYZero(model.getYZero() + deltaY);
model.setXZero(model.getXZero() + deltaX);

initialClick = currentDrag;
mouseDragStart = currentDrag;

canvas.repaint();
canvas.repaint();
}
}

private void handleCanvasResize() {
if (model == null)
return;
int width = canvas.getWidth();
int height = canvas.getHeight();

// place origin at center of canvas
canvas.setYZero(height / 2);
canvas.setXZero(width / 2);
model.setYZero(height / 2);
model.setXZero(width / 2);

canvas.repaint();
}

private void handleMousePressed(MouseEvent e) {
initialClick = e.getPoint();
}
if (app.getMode() == Mode.MOVE_GRAPHICS_VIEW || app.getMode() == Mode.MOVE_CANVAS) {
mouseDragStart = e.getPoint();
}

private void handleHomeButton() {
canvas.setCellSize(DEFAULT_CELL_SIZE);
canvas.repaint();
}
/**
* Coordinates of mouse pressed in the polydraw coordinate system
*/
Point2D polySpaceMousePosition = model.toPolySpace(e.getPoint());
System.out.println(polySpaceMousePosition);

if (app.getMode() == Mode.DRAW_LINE_BRESENHAM || app.getMode() == Mode.DRAW_LINE_DDA) {
if (currentWrapper == null) {
// first coordinate of line has been selected

// create a shape wrapper
currentWrapper = new ShapeWrapper();
currentWrapper.getPlottedPoints().add(polySpaceMousePosition);

// save wrapper
model.getShapes().add(currentWrapper);

} else {
// second coordinate has now been selected

// create a line
Point2D lineStart = currentWrapper.getPlottedPoints().get(0);
Point2D lineEnd = polySpaceMousePosition;
Line2D line = new Line2D.Double();
line.setLine(lineStart, lineEnd);

currentWrapper.getPlottedPoints().add(lineEnd);
currentWrapper.setShape(line);

currentWrapper = null;
}

}

private void handleZoomInButton() {
canvas.setCellSize(Math.min(MAX_CELL_SIZE, canvas.getCellSize() + ZOOM_INCREMENT));
canvas.repaint();
}

private void handleZoomOutButton() {
canvas.setCellSize(Math.max(MIN_CELL_SIZE, canvas.getCellSize() - ZOOM_INCREMENT));
private void resetCanvasView() {
// show origin at center of canvas
model.setXZero(canvas.getWidth() / 2);
model.setYZero(canvas.getHeight() / 2);

// reset zoom level
model.setCellSize(CanvasModel.DEFAULT_CELL_SIZE);
canvas.repaint();
}
}
14 changes: 7 additions & 7 deletions src/main/java/com/github/creme332/controller/Controller.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,23 @@ public class Controller {

public Controller() {
try {
menuBar = new MenuBar(app.getMenuModels());
new MenuBarController(app, menuBar);

toolbar = new Toolbar();
new ToolBarController(toolbar);

canvas = new Canvas(toolbar);
new CanvasController(canvas);
canvas = new Canvas(app.getCanvasModel(), toolbar);
new CanvasController(app, canvas);

frame = new Frame(canvas);
frame = new Frame(canvas, menuBar);
frameController = new FrameController(app, frame);

menuBar = frame.getMyMenuBar();
new MenuBarController(app, menuBar);

new SideMenuController(app, frame.getSideMenuPanel());
} catch (InvalidIconSizeException | InvalidPathException e) {
System.err.println("Error: " + e.getMessage());
System.exit(1);
} catch (Exception e) {
} catch (Exception e) {
System.err.println("Unexpected error: " + e.getMessage());
e.printStackTrace();
System.exit(1);
Expand Down
100 changes: 49 additions & 51 deletions src/main/java/com/github/creme332/controller/MenuBarController.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,102 +3,100 @@
import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.BorderFactory;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.border.Border;
import javax.swing.border.MatteBorder;

import com.github.creme332.model.AppState;
import com.github.creme332.model.MenuModel;
import com.github.creme332.model.Mode;
import com.github.creme332.view.MenuBar;

public class MenuBarController {
public class MenuBarController implements PropertyChangeListener {
private MenuBar menubar;
private AppState app;

private int activeMenuIndex = 0;

private static final MatteBorder VISIBLE_BORDER = BorderFactory.createMatteBorder(
2, 2, 2, 2, new Color(97, 97, 255));

Mode[][] modes = {
new Mode[] { Mode.MOVE_CANVAS, Mode.DRAW_FREEHAND },
new Mode[] { Mode.DRAW_LINE_DDA, Mode.DRAW_LINE_BRESENHAM },
new Mode[] { Mode.DRAW_CIRCLE_DYNAMIC, Mode.DRAW_CIRCLE_FIXED },
new Mode[] { Mode.DRAW_ELLIPSE },
new Mode[] { Mode.DRAW_POLYGON_DYNAMIC, Mode.DRAW_REGULAR_POLYGON },
new Mode[] { Mode.REFLECT_ABOUT_LINE, Mode.REFLECT_ABOUT_POINT, Mode.ROTATE_AROUND_POINT },
new Mode[] { Mode.MOVE_GRAPHICS_VIEW, Mode.ZOOM_IN, Mode.ZOOM_OUT, Mode.DELETE }
};

Mode[] menuModes = new Mode[modes.length]; // currently selected option for each menu
MenuModel[] menuModels;
int activeMenuIndex;
Border defaultBorder;

public MenuBarController(AppState app, MenuBar menu) {
this.menubar = menu;
public MenuBarController(AppState app, MenuBar menubar) {
this.menubar = menubar;
this.app = app;
app.setMode(modes[0][0]);
this.menuModels = app.getMenuModels();

for (int i = 0; i < menu.getMenuCount(); i++) {
JMenu jMenu = menu.getMenu(i);
activeMenuIndex = app.getModeToMenuMapper().get(app.getMode());
defaultBorder = menubar.getMenu(0).getBorder();

// note: getMenuCount() returns the number of items in the menubar and not all
// items are menus
if (jMenu == null)
break;
// for each menu in menubar
for (int i = 0; i < menuModels.length; i++) {
JMenu jMenu = menubar.getMenu(i);
MenuModel menuModel = menuModels[i];

final int menuIndex = i;
final Border normalBorder = jMenu.getBorder();
// listen to changes in each menu model
menuModel.addPropertyChangeListener(this);

// set initial mode of menu to first mode present
menuModes[i] = modes[i][0];
// create a menu controller
new MenuController(menuModel, jMenu);

if (i == activeMenuIndex) {
jMenu.setBorder(VISIBLE_BORDER);
}

final int menuIndex = i;
// when user clicks on a menu
jMenu.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {

// remove border from previously active menu
menu.getMenu(activeMenuIndex).setBorder(normalBorder);
menubar.getMenu(activeMenuIndex).setBorder(defaultBorder);

// store index of clicked menu
activeMenuIndex = menuIndex;

JMenu clickedMenu = (JMenu) e.getComponent();

// add border to clicked menu
menu.getMenu(activeMenuIndex).setBorder(VISIBLE_BORDER);
clickedMenu.setBorder(VISIBLE_BORDER);

// change mode of app
app.setMode(menuModes[activeMenuIndex]);
// update global mode using menu model for clicked menu
app.setMode(menuModel.getActiveItem().getMode());
}
});

for (int j = 0; j < jMenu.getItemCount(); j++) {
JMenuItem jMenuItem = jMenu.getItem(j);

final int menuItemIndex = j;
// add mouse listener to menu item
jMenuItem.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
// change menu icon to icon of menu item
jMenu.setIcon(jMenuItem.getIcon());
app.setMode(modes[menuIndex][menuItemIndex]);
menuModes[activeMenuIndex] = modes[menuIndex][menuItemIndex];
}
});
}
}

menu.getSideBarButton().addMouseListener(new MouseAdapter() {
menubar.getSideBarButton().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
// toggle sidebar visibility
app.setSideBarVisibility(!app.getSideBarVisibility());
}
});
}

@Override
public void propertyChange(PropertyChangeEvent e) {
String propertyName = e.getPropertyName();
if ("modeChange".equals(propertyName)) {
Mode newMode = (Mode) e.getNewValue();

// remove border from previously active menu
menubar.getMenu(activeMenuIndex).setBorder(defaultBorder);

// store index of clicked menu
activeMenuIndex = app.getModeToMenuMapper().get(newMode);

// add border to clicked menu
menubar.getMenu(activeMenuIndex).setBorder(VISIBLE_BORDER);

// update global mode
app.setMode(newMode);
}
}
}
Loading
Loading