-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEditor.java
More file actions
279 lines (243 loc) · 8.22 KB
/
Copy pathEditor.java
File metadata and controls
279 lines (243 loc) · 8.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
import java.util.ArrayList;
import java.util.List;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
* Client-server graphical editor
*
* @author Chris Bailey-Kellogg, Dartmouth CS 10, Fall 2012; loosely based on CS 5 code by Tom Cormen
* @author CBK, winter 2014, overall structure substantially revised
* @author Travis Peters, Dartmouth CS 10, Winter 2015; remove EditorCommunicatorStandalone (use echo server for testing)
* @author CBK, spring 2016 and Fall 2016, restructured Shape and some of the GUI
* @author Tim Pierson Dartmouth CS 10, provided for Winter 2024
* author Godwin Kangor
* @author Ahmed Elmi
*/
public class Editor extends JFrame {
private static String serverIP = "localhost";//129.170.197.82 // IP address of sketch server
// "localhost" for your own machine;
// or ask a friend for their IP address
private static final int width = 800, height = 800; // canvas size
// Current settings on GUI
public enum Mode {
DRAW, MOVE, RECOLOR, DELETE
}
private Mode mode = Mode.DRAW; // drawing/moving/recoloring/deleting objects
private String shapeType = "ellipse"; // type of object to add
private Color color = Color.black; // current drawing color
// Drawing state
// these are remnants of my implementation; take them as possible suggestions or ignore them
private Shape curr = null; // current shape (if any) being drawn
private Sketch sketch; // holds and handles all the completed objects
private int movingId = -1; // current shape id (if any; else -1) being moved
private Point drawFrom = null; // where the drawing started
private Point moveFrom = null; // where object is as it's being dragged
// Communication
private EditorCommunicator comm; // communication with the sketch server
public Editor() {
super("Graphical Editor");
sketch = new Sketch();
// Connect to server
comm = new EditorCommunicator(serverIP, this);
comm.start();
// Helpers to create the canvas and GUI (buttons, etc.)
JComponent canvas = setupCanvas();
JComponent gui = setupGUI();
// Put the buttons and canvas together into the window
Container cp = getContentPane();
cp.setLayout(new BorderLayout());
cp.add(canvas, BorderLayout.CENTER);
cp.add(gui, BorderLayout.NORTH);
// Usual initialization
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
/**
* Creates a component to draw into
*/
private JComponent setupCanvas() {
JComponent canvas = new JComponent() {
public void paintComponent(Graphics g) {
super.paintComponent(g);
drawSketch(g);
}
};
canvas.setPreferredSize(new Dimension(width, height));
canvas.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent event) {
handlePress(event.getPoint());
}
public void mouseReleased(MouseEvent event) {
handleRelease();
}
});
canvas.addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent event) {
handleDrag(event.getPoint());
}
});
return canvas;
}
/**
* Creates a panel with all the buttons
*/
private JComponent setupGUI() {
// Select type of shape
String[] shapes = {"ellipse", "freehand", "rectangle", "segment"};
JComboBox<String> shapeB = new JComboBox<String>(shapes);
shapeB.addActionListener(e -> shapeType = (String)((JComboBox<String>)e.getSource()).getSelectedItem());
// Select drawing/recoloring color
// Following Oracle example
JButton chooseColorB = new JButton("choose color");
JColorChooser colorChooser = new JColorChooser();
JLabel colorL = new JLabel();
colorL.setBackground(Color.black);
colorL.setOpaque(true);
colorL.setBorder(BorderFactory.createLineBorder(Color.black));
colorL.setPreferredSize(new Dimension(25, 25));
JDialog colorDialog = JColorChooser.createDialog(chooseColorB,
"Pick a Color",
true, //modal
colorChooser,
e -> { color = colorChooser.getColor(); colorL.setBackground(color); }, // OK button
null); // no CANCEL button handler
chooseColorB.addActionListener(e -> colorDialog.setVisible(true));
// Mode: draw, move, recolor, or delete
JRadioButton drawB = new JRadioButton("draw");
drawB.addActionListener(e -> mode = Mode.DRAW);
drawB.setSelected(true);
JRadioButton moveB = new JRadioButton("move");
moveB.addActionListener(e -> mode = Mode.MOVE);
JRadioButton recolorB = new JRadioButton("recolor");
recolorB.addActionListener(e -> mode = Mode.RECOLOR);
JRadioButton deleteB = new JRadioButton("delete");
deleteB.addActionListener(e -> mode = Mode.DELETE);
ButtonGroup modes = new ButtonGroup(); // make them act as radios -- only one selected
modes.add(drawB);
modes.add(moveB);
modes.add(recolorB);
modes.add(deleteB);
JPanel modesP = new JPanel(new GridLayout(1, 0)); // group them on the GUI
modesP.add(drawB);
modesP.add(moveB);
modesP.add(recolorB);
modesP.add(deleteB);
// Put all the stuff into a panel
JComponent gui = new JPanel();
gui.setLayout(new FlowLayout());
gui.add(shapeB);
gui.add(chooseColorB);
gui.add(colorL);
gui.add(modesP);
return gui;
}
/**
* Getter for the sketch instance variable
*/
public Sketch getSketch() {
return sketch;
}
/**
* Draws all the shapes in the sketch,
* along with the object currently being drawn in this editor (not yet part of the sketch)
*/
public void drawSketch(Graphics g) {
// TODO: YOUR CODE HERE
sketch.draw(g);
}
// Helpers for event handlers
/**
* Helper method for press at point
* In drawing mode, start a new object;
* in moving mode, (request to) start dragging if clicked in a shape;
* in recoloring mode, (request to) change clicked shape's color
* in deleting mode, (request to) delete clicked shape
*/
private void handlePress(Point p) {
// TODO: YOUR CODE HERE
if(mode==Mode.DRAW){
drawFrom = p;
if ("ellipse".equals(shapeType)) {
curr = new Ellipse((int) p.getX(), (int) p.getY(), color);
} else if ("freehand".equals(shapeType)) {
curr = new Polyline((int) p.getX(), (int) p.getY(), color);
} else if ("rectangle".equals(shapeType)) {
curr = new Rectangle((int) p.getX(), (int) p.getY(), color);
} else if ("segment".equals(shapeType)) {
curr = new Segment((int) p.getX(), (int) p.getY(), color);
}
}
if (sketch.containsPoint(p) != null) {
if (mode == Mode.MOVE) {
moveFrom = p;
curr = sketch.containsPoint(p);
movingId = sketch.getId(curr);
}
if (mode == Mode.RECOLOR) {
int id;
curr = sketch.containsPoint(p);
id = sketch.getId(curr);
comm.sendMessage("recolor" + " " + id + " " + color.getRGB());
}
if (mode == Mode.DELETE) {
int id;
curr = sketch.containsPoint(p);
id = sketch.getId(curr);
comm.sendMessage("delete" + " " + id);
}
}
repaint();
}
/**
* Helper method for drag to new point
* In drawing mode, update the other corner of the object;
* in moving mode, (request to) drag the object
*/
private void handleDrag(Point p) {
// TODO: YOUR CODE HERE
int Vx = (int) p.getX();
int Vy = (int) p.getY();
if(mode == Mode.DRAW ){
if ("ellipse".equals(shapeType)) {
((Ellipse) curr).setCorners((int) drawFrom.getX(), (int) drawFrom.getY(), Vx, Vy);
} else if ("freehand".equals(shapeType)) {
((Polyline) curr).addNext(Vx, Vy);
} else if ("rectangle".equals(shapeType)) {
((Rectangle) curr).setCorners((int) drawFrom.getX(), (int) drawFrom.getY(), Vx, Vy);
} else if ("segment".equals(shapeType)) {
((Segment) curr).setEnd(Vx, Vy);
}
repaint();
}
else if (mode == Mode.MOVE){
if(sketch.containsPoint(p) != null){
comm.sendMessage("move" + " " + movingId + " " + //send message
(int) moveFrom.getX() + " " + (int) moveFrom.getY() +
" " + (int) (Vx - moveFrom.getX()) + " " + (int)(Vy - moveFrom.getY()));
moveFrom = p;
}
}
}
/**
* Helper method for release
* In drawing mode, pass the add new object request on to the server;
* in moving mode, release it
*/
private void handleRelease() {
// TODO: YOUR CODE HERE
if(mode == Mode.DRAW){
comm.sendMessage("draw" + " " + curr.toString());
}
repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Editor();
}
});
}
}