source: trunk/src/org/expeditee/items/Dot.java@ 78

Last change on this file since 78 was 78, checked in by ra33, 16 years ago

Added @b and @v...
Also changed @f... so that images can be displayed with transparent backgrounds.
Did a bunch of refactoring in the process to remove duplicated code and simplify managing @i, @f and @b.

File size: 7.8 KB
Line 
1package org.expeditee.items;
2
3import java.awt.Color;
4import java.awt.Graphics2D;
5import java.awt.Polygon;
6import java.awt.Rectangle;
7import java.util.ArrayList;
8import java.util.LinkedList;
9import java.util.List;
10
11import org.expeditee.gui.DisplayIO;
12import org.expeditee.gui.Frame;
13import org.expeditee.gui.FrameKeyboardActions;
14
15/**
16 * Represents a point on the screen. All Point objects are stored as x,y pairs
17 * with an Item ID. Note: Lines and all combinates of lines (rectangles, etc)
18 * are represented only as Points that share line IDs.
19 *
20 * @author jdm18
21 *
22 */
23public class Dot extends Item {
24
25 // Standard Item variables
26
27 private static final int _MINIMUM_DOT_SIZE = 6;
28
29 // the polygon surrounding this point, used for 'gravity'
30 private Polygon _poly = null;
31
32 private int _pointType = Item.POINTTYPE_SQUARE;
33
34 private boolean _filled = true;
35
36 protected boolean _filledHighlight = false;
37
38 public Dot(int id) {
39 super();
40 setID(id);
41 }
42
43 /**
44 * Constructs a new Point with the given x,y coordinates and Item ID.
45 *
46 * @param x
47 * The x coordinate of this point
48 * @param y
49 * The y coordinate of this point
50 * @param id
51 * The Item ID of this Point
52 */
53 public Dot(int x, int y, int id) {
54 super();
55 setID(id);
56 setPosition(x, y);
57 }
58
59 public void setPointType(int type) {
60 _pointType = type;
61 }
62
63 public void useFilledPoints(boolean val) {
64 _filled = val;
65 }
66
67 @Override
68 protected boolean hasVisibleArrow() {
69 return getArrowheadRatio() != 0 && getArrowheadLength() != 0;
70 }
71
72 /**
73 * Sets the 'thickness' of this Dot, that is, how many pixels this Dot
74 * should be.
75 *
76 * @param thick
77 * The number of pixels to use when displaying this Dot The Dot
78 * is displayed as a thick x thick square.
79 */
80 @Override
81 public void setThickness(float thick) {
82 super.setThickness(thick);
83
84 updatePolygon();
85 }
86
87 @Override
88 public void setColor(Color c) {
89 super.setColor(c);
90
91 // update the colour of any lines
92 for (Line line : getLines())
93 line.setColor(c);
94 }
95
96 @Override
97 public void paint(Graphics2D g) {
98 if (isHighlighted() /* && !Frame.FreeItems.contains(this) */) {
99 g.setColor(getHighlightColor());
100 // Draw the highlighting rectangle surrounding the dot
101 // this is drawn even if its part of a rectangle
102 Rectangle rect = getPolygon().getBounds();
103 if (_mode == SelectedMode.Enclosed ||
104 // Make sure single dots are highlighted filled
105 this.getConnected().size() <= 1)
106 g.fillRect(rect.x, rect.y, rect.width, rect.height);
107 else if (_mode == SelectedMode.Connected)
108 g.drawRect(rect.x, rect.y, rect.width, rect.height);
109 else if (_mode == SelectedMode.Normal) {
110 g.fillOval(rect.x, rect.y, rect.width, rect.height);
111 }
112 //System.out.println(_mode.toString());
113 }
114
115 // dots on lines are hidden
116 if (getLines().size() > 0)
117 return;
118
119 g.setColor(getPaintColor());
120
121 int thick = (int) getThickness();
122 if (thick < 2)
123 thick = 2;
124
125 int width = thick / 2;
126
127 if (_pointType == Item.POINTTYPE_CIRCLE) {
128 int points = 40;
129
130 double radians = 0.0;
131 int xPoints[] = new int[points];
132 int yPoints[] = new int[xPoints.length];
133
134 for (int i = 0; i < xPoints.length; i++) {
135 xPoints[i] = getX() + (int) (width * Math.cos(radians));
136 yPoints[i] = getY() + (int) (width * Math.sin(radians));
137 radians += (2.0 * Math.PI) / xPoints.length;
138 }
139
140 if (_filled)
141 g.fillPolygon(new Polygon(xPoints, yPoints, xPoints.length));
142 else
143 g.drawPolygon(new Polygon(xPoints, yPoints, xPoints.length));
144 } else {
145 if (_filled)
146 g.fillRect(getX() - width, getY() - width, thick, thick);
147 else
148 g.drawRect(getX() - width, getY() - width, thick, thick);
149 }
150
151 }
152
153 /**
154 * Updates the points of the polygon surrounding this Dot
155 */
156 protected void updatePolygon() {
157 int thick = (int) Math.ceil(getThickness());
158 // Sets a minimum size for the dot
159 thick = Math.max(thick, _MINIMUM_DOT_SIZE);
160
161 int x = getX() - thick / 2;
162 int y = getY() - thick / 2;
163
164 _poly = new Polygon();
165 _poly.addPoint(x - getGravity(), y - getGravity());
166 _poly.addPoint(x + thick + getGravity(), y - getGravity());
167 _poly.addPoint(x + thick + getGravity(), y + thick + getGravity());
168 _poly.addPoint(x - getGravity(), y + thick + getGravity());
169 }
170
171 @Override
172 public Polygon getPolygon() {
173 if (_poly == null)
174 updatePolygon();
175
176 Polygon external = new Polygon(_poly.xpoints, _poly.ypoints,
177 _poly.npoints);
178
179 return external;
180 }
181
182 @Override
183 public Item copy() {
184 Dot copy = new Dot(getX(), getY(), getID());
185
186 Item.DuplicateItem(this, copy);
187
188 copy.setThickness(getThickness());
189 copy.setPointType(_pointType);
190 copy.useFilledPoints(_filled);
191
192 return copy;
193 }
194
195 @Override
196 public int setSelectionColor() {
197 super.setSelectionColor();
198
199 return Item.DEFAULT_CURSOR;
200 }
201
202 @Override
203 public void setAnnotation(boolean val) {
204 DisplayIO.setCursorPosition(this.getPosition());
205 FrameKeyboardActions.replaceDot(this, '@');
206 }
207
208 @Override
209 public Item merge(Item merger, int mouseX, int mouseY) {
210 // if the item being merged with is another Dot
211 if (merger instanceof Dot) {
212 Item dot = (Item) merger;
213 merger.setPosition(this.getPosition());
214 // prevent concurrency issues if removing lines
215 List<Line> lines = new ArrayList<Line>();
216 lines.addAll(dot.getLines());
217
218 for (Line line : lines) {
219 // remove lines that are in common
220 if (getLines().contains(line)) {
221 dot.removeLine(line);
222 removeLine(line);
223 } else {
224 // check for duplicated lines as a result of merging
225 Item check = (Item) line.getOppositeEnd(dot);
226 boolean dup = false;
227
228 for (Line l : getLines()) {
229 Item opposite = l.getOppositeEnd(this);
230
231 if (check == opposite) {
232 line.getStartItem().removeLine(line);
233 line.getEndItem().removeLine(line);
234 dup = true;
235 break;
236 }
237 }
238
239 if (!dup)
240 line.replaceEnd(dot, this);
241 }
242 }
243
244 setThickness(dot.getThickness());
245 setColor(dot.getColor());
246 setFillColor(dot.getFillColor());
247
248 return null;
249 }
250
251 if (merger instanceof Text) {
252 merger.setPosition(this.getPosition());
253 List<Line> lines = new LinkedList<Line>();
254 lines.addAll(getLines());
255 for (Line line : lines)
256 line.replaceEnd(this, merger);
257 this.delete();
258 return merger;
259 }
260
261 // if the item being merged with is a Line
262 if (merger instanceof Line) {
263 Line line = (Line) merger;
264 // if this dot is part of the line then keep it, otherwise it
265 // can be removed
266 if (line.getOppositeEnd(this) != null && getLines().contains(line))
267 return merger;
268 else
269 return null;
270 }
271
272 return merger;
273 }
274
275 @Override
276 public String getTypeAndID() {
277 return "P " + getID();
278 }
279
280 @Override
281 public void setFilledHighlight(boolean value) {
282 _filledHighlight = value;
283 }
284
285 @Override
286 public void delete() {
287 super.delete();
288
289 for (Line l : this.getLines())
290 l.delete();
291 }
292
293 @Override
294 public void anchor() {
295 Frame current = getParentOrCurrentFrame();
296 //This is to make lines anchored across frames be on one frame
297 for(Line l: getLines()) {
298 Frame parent = l.getOppositeEnd(this).getParent();
299 if (parent != null && parent != current) {
300 this.setParent(parent);
301 if(DisplayIO.getCurrentSide() == 0)
302 this.setX(this.getX() - DisplayIO.getMiddle());
303 else
304 this.setX(this.getX() + DisplayIO.getMiddle());
305 }
306 break;
307 }
308
309 super.anchor();
310
311 //TODO is the code below needed... what for?
312 for (Line line : getLines()) {
313 if (line.getID() < 0 && !current.getItems().contains(line)) {
314 line.setID(current.getNextItemID());
315 line.setSelectionColor();
316 // Mike: Why was this line here?
317 //anchor(line);
318 }
319 }
320 }
321
322 @Override
323 public void addLine(Line line) {
324 super.addLine(line);
325 line.setColor(getColor());
326 line.setThickness(getThickness());
327 line.setLinePattern(getLinePattern());
328 }
329
330 @Override
331 public void lineColorChanged(Color c) {
332 if (getColor() != c) {
333 setColor(c);
334 }
335 }
336}
Note: See TracBrowser for help on using the repository browser.