From 5f0bcda8ba0b0c6ebc409ca99bbc72c29fcb0f96 Mon Sep 17 00:00:00 2001 From: Thibaud Date: Wed, 19 Feb 2025 12:57:48 +0100 Subject: [PATCH] Import menu items from original project --- src/main/java/ovh/gasser/newshapes/App.java | 69 +++++++++-- .../ovh/gasser/newshapes/ui/Controller.java | 2 +- .../ovh/gasser/newshapes/ui/ShapesView.java | 4 + .../newshapes/ui/menu/MenuAddListener.java | 50 ++++++++ .../newshapes/ui/menu/MenuEditListener.java | 113 ++++++++++++++++++ 5 files changed, 229 insertions(+), 9 deletions(-) create mode 100644 src/main/java/ovh/gasser/newshapes/ui/menu/MenuAddListener.java create mode 100644 src/main/java/ovh/gasser/newshapes/ui/menu/MenuEditListener.java diff --git a/src/main/java/ovh/gasser/newshapes/App.java b/src/main/java/ovh/gasser/newshapes/App.java index 6c30b8d..e3b0732 100644 --- a/src/main/java/ovh/gasser/newshapes/App.java +++ b/src/main/java/ovh/gasser/newshapes/App.java @@ -1,15 +1,20 @@ package ovh.gasser.newshapes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import ovh.gasser.newshapes.shapes.SCircle; import ovh.gasser.newshapes.shapes.SCollection; import ovh.gasser.newshapes.shapes.SRectangle; import ovh.gasser.newshapes.ui.ShapesView; +import ovh.gasser.newshapes.ui.menu.MenuAddListener; +import ovh.gasser.newshapes.ui.menu.MenuEditListener; import javax.swing.*; import java.awt.*; +import java.io.FileNotFoundException; public class App { - + private final static Logger logger = LoggerFactory.getLogger(App.class); public static final Dimension WIN_SIZE = new Dimension(800, 600); private SCollection model; @@ -29,7 +34,7 @@ public class App { frame.pack(); frame.setVisible(true); - this.buildMenuBar(frame); + this.buildMenuBar(frame, view); } private void buildModel() { @@ -44,20 +49,68 @@ public class App { ); } - private void buildMenuBar(JFrame frame) { + private void buildMenuBar(JFrame frame, ShapesView sview) { var menubar = new JMenuBar(); - var helpMenu = new JMenu("Help"); - var aboutItem = new JMenuItem("About"); - aboutItem.addActionListener(actionEvent -> { - JOptionPane.showMessageDialog(frame, "New shapes"); - }); + // About + JMenu helpMenu = new JMenu("Help"); + JMenuItem aboutItem = new JMenuItem("About"); + aboutItem.addActionListener(evt -> JOptionPane.showMessageDialog(frame, "This project was created by Alexandre Colicchio and Thibaud Gasser", "About this project", JOptionPane.INFORMATION_MESSAGE)); helpMenu.add(aboutItem); + menubar.add(buildFileMenu(sview)); + menubar.add(buildEditMenu(sview)); menubar.add(helpMenu); frame.setJMenuBar(menubar); } + private JMenu buildFileMenu(ShapesView sview) { + JMenu menuFile = new JMenu("File"); + JMenuItem addRectItem = new JMenuItem("Add SRectangle"); + JMenuItem addCircleItem = new JMenuItem("Add SCircle"); + JMenuItem htmlExportItem = new JMenuItem("Export to HTML"); + JMenuItem exitItem = new JMenuItem("Exit"); + addRectItem.addActionListener(new MenuAddListener("SRectangle", model, sview)); + addCircleItem.addActionListener(new MenuAddListener("SCircle", model, sview)); + htmlExportItem.addActionListener(evt -> { + try { + new HTMLExporter(model).export(); + } catch (FileNotFoundException e) { + logger.error("Could not export as html: {}", e.getMessage()); + } + }); + exitItem.addActionListener(evt -> System.exit(0)); + menuFile.add(addRectItem); + menuFile.add(addCircleItem); + menuFile.addSeparator(); + menuFile.add(htmlExportItem); + menuFile.add(exitItem); + return menuFile; + } + + private JMenu buildEditMenu(ShapesView sview) { + MenuEditListener editListener = new MenuEditListener(model, sview, sview.getController()); + JMenu menuEdit = new JMenu("Edit"); + JMenuItem editColor = new JMenuItem("Change color"); + JMenuItem editBorderColor = new JMenuItem("Change border color"); + JMenuItem deleteItem = new JMenuItem("Delete"); + JCheckBoxMenuItem editFill = new JCheckBoxMenuItem("Fill Shape"); + JCheckBoxMenuItem editBorder = new JCheckBoxMenuItem("Draw border"); + editColor.addActionListener(editListener); + editBorderColor.addActionListener(editListener); + deleteItem.addActionListener(editListener); + editFill.addActionListener(editListener); + editBorder.addActionListener(editListener); + + menuEdit.add(editColor); + menuEdit.add(editBorderColor); + menuEdit.add(deleteItem); + menuEdit.addSeparator(); + menuEdit.add(editBorder); + menuEdit.add(editFill); + return menuEdit; + } + public static void main(String[] args) { SwingUtilities.invokeLater(App::new); } diff --git a/src/main/java/ovh/gasser/newshapes/ui/Controller.java b/src/main/java/ovh/gasser/newshapes/ui/Controller.java index a072ee5..4fe0c83 100644 --- a/src/main/java/ovh/gasser/newshapes/ui/Controller.java +++ b/src/main/java/ovh/gasser/newshapes/ui/Controller.java @@ -108,7 +108,7 @@ public class Controller { view.repaint(); } - private void deleteSelected() { + public void deleteSelected() { if (selection == null) return; logger.debug("Deleting selected shape(s)"); this.model.remove(selection.shape); diff --git a/src/main/java/ovh/gasser/newshapes/ui/ShapesView.java b/src/main/java/ovh/gasser/newshapes/ui/ShapesView.java index 9d18480..b47781e 100644 --- a/src/main/java/ovh/gasser/newshapes/ui/ShapesView.java +++ b/src/main/java/ovh/gasser/newshapes/ui/ShapesView.java @@ -27,4 +27,8 @@ public class ShapesView extends JPanel { this.draftman = new ShapeDraftman(g); model.accept(draftman); } + + public Controller getController() { + return controller; + } } diff --git a/src/main/java/ovh/gasser/newshapes/ui/menu/MenuAddListener.java b/src/main/java/ovh/gasser/newshapes/ui/menu/MenuAddListener.java new file mode 100644 index 0000000..734c388 --- /dev/null +++ b/src/main/java/ovh/gasser/newshapes/ui/menu/MenuAddListener.java @@ -0,0 +1,50 @@ +package ovh.gasser.newshapes.ui.menu; + +import ovh.gasser.newshapes.attributes.ColorAttributes; +import ovh.gasser.newshapes.attributes.SelectionAttributes; +import ovh.gasser.newshapes.shapes.SCircle; +import ovh.gasser.newshapes.shapes.SCollection; +import ovh.gasser.newshapes.shapes.SRectangle; +import ovh.gasser.newshapes.shapes.Shape; +import ovh.gasser.newshapes.ui.ShapesView; + +import java.awt.Color; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + + +public class MenuAddListener implements ActionListener { + private final String shape; + private final ShapesView view; + private final SCollection model; + + public MenuAddListener(String shape, SCollection model, ShapesView view) { + this.shape = shape; + this.model = model; + this.view = view; + } + @Override + public void actionPerformed(ActionEvent e) { + Shape s; + Rectangle bounds = model.getBounds(); + // All new shapes will be in the center of the panel. + Point loc = new Point((int)bounds.getCenterX(), (int)bounds.getCenterY()); + + if (this.shape.equals("SRectangle")){ + s = SRectangle.create(loc.x, loc.y, 50, 50); + } else if (this.shape.equals("SCircle")){ + s = SCircle.create(loc.x, loc.y, 50); + } else return; + + s.addAttributes(new SelectionAttributes()); + s.addAttributes(new ColorAttributes(true, false, randomColor(), Color.BLACK)); + model.add(s); + view.repaint(); + } + + private Color randomColor(){ + return new Color((int)(Math.random() * 0x1000000)); + } +} diff --git a/src/main/java/ovh/gasser/newshapes/ui/menu/MenuEditListener.java b/src/main/java/ovh/gasser/newshapes/ui/menu/MenuEditListener.java new file mode 100644 index 0000000..695c11e --- /dev/null +++ b/src/main/java/ovh/gasser/newshapes/ui/menu/MenuEditListener.java @@ -0,0 +1,113 @@ +package ovh.gasser.newshapes.ui.menu; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ovh.gasser.newshapes.attributes.ColorAttributes; +import ovh.gasser.newshapes.attributes.SelectionAttributes; +import ovh.gasser.newshapes.shapes.SCollection; +import ovh.gasser.newshapes.shapes.Shape; +import ovh.gasser.newshapes.ui.Controller; +import ovh.gasser.newshapes.ui.ShapesView; + +import java.awt.Color; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JColorChooser; + + +public class MenuEditListener implements ActionListener { + private final static Logger logger = LoggerFactory.getLogger(MenuEditListener.class); + + private final SCollection model; + private final ShapesView view; + private final Controller controller; + + public MenuEditListener(SCollection model, ShapesView view, Controller controller) { + this.model = model; + this.view = view; + this.controller = controller; + } + + @Override + public void actionPerformed(ActionEvent e) { + Object source = e.getSource(); + if (source instanceof JCheckBoxMenuItem item) { + if (item.getText().equals("Draw border")) setBorder(item.isSelected()); + if (item.getText().equals("Fill Shape")) setShapeFilled(item.getState()); + } else { + switch (e.getActionCommand()) { + case "Change color" -> { + Color newColor = JColorChooser.showDialog(null, "Choose a color", Color.RED); + changeColor(newColor); + } + case "Change border color" -> { + Color newColor = JColorChooser.showDialog(null, "Choose a color", Color.RED); + changeBorderColor(newColor); + } + case "Delete" -> this.controller.deleteSelected(); + } + } + view.repaint(); + } + + private void changeColor(Color filledColor) { + for (Shape s : model) { + SelectionAttributes selAttrs = (SelectionAttributes) s.getAttributes(SelectionAttributes.ID); + if ((selAttrs == null) || (! selAttrs.selected)) continue; + ColorAttributes currentColAttrs = (ColorAttributes) s.getAttributes(ColorAttributes.ID); + if (currentColAttrs == null) { + logger.warn("No color attributes: {}", s); + continue; + } + s.addAttributes(new ColorAttributes(true, currentColAttrs.stroked, filledColor, currentColAttrs.strokedColor)); + } + } + + private void changeBorderColor(Color strockedColor) { + for (Shape s : model) { + SelectionAttributes selAttrs = (SelectionAttributes) s.getAttributes(SelectionAttributes.ID); + if ((selAttrs == null) || (! selAttrs.selected)) continue; + ColorAttributes currentColAttrs = (ColorAttributes) s.getAttributes(ColorAttributes.ID); + if (currentColAttrs == null) { + logger.warn("No color attributes: {}", s); + continue; + } + s.addAttributes(new ColorAttributes(currentColAttrs.filled, true, currentColAttrs.filledColor, strockedColor)); + } + } + + /* + * Change the state of the border of all selected shapes. + */ + private void setBorder(boolean state){ + for (Shape s : model) { + SelectionAttributes selAttrs = (SelectionAttributes) s.getAttributes(SelectionAttributes.ID); + if ((selAttrs == null) || (!selAttrs.selected)) continue; + ColorAttributes colAttrs = (ColorAttributes) s.getAttributes(ColorAttributes.ID); + if (colAttrs == null) { + logger.warn("No color attributes: {}", s); + continue; + } + s.addAttributes(new ColorAttributes(colAttrs.filled, state, colAttrs.filledColor, colAttrs.strokedColor)); + } + } + + /* + * Change the filled state for all selected shapes. + */ + private void setShapeFilled(boolean state){ + logger.info("setShapeFilled(" + state + ")"); + for (Shape s : model) { + SelectionAttributes selAttrs = (SelectionAttributes) s.getAttributes(SelectionAttributes.ID); + if ((selAttrs == null) || (!selAttrs.selected)) continue; + ColorAttributes colAttrs = (ColorAttributes) s.getAttributes(ColorAttributes.ID); + if (colAttrs == null) { + logger.warn("No color attributes: {}", s); + continue; + } + s.addAttributes(new ColorAttributes(state, colAttrs.stroked, colAttrs.filledColor, colAttrs.strokedColor)); + } + } +}