diff --git a/README.md b/README.md index d972eb4..adc3126 100644 --- a/README.md +++ b/README.md @@ -26,22 +26,31 @@ # UML Editor -- [Software Requirements](#software-requirements) - - [Maven Dependencies](#maven-dependencies) -- [Features](#features) - - [GUI Layout and Buttons](#gui-layout-and-buttons) - - [Functions](#functions) - - [Extra Features](#extra-features) -- [Program Flow Overview](#program-flow-overview) -- [Usage](#usage) - - [Build](#build) - - [Run](#run) -- [Class Diagram](#class-diagram) -- [Future Work](#future-work) -- [Project File Structure](#project-file-structure) -- [References](#references) - - [Documentations](#documentations) - - [Related Projects](#related-projects) +- [UML Editor](#uml-editor) + - [Software Requirements](#software-requirements) + - [Maven Dependencies](#maven-dependencies) + - [Features](#features) + - [GUI Layout and Buttons](#gui-layout-and-buttons) + - [Functions](#functions) + - [Extra Features](#extra-features) + - [Usage](#usage) + - [Build](#build) + - [Run](#run) + - [Class Diagram](#class-diagram) + - [Future Work](#future-work) + - [Project File Structure](#project-file-structure) + - [Program Flow Overview](#program-flow-overview) + - [Use Case Sequence Diagram](#use-case-sequence-diagram) + - [A. Creating a UML Object](#a-creating-a-uml-object) + - [B. Creating a UML Connection Line](#b-creating-a-uml-connection-line) + - [C. Select/Unselect a Single Object](#c-selectunselect-a-single-object) + - [D.1 Group Objects](#d1-group-objects) + - [D.2 Ungroup Objects](#d2-ungroup-objects) + - [E. Move Objects](#e-move-objects) + - [F. Change Object Name](#f-change-object-name) + - [References](#references) + - [Documentations](#documentations) + - [Related Projects](#related-projects) ## Software Requirements @@ -85,60 +94,7 @@ - [ ] Delete UMLObject -## Program Flow Overview - -> [!CAUTION] -> This part will be updated soon. - -1. Click Tool Button -2. Mode - 1. Create UMLObject - 1. Create UMLConnectionLine - 2. Create UMLBasicObject - 2. Select - 1. If selection is UMLObjects - 1. can Move (UMLConnectionLine movement are not supported yet.) - 2. If selection is UMLBasicObject - 1. can change it’s ObjectName - 3. If selection is an Area including several UMLObjects - 1. can Group - 4. If selection is an UMLGroup - 1. can UnGroup -3. Canvas Repaint -```mermaid -graph TD - A[Initialize UML Editor] --> B{Button Clicked} - B -->|Select| C[Set Select Mode] - B -->|Association| D[Set Association Mode] - B -->|Generalization| E[Set Generalization Mode] - B -->|Composition| F[Set Composition Mode] - B -->|Class| G[Set Class Creation Mode] - B -->|Use Case| H[Set Use Case Creation Mode] - C --> I{Mouse Event on Canvas} - D --> I - E --> I - F --> I - G --> I - H --> I - I -->|Left Click on Object| J[Select/Unselect Object] - I -->|Left Click on Canvas| K[Unselect All Objects] - I -->|Left Press on Object| L[Start Line Creation] - I -->|Mouse Drag| M[Update Line Endpoint] - I -->|Left Release on Object| N[Create Connection Line] - I -->|Left Press on Object| O[Start Object Movement] - I -->|Mouse Drag| P[Move Object] - I -->|Left Release| Q[Update Object Position] - J --> R{Edit Menu} - K --> R - R -->|Group Selected| S[Merge Selected Objects] - R -->|Ungroup Selected| T[Decompose Composite Object] - R -->|Change Object Name| U[Open Name Change Window] - U -->|OK with New Name| V[Update Object Name] - U -->|Cancel| W[Close Window] - V --> W - W --> I -``` ## Usage @@ -156,16 +112,11 @@ mvn clean package java -jar target/uml-editor-1.0-jar-with-dependencies.jar ``` -## Class Diagram +## Class Diagram with Dependency > [!TIP] > Generated by [UML class diagrams](https://www.jetbrains.com/help/idea/class-diagram.html) -Class Diagram - -![Class Diagram](./assets/class-diagram.png) - -Class Diagram with Dependency ![Class Diagram with Dependency](./assets/class-diagram-with-dependency.png) @@ -229,6 +180,169 @@ Class Diagram with Dependency ... ``` +## Program Flow Overview + +1. Click Tool Button +2. Mode + 1. Create UMLObject + 1. Create UMLConnectionLine + 2. Create UMLBasicObject + 2. Select + 1. If selection is UMLObjects + 1. can Move (UMLConnectionLine movement are not supported yet.) + 2. If selection is UMLBasicObject + 1. can change it’s ObjectName + 3. If selection is an Area including several UMLObjects + 1. can Group + 4. If selection is an UMLGroup + 1. can UnGroup +3. Canvas Repaint + +```mermaid +graph TD + A[Initialize UML Editor] --> B{Button Clicked} + B -->|Select| C[Set Select Mode] + B -->|Association| D[Set Association Mode] + B -->|Generalization| E[Set Generalization Mode] + B -->|Composition| F[Set Composition Mode] + B -->|Class| G[Set Class Creation Mode] + B -->|Use Case| H[Set Use Case Creation Mode] + C --> I{Mouse Event on Canvas} + D --> I + E --> I + F --> I + G --> I + H --> I + I -->|Left Click on Object| J[Select/Unselect Object] + I -->|Left Click on Canvas| K[Unselect All Objects] + I -->|Left Press on Object| L[Start Line Creation] + I -->|Mouse Drag| M[Update Line Endpoint] + I -->|Left Release on Object| N[Create Connection Line] + I -->|Left Press on Object| O[Start Object Movement] + I -->|Mouse Drag| P[Move Object] + I -->|Left Release| Q[Update Object Position] + J --> R{Edit Menu} + K --> R + R -->|Group Selected| S[Merge Selected Objects] + R -->|Ungroup Selected| T[Decompose Composite Object] + R -->|Change Object Name| U[Open Name Change Window] + U -->|OK with New Name| V[Update Object Name] + U -->|Cancel| W[Close Window] + V --> W + W --> I +``` + +## Use Case Sequence Diagram + +### A. Creating a UML Object + +```mermaid +sequenceDiagram + participant User + participant Button + participant Canvas + User->>Button: Click button + Button-->>User: Change button color to black + User->>Canvas: Move cursor to (x,y) and press left mouse button + Canvas-->>Canvas: Draw a blank object at (x,y) + User->>Canvas: Repeat creating same object + alt User press another button + User->>Button: Click another button + Button-->>User: Change to the mode of clicked button + end +``` + +### B. Creating a UML Connection Line + +```mermaid +sequenceDiagram + participant User + participant Object1 + participant Object2 + participant Canvas + User->>Object1: Press left mouse button within boundary + User->>Canvas: Drag mouse + User->>Object2: Release mouse button within boundary + Canvas-->>Canvas: Create connection line between Object1 and Object2 + Canvas-->>Canvas: Draw arrow at Object2 based on line type + alt Press point not on object + User->>Canvas: Press, drag and release not on any object + Canvas-->>Canvas: Do nothing + else Release point not on object + User->>Canvas: Release mouse not on any object + Canvas-->>Canvas: Do not create connection line + end +``` + +### C. Select/Unselect a Single Object + +```mermaid +sequenceDiagram + participant User + participant Object + participant Canvas + User->>Object: Click on object + Object-->>Canvas: Deselect any other selected objects + Object-->>Object: Display 4 connection ports + alt Click on empty area + User->>Canvas: Click on coordinates without object + Canvas-->>Canvas: Deselect any selected objects + end +``` + +### D.1 Group Objects + +```mermaid +sequenceDiagram + participant User + participant EditMenu + participant SelectedObjects + User->>EditMenu: Select "Group" option + EditMenu->>SelectedObjects: Merge into one composite object +``` + +### D.2 Ungroup Objects + +```mermaid +sequenceDiagram + participant User + participant EditMenu + participant CompositeObject + User->>EditMenu: Select "Ungroup" option + EditMenu->>CompositeObject: Decompose one layer +``` + + +### E. Move Objects + +```mermaid +sequenceDiagram + participant User + participant Object + participant Canvas + User->>Object: Press left mouse button + User->>Canvas: Drag mouse to (x,y) + User->>Canvas: Release mouse button + Canvas->>Object: Move object to (x,y) + Canvas-->>Canvas: Redraw connected lines +``` + +### F. Change Object Name + +```mermaid +sequenceDiagram + participant User + participant EditMenu + participant Object + participant NameWindow + User->>Object: Select object + User->>EditMenu: Select "Change Object Name" + EditMenu-->>NameWindow: Open window with text area and OK/Cancel + User->>NameWindow: Enter new name, press OK + NameWindow-->>Object: Change object name + NameWindow-->>NameWindow: Close window +``` + ## References ### Documentations @@ -241,8 +355,8 @@ Class Diagram with Dependency ### Related Projects -> [!CAUTION] -> Code similarity will be checked and updated. Expecting to use [MOSS](https://theory.stanford.edu/~aiken/moss/) +> [!TIP] +> Code similarity is checked by using [MOSS](https://theory.stanford.edu/~aiken/moss/). Result: http://moss.stanford.edu/results/1/9411843636512/ - [haVincy/UML-Editor](https://github.com/haVincy/UML-Editor) - [MU-PING/UML-editor](https://github.com/MU-PING/UML-editor) diff --git a/assets/class-diagram-with-dependency.png b/assets/class-diagram-with-dependency.png index b3f893f..d340cf8 100644 Binary files a/assets/class-diagram-with-dependency.png and b/assets/class-diagram-with-dependency.png differ diff --git a/assets/class-diagram.png b/assets/class-diagram.png deleted file mode 100644 index 58ff331..0000000 Binary files a/assets/class-diagram.png and /dev/null differ diff --git a/assets/usecase-a.png b/assets/usecase-a.png new file mode 100644 index 0000000..6977054 Binary files /dev/null and b/assets/usecase-a.png differ diff --git a/assets/usecase-b.png b/assets/usecase-b.png new file mode 100644 index 0000000..b376cd4 Binary files /dev/null and b/assets/usecase-b.png differ diff --git a/assets/usecase-c.png b/assets/usecase-c.png new file mode 100644 index 0000000..f65f32e Binary files /dev/null and b/assets/usecase-c.png differ diff --git a/assets/usecase-d-1.png b/assets/usecase-d-1.png new file mode 100644 index 0000000..0e327f0 Binary files /dev/null and b/assets/usecase-d-1.png differ diff --git a/assets/usecase-d-2.png b/assets/usecase-d-2.png new file mode 100644 index 0000000..25f8ae1 Binary files /dev/null and b/assets/usecase-d-2.png differ diff --git a/assets/usecase-e.png b/assets/usecase-e.png new file mode 100644 index 0000000..6f24251 Binary files /dev/null and b/assets/usecase-e.png differ diff --git a/assets/usecase-f.png b/assets/usecase-f.png new file mode 100644 index 0000000..1557b0e Binary files /dev/null and b/assets/usecase-f.png differ diff --git a/src/main/java/com/xxrjun/components/uml/UMLObject.java b/src/main/java/com/xxrjun/components/uml/UMLObject.java index a4dda37..0b3a059 100644 --- a/src/main/java/com/xxrjun/components/uml/UMLObject.java +++ b/src/main/java/com/xxrjun/components/uml/UMLObject.java @@ -13,7 +13,6 @@ public abstract class UMLObject{ /** * The Uml ports. */ - protected UMLPort[] umlPorts; private boolean isGroupSelected = false; private boolean isNameChangeable = false; diff --git a/src/main/java/com/xxrjun/components/uml/basics/UMLBasicObject.java b/src/main/java/com/xxrjun/components/uml/basics/UMLBasicObject.java index 0b89d1e..d1b99ee 100644 --- a/src/main/java/com/xxrjun/components/uml/basics/UMLBasicObject.java +++ b/src/main/java/com/xxrjun/components/uml/basics/UMLBasicObject.java @@ -38,7 +38,7 @@ private enum PortPosition { */ RIGHT} - private final Map connectionLines = new HashMap<>(); + private final Map connectionLines = new HashMap<>(); /** * Instantiates a new Uml basic object. @@ -102,17 +102,17 @@ public UMLPort findNearestPort(Point point) { * Update connection line. */ public void updateConnectionLine() { - for (Map.Entry entry : connectionLines.entrySet()) { + for (Map.Entry entry : connectionLines.entrySet()) { // if source => calculate source Nearest port => set source port // if destination => calculate destination Nearest port => set destination port UMLConnectionLine connectionLine = entry.getKey(); - UMLConnectionLine.EndPointType endPointType = entry.getValue(); + UMLConnectionLine.EndPointTypes endPointType = entry.getValue(); // TODO: BUG: UMLBasicObject and UMLConnectionLine overlapping still exists after updating to nearest port - if (endPointType == UMLConnectionLine.EndPointType.SOURCE) { + if (endPointType == UMLConnectionLine.EndPointTypes.SOURCE) { connectionLine.setSourcePort(findNearestPort(new Point(connectionLine.getX1(), connectionLine.getY1()))); - } else if (endPointType == UMLConnectionLine.EndPointType.DESTINATION) { + } else if (endPointType == UMLConnectionLine.EndPointTypes.DESTINATION) { connectionLine.setDestinationPort(findNearestPort(new Point(connectionLine.getX2(), connectionLine.getY2()))); } // reset the location of the connection line @@ -136,7 +136,7 @@ public void updateLocation(int deltaX, int deltaY) { * @param connectionLine the connection line * @param endPointType the end point type */ - public void addConnectionLine(UMLConnectionLine connectionLine, UMLConnectionLine.EndPointType endPointType) { + public void addConnectionLine(UMLConnectionLine connectionLine, UMLConnectionLine.EndPointTypes endPointType) { connectionLines.put(connectionLine, endPointType); } diff --git a/src/main/java/com/xxrjun/components/uml/connectionlines/UMLConnectionLine.java b/src/main/java/com/xxrjun/components/uml/connectionlines/UMLConnectionLine.java index befe23d..a9563eb 100644 --- a/src/main/java/com/xxrjun/components/uml/connectionlines/UMLConnectionLine.java +++ b/src/main/java/com/xxrjun/components/uml/connectionlines/UMLConnectionLine.java @@ -17,7 +17,7 @@ public abstract class UMLConnectionLine extends UMLObject { /** * The enum End point type. */ - public enum EndPointType { + public enum EndPointTypes { /** * Source end point type. */ @@ -32,7 +32,7 @@ public enum EndPointType { NONE } - private EndPointType currentEndPointType = EndPointType.NONE; + private EndPointTypes currentEndPointType = EndPointTypes.NONE; /** * Instantiates a new Uml connection line. @@ -81,10 +81,10 @@ public void resetLocation() { * @param p the p */ public void resetEndPoint(Point p) { - if (currentEndPointType == EndPointType.SOURCE) { + if (currentEndPointType == EndPointTypes.SOURCE) { this.setX1(p.x); this.setY1(p.y); - } else if (currentEndPointType == EndPointType.DESTINATION) { + } else if (currentEndPointType == EndPointTypes.DESTINATION) { this.setX2(p.x); this.setY2(p.y); } @@ -113,7 +113,7 @@ public void setDestinationPort(UMLPort umlPort) { * * @return the current end point type */ - public EndPointType getCurrentEndPointType() { + public EndPointTypes getCurrentEndPointType() { return currentEndPointType; } @@ -122,7 +122,7 @@ public EndPointType getCurrentEndPointType() { * * @param endPointType the end point type */ - public void setEndPointType(EndPointType endPointType) { + public void setEndPointType(EndPointTypes endPointType) { currentEndPointType = endPointType; } diff --git a/src/main/java/com/xxrjun/modes/CreateUMLConnectionLine.java b/src/main/java/com/xxrjun/modes/CreateUMLConnectionLine.java index 05f9baf..810c6a2 100644 --- a/src/main/java/com/xxrjun/modes/CreateUMLConnectionLine.java +++ b/src/main/java/com/xxrjun/modes/CreateUMLConnectionLine.java @@ -39,6 +39,7 @@ public void mousePressed(MouseEvent e) { allUMLObjects = canvas.getUMLObjects(); for (UMLObject umlObject : allUMLObjects) { // Check if the mouse click is inside the object + // I think using instanceof here is good enough if (umlObject instanceof UMLBasicObject umlBasicObject && (umlBasicObject.contains(e.getPoint()))) { sourceObject = umlBasicObject; sourcNearestUMLPort = umlBasicObject.findNearestPort(e.getPoint()); @@ -71,8 +72,8 @@ public void mouseReleased(MouseEvent e) { newConnectionLine.setSourcePort(sourcNearestUMLPort); newConnectionLine.setDestinationPort(destinationNearestUMLPort); - sourceObject.addConnectionLine(newConnectionLine, UMLConnectionLine.EndPointType.SOURCE); - destinationObject.addConnectionLine(newConnectionLine, UMLConnectionLine.EndPointType.DESTINATION); + sourceObject.addConnectionLine(newConnectionLine, UMLConnectionLine.EndPointTypes.SOURCE); + destinationObject.addConnectionLine(newConnectionLine, UMLConnectionLine.EndPointTypes.DESTINATION); } // clear temporary connection line and repaint diff --git a/src/main/java/com/xxrjun/modes/Select.java b/src/main/java/com/xxrjun/modes/Select.java index 06c92c6..0fdd51c 100644 --- a/src/main/java/com/xxrjun/modes/Select.java +++ b/src/main/java/com/xxrjun/modes/Select.java @@ -52,17 +52,10 @@ public void mouseDragged(MouseEvent e) { int moveY = e.getY() - startPoint.y; if (canvas.getSelection() != null) { - if (canvas.getSelection() instanceof UMLBasicObject umlBasicObject) { - // UMLObject selected - umlBasicObject.updateLocation(moveX, moveY); - startPoint.x = e.getX(); - startPoint.y = e.getY(); - } else if (canvas.getSelection() instanceof UMLGroup umlGroup) { - // UMLGroup selected - umlGroup.updateLocation(moveX, moveY); - startPoint.x = e.getX(); - startPoint.y = e.getY(); - } + UMLObject selectedObject = canvas.getSelection(); + selectedObject.updateLocation(moveX, moveY); + startPoint.x = e.getX(); + startPoint.y = e.getY(); } else { // Update selected area int upperLeftX = Math.min(startPoint.x, e.getX());