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

Last change on this file since 919 was 919, checked in by jts21, 10 years ago

Added license headers to all files, added full GPL3 license file, moved license header generator script to dev/bin/scripts

File size: 10.4 KB
Line 
1/**
2 * Dot.java
3 * Copyright (C) 2010 New Zealand Digital Library, http://expeditee.org
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package org.expeditee.items;
20
21import java.awt.Color;
22import java.awt.Graphics2D;
23import java.awt.Polygon;
24import java.awt.Rectangle;
25import java.util.ArrayList;
26import java.util.LinkedList;
27import java.util.List;
28
29import org.expeditee.gui.DisplayIO;
30import org.expeditee.gui.Frame;
31import org.expeditee.gui.FrameGraphics;
32import org.expeditee.gui.FrameKeyboardActions;
33
34/**
35 * Represents a point on the screen. All Point objects are stored as x,y pairs
36 * with an Item ID. Note: Lines and all combinates of lines (rectangles, etc)
37 * are represented only as Points that share line IDs.
38 *
39 * @author jdm18
40 *
41 */
42public class Dot extends Item {
43
44 // Standard Item variables
45
46 // private static final int _MINIMUM_DOT_SIZE = 6;
47
48 private static final int MINIMUM_DOT_SIZE = 2;
49
50 public Dot(int id) {
51 super();
52 setID(id);
53 }
54
55 /**
56 * Constructs a new Point with the given x,y coordinates and Item ID.
57 *
58 * @param x
59 * The x coordinate of this point
60 * @param y
61 * The y coordinate of this point
62 * @param id
63 * The Item ID of this Point
64 */
65 public Dot(int x, int y, int id) {
66 super();
67 setID(id);
68 setPosition(x, y);
69 }
70
71 @Override
72 public void setColor(Color c) {
73 super.setColor(c);
74
75 // update the colour of any lines
76 for (Line line : getLines())
77 line.setColor(c);
78 }
79
80 @Override
81 public void setAnchorLeft(Float anchor) {
82 if (!isLineEnd()) {
83 super.setAnchorLeft(anchor);
84 return;
85 }
86
87 invalidateFill();
88 invalidateCommonTrait(ItemAppearence.PreMoved);
89
90 this._anchorLeft = anchor;
91 this._anchorRight = null;
92
93 int oldX = getX();
94 if (anchor != null) {
95 float deltaX = anchor - oldX;
96 anchorConnected(AnchorEdgeType.Left, deltaX);
97 }
98
99 invalidateCommonTrait(ItemAppearence.PostMoved);
100 invalidateFill();
101 }
102
103 @Override
104 public void setAnchorRight(Float anchor) {
105 if (!isLineEnd()) {
106 super.setAnchorRight(anchor);
107 return;
108 }
109 invalidateFill();
110 invalidateCommonTrait(ItemAppearence.PreMoved);
111
112 this._anchorRight = anchor;
113 this._anchorLeft = null;
114
115 int oldX = getX();
116 if (anchor != null) {
117 float deltaX = FrameGraphics.getMaxFrameSize().width - anchor
118 - getBoundsWidth() - oldX;
119
120 anchorConnected(AnchorEdgeType.Right, deltaX);
121 }
122
123 invalidateCommonTrait(ItemAppearence.PostMoved);
124 invalidateFill();
125 }
126
127 @Override
128 public void setAnchorTop(Float anchor) {
129 if (!isLineEnd()) {
130 super.setAnchorTop(anchor);
131 return;
132 }
133 invalidateFill();
134 invalidateCommonTrait(ItemAppearence.PreMoved);
135
136 this._anchorTop = anchor;
137 this._anchorBottom = null;
138
139 int oldY = getY();
140 if (anchor != null) {
141 float deltaY = anchor - oldY;
142 anchorConnected(AnchorEdgeType.Top, deltaY);
143 }
144
145 invalidateCommonTrait(ItemAppearence.PostMoved);
146 invalidateFill();
147 }
148
149 @Override
150 public void setAnchorBottom(Float anchor) {
151 if (!isLineEnd()) {
152 super.setAnchorBottom(anchor);
153 return;
154 }
155 invalidateFill();
156 invalidateCommonTrait(ItemAppearence.PreMoved);
157
158 this._anchorBottom = anchor;
159 this._anchorTop = null;
160
161 int oldY = getY();
162 if (anchor != null) {
163 float deltaY = FrameGraphics.getMaxFrameSize().height - anchor
164 - getBoundsHeight() - oldY;
165 anchorConnected(AnchorEdgeType.Bottom, deltaY);
166 }
167
168 invalidateCommonTrait(ItemAppearence.PostMoved);
169 invalidateFill();
170 }
171
172
173
174 @Override
175 public void paint(Graphics2D g) {
176 if (isHighlighted() /* && !FreeItems.getInstance().contains(this) */) {
177 Color highlightColor = getHighlightColor();
178 g.setColor(highlightColor);
179 g.setStroke(DOT_STROKE);
180 // g.setStroke()
181 // Draw the highlighting rectangle surrounding the dot
182 // this is drawn even if its part of a rectangle
183
184 if (isVectorItem())
185 updatePolygon();
186
187 Rectangle rect = getPolygon().getBounds();
188 if (_mode == HighlightMode.Enclosed ||
189 // Make sure single dots are highlighted filled
190 this.getConnected().size() <= 1)
191 g.fillRect(rect.x, rect.y, rect.width, rect.height);
192 else if (_mode == HighlightMode.Connected){
193 g.setStroke(HIGHLIGHT_STROKE);
194 g.drawRect(rect.x, rect.y, rect.width, rect.height);
195 }else if (_mode == HighlightMode.Normal) {
196 g.fillOval(rect.x, rect.y, rect.width, rect.height);
197 }
198 // System.out.println(_mode.toString());
199 }
200
201 // dots on lines are hidden
202 if (getLines().size() > 0)
203 return;
204
205 g.setColor(getPaintColor());
206
207 int thick = (int) getThickness();
208 if (thick < MINIMUM_DOT_SIZE)
209 thick = MINIMUM_DOT_SIZE;
210
211 int width = thick / 2;
212
213 switch (_type) {
214 case circle:
215 if (_filled)
216 g.fillOval(getX() - width, getY() - width, thick, thick);
217 else {
218 g.drawOval(getX() - width, getY() - width, thick, thick);
219 }
220 break;
221 case diamond:
222 int[] x = new int[4];
223 int[] y = new int[4];
224
225 x[0] = x[2] = getX();
226 x[1] = getX() - width;
227 x[3] = getX() + width;
228
229 y[1] = y[3] = getY();
230 y[0] = getY() - width;
231 y[2] = getY() + width;
232
233 if (_filled)
234 g.fillPolygon(x, y, 4);
235 else {
236 g.drawPolygon(x, y, 4);
237 }
238 break;
239 case triangle:
240 x = new int[3];
241 y = new int[3];
242
243 x[0] = getX();
244 x[1] = getX() - width;
245 x[2] = getX() + width;
246
247 y[0] = getY() - width;
248 y[1] = y[2] = getY() + width;
249
250 if (_filled)
251 g.fillPolygon(x, y, 3);
252 else {
253 g.drawPolygon(x, y, 3);
254 }
255 break;
256 case roundSquare:
257 int arc = thick / 2;
258 if (_filled)
259 g.fillRoundRect(getX() - width, getY() - width, thick, thick,
260 arc, arc);
261 else {
262 g.drawRoundRect(getX() - width, getY() - width, thick, thick,
263 arc, arc);
264 }
265 break;
266 default:
267 if (_filled)
268 g.fillRect(getX() - width, getY() - width, thick, thick);
269 else {
270 g.drawRect(getX() - width, getY() - width, thick, thick);
271 }
272
273 }
274
275 }
276
277 /**
278 * Updates the points of the polygon surrounding this Dot
279 */
280 public void updatePolygon() {
281 int thick = Math.round(getThickness());
282 // Sets a minimum size for the dot
283 thick = Math.max(thick, getGravity() * 2);
284
285 int x = getX() - thick / 2;
286 int y = getY() - thick / 2;
287
288 _poly = new Polygon();
289 _poly.addPoint(x - getGravity(), y - getGravity());
290 _poly.addPoint(x + thick + getGravity(), y - getGravity());
291 _poly.addPoint(x + thick + getGravity(), y + thick + getGravity());
292 _poly.addPoint(x - getGravity(), y + thick + getGravity());
293 }
294
295 @Override
296 public Item copy() {
297 Dot copy = new Dot(getX(), getY(), getID());
298
299 Item.DuplicateItem(this, copy);
300
301 return copy;
302 }
303
304 @Override
305 public int setHighlightColor() {
306 super.setHighlightColor();
307
308 return Item.DEFAULT_CURSOR;
309 }
310
311 @Override
312 public void setAnnotation(boolean val) {
313 DisplayIO.setCursorPosition(this.getPosition());
314 FrameKeyboardActions.replaceDot(this, '@');
315 }
316
317 @Override
318 public Item merge(Item merger, int mouseX, int mouseY) {
319 // if the item being merged with is another Dot
320 if (merger instanceof Dot) {
321 if (merger.hasEnclosures() || hasEnclosures())
322 return merger;
323
324 Item dot = (Item) merger;
325 merger.setPosition(this.getPosition());
326 // prevent concurrency issues if removing lines
327 List<Line> lines = new ArrayList<Line>();
328 lines.addAll(dot.getLines());
329
330 for (Line line : lines) {
331 // remove lines that are in common
332 if (getLines().contains(line)) {
333 dot.removeLine(line);
334 removeLine(line);
335 } else {
336 // check for duplicated lines as a result of merging
337 Item check = (Item) line.getOppositeEnd(dot);
338 boolean dup = false;
339
340 for (Line l : getLines()) {
341 Item opposite = l.getOppositeEnd(this);
342
343 if (check == opposite) {
344 line.getStartItem().removeLine(line);
345 line.getEndItem().removeLine(line);
346 dup = true;
347 break;
348 }
349 }
350
351 if (!dup)
352 line.replaceLineEnd(dot, this);
353 }
354 }
355
356 setThickness(dot.getThickness());
357 setColor(dot.getColor());
358 setFillColor(dot.getFillColor());
359
360 return null;
361 }
362
363 if (merger instanceof Text) {
364 merger.setPosition(this.getPosition());
365 List<Line> lines = new LinkedList<Line>();
366 lines.addAll(getLines());
367 for (Line line : lines)
368 line.replaceLineEnd(this, merger);
369 this.delete();
370 return merger;
371 }
372
373 // if the item being merged with is a Line
374 if (merger instanceof Line) {
375 Line line = (Line) merger;
376 // if this dot is part of the line then keep it, otherwise it
377 // can be removed
378 if (line.getOppositeEnd(this) != null && getLines().contains(line))
379 return merger;
380 else
381 return null;
382 }
383
384 return merger;
385 }
386
387 @Override
388 public String getTypeAndID() {
389 return "P " + getID();
390 }
391
392 @Override
393 public void delete() {
394 super.delete();
395
396 for (Line l : this.getLines())
397 l.delete();
398 }
399
400 @Override
401 public void anchor() {
402 Frame current = getParentOrCurrentFrame();
403 // This is to make lines anchored across frames be on one frame
404 for (Line l : getLines()) {
405 Frame parent = l.getOppositeEnd(this).getParent();
406 if (parent != null && parent != current) {
407 this.setParent(parent);
408 if (DisplayIO.getCurrentSide() == 0)
409 this.setX(this.getX() - DisplayIO.getMiddle());
410 else
411 this.setX(this.getX() + DisplayIO.getMiddle());
412 }
413 break;
414 }
415
416 super.anchor();
417
418 // TODO is the code below needed... what for?
419 for (Line line : getLines()) {
420 if (line.getID() < 0 && !current.getItems().contains(line)) {
421 line.setID(current.getNextItemID());
422 line.setHighlightColor();
423 // Mike: Why was this line here?
424 // anchor(line);
425 }
426 }
427 }
428
429 @Override
430 public void addLine(Line line) {
431 super.addLine(line);
432 line.setColor(getColor());
433 line.setThickness(getThickness());
434 line.setLinePattern(getLinePattern());
435 }
436
437 @Override
438 public void lineColorChanged(Color c) {
439 if (getColor() != c) {
440 setColor(c);
441 }
442 }
443
444 @Override
445 public boolean dontSave() {
446 if (getThickness() <= 1 && (getLines().size() == 0)
447 && getConstraints().size() == 0) {
448 return true;
449 }
450 return super.dontSave();
451 }
452}
Note: See TracBrowser for help on using the repository browser.