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

Last change on this file since 1318 was 1318, checked in by bln4, 5 years ago
File size: 10.7 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.util.ArrayList;
22import java.util.LinkedList;
23import java.util.List;
24
25import org.expeditee.core.Colour;
26import org.expeditee.core.Dimension;
27import org.expeditee.core.Fill;
28import org.expeditee.core.Point;
29import org.expeditee.core.bounds.AxisAlignedBoxBounds;
30import org.expeditee.core.bounds.Bounds;
31import org.expeditee.core.bounds.PolygonBounds;
32import org.expeditee.gio.EcosystemManager;
33import org.expeditee.gio.GraphicsManager;
34import org.expeditee.gui.DisplayController;
35import org.expeditee.gui.Frame;
36
37/**
38 * Represents a point on the screen. All Point objects are stored as x,y pairs
39 * with an Item ID. Note: Lines and all combinates of lines (rectangles, etc)
40 * are represented only as Points that share line IDs.
41 *
42 * @author jdm18
43 *
44 */
45public class Dot extends Item {
46
47 // Standard Item variables
48
49 // private static final int _MINIMUM_DOT_SIZE = 6;
50
51 private static final int MINIMUM_DOT_SIZE = 2;
52
53 public Dot(int id) {
54 super();
55 setID(id);
56 }
57
58 /**
59 * Constructs a new Point with the given x,y coordinates and Item ID.
60 *
61 * @param x
62 * The x coordinate of this point
63 * @param y
64 * The y coordinate of this point
65 * @param id
66 * The Item ID of this Point
67 */
68 public Dot(int x, int y, int id) {
69 super();
70 setID(id);
71 setPosition(x, y);
72 }
73
74 @Override
75 public void setColor(Colour c) {
76 super.setColor(c);
77
78 // update the colour of any lines
79 for (Line line : getLines())
80 line.setColor(c);
81 }
82
83 @Override
84 public void setAnchorLeft(Integer anchor) {
85 if (!isLineEnd()) {
86 super.setAnchorLeft(anchor);
87 return;
88 }
89
90 invalidateFill();
91 invalidateCommonTrait(ItemAppearence.PreMoved);
92
93 this._anchoring.setLeftAnchor(anchor);
94
95 int oldX = getX();
96 if (anchor != null) {
97 float deltaX = anchor - oldX;
98 anchorConnected(AnchorEdgeType.Left, deltaX);
99 }
100
101 invalidateCommonTrait(ItemAppearence.PostMoved);
102 invalidateFill();
103 }
104
105 @Override
106 public void setAnchorRight(Integer anchor) {
107 if (!isLineEnd()) {
108 super.setAnchorRight(anchor);
109 return;
110 }
111 invalidateFill();
112 invalidateCommonTrait(ItemAppearence.PreMoved);
113
114 this._anchoring.setRightAnchor(anchor);
115
116 int oldX = getX();
117 if (anchor != null) {
118 float deltaX = DisplayController.getFramePaintAreaWidth() - anchor - getBoundsWidth() - oldX;
119
120 anchorConnected(AnchorEdgeType.Right, deltaX);
121 }
122
123 invalidateCommonTrait(ItemAppearence.PostMoved);
124 invalidateFill();
125 }
126
127 @Override
128 public void setAnchorTop(Integer anchor) {
129 if (!isLineEnd()) {
130 super.setAnchorTop(anchor);
131 return;
132 }
133 invalidateFill();
134 invalidateCommonTrait(ItemAppearence.PreMoved);
135
136 this._anchoring.setTopAnchor(anchor);
137
138 int oldY = getY();
139 if (anchor != null) {
140 float deltaY = anchor - oldY;
141 anchorConnected(AnchorEdgeType.Top, deltaY);
142 }
143
144 invalidateCommonTrait(ItemAppearence.PostMoved);
145 invalidateFill();
146 }
147
148 @Override
149 public void setAnchorBottom(Integer anchor) {
150 if (!isLineEnd()) {
151 super.setAnchorBottom(anchor);
152 return;
153 }
154 invalidateFill();
155 invalidateCommonTrait(ItemAppearence.PreMoved);
156
157 this._anchoring.setBottomAnchor(anchor);
158
159 int oldY = getY();
160 if (anchor != null) {
161 float deltaY = DisplayController.getFramePaintAreaHeight() - anchor - getBoundsHeight() - oldY;
162 anchorConnected(AnchorEdgeType.Bottom, deltaY);
163 }
164
165 invalidateCommonTrait(ItemAppearence.PostMoved);
166 invalidateFill();
167 }
168
169
170
171 @Override
172 public void paint() {
173 GraphicsManager g = EcosystemManager.getGraphicsManager();
174 if (isHighlighted() /* && !FreeItems.getInstance().contains(this) */) {
175 Colour highlightColor = getHighlightColor();
176 Fill fill = new Fill(highlightColor);
177 // g.setStroke()
178 // Draw the highlighting rectangle surrounding the dot
179 // this is drawn even if its part of a rectangle
180
181 if (isVectorItem()) invalidateBounds();
182
183 AxisAlignedBoxBounds bounds = getBoundingBox();
184 if (_highlightMode == HighlightMode.Enclosed || this.getConnected().size() <= 1) { // Make sure single dots are highlighted filled
185 g.drawRectangle(bounds.getTopLeft(), bounds.getSize(), 0.0f, fill, highlightColor, DOT_STROKE, null);
186 } else if (_highlightMode == HighlightMode.Connected) {
187 g.drawRectangle(bounds.getTopLeft(), bounds.getSize(), 0.0f, null, highlightColor, HIGHLIGHT_STROKE, null);
188 } else if (_highlightMode == HighlightMode.Normal) {
189 g.drawOval(bounds.getCentre(), bounds.getSize(), 0.0f, fill, highlightColor, DOT_STROKE);
190 }
191 // System.out.println(_mode.toString());
192 }
193
194 // dots on lines are hidden
195 if (getLines().size() > 0) return;
196
197 int thick = (int) getThickness();
198 if (thick < MINIMUM_DOT_SIZE) thick = MINIMUM_DOT_SIZE;
199
200 Fill fill = _filled ? new Fill(getPaintColor()) : null;
201
202 // TODO: On testing, this code doesn't seem to work (can't change to any type except square). cts16
203 switch (_type) {
204 case circle:
205 g.drawOval(
206 new Point(getX(), getY()),
207 new Dimension(thick, thick),
208 0.0,
209 fill,
210 getPaintColor(),
211 null
212 );
213 break;
214 case diamond:
215 PolygonBounds diamond = PolygonBounds.getDiamond(thick, thick).translate(getX(), getY()).close();
216 g.drawPolygon(diamond, null, null, 0.0, fill, getPaintColor(), null);
217 break;
218 case triangle:
219 PolygonBounds triangle = PolygonBounds.getTriangle(thick, thick).translate(getX(), getY()).close();
220 g.drawPolygon(triangle, null, null, 0.0, fill, getPaintColor(), null);
221 break;
222 case roundSquare:
223 int arc = thick / 4;
224 g.drawRectangle(
225 new Point(getX(), getY()),
226 new Dimension(thick, thick),
227 0.0,
228 fill,
229 getPaintColor(),
230 null,
231 new Dimension(arc, arc)
232 );
233 break;
234 default:
235 g.drawRectangle(
236 new Point(getX(), getY()),
237 new Dimension(thick, thick),
238 0.0,
239 fill,
240 getPaintColor(),
241 null,
242 null
243 );
244 }
245
246 }
247
248 /**
249 * Updates the bounds surrounding this Dot.
250 * TODO: Standardise Dot minimum size. cts16
251 */
252 public Bounds updateBounds()
253 {
254 int thick = Math.round(getThickness());
255
256 // Sets a minimum size for the dot
257 thick = Math.max(thick, getGravity() * 2);
258
259 // Include the gravity in the thickness
260 thick += 2 * getGravity();
261
262
263 int x = getX() - thick / 2;
264 int y = getY() - thick / 2;
265
266 return new AxisAlignedBoxBounds(x, y, thick, thick);
267 }
268
269 @Override
270 public Item copy() {
271 Dot copy = new Dot(getX(), getY(), getID());
272
273 Item.DuplicateItem(this, copy);
274
275 return copy;
276 }
277
278 @Override
279 public void setHighlightColorToDefault() {
280 super.setHighlightColorToDefault();
281
282 //return Item.DEFAULT_CURSOR;
283 }
284
285 @Override
286 public void setAnnotation(boolean val) {
287 DisplayController.setCursorPosition(this.getPosition());
288 Item.replaceDot(this, '@');
289 }
290
291 @Override
292 public Item merge(Item merger, int mouseX, int mouseY) {
293 // if the item being merged with is another Dot
294 if (merger instanceof Dot) {
295 if (merger.hasEnclosures() || hasEnclosures())
296 return merger;
297
298 Item dot = (Item) merger;
299 merger.setPosition(this.getPosition());
300 // prevent concurrency issues if removing lines
301 List<Line> lines = new ArrayList<Line>();
302 lines.addAll(dot.getLines());
303
304 for (Line line : lines) {
305 // remove lines that are in common
306 if (getLines().contains(line)) {
307 dot.removeLine(line);
308 removeLine(line);
309 } else {
310 // check for duplicated lines as a result of merging
311 Item check = (Item) line.getOppositeEnd(dot);
312 boolean dup = false;
313
314 for (Line l : getLines()) {
315 Item opposite = l.getOppositeEnd(this);
316
317 if (check == opposite) {
318 line.getStartItem().removeLine(line);
319 line.getEndItem().removeLine(line);
320 dup = true;
321 break;
322 }
323 }
324
325 if (!dup)
326 line.replaceLineEnd(dot, this);
327 }
328 }
329
330 setThickness(dot.getThickness());
331 setColor(dot.getColor());
332 setFillColor(dot.getFillColor());
333
334 return null;
335 }
336
337 if (merger instanceof Text) {
338 merger.setPosition(this.getPosition());
339 List<Line> lines = new LinkedList<Line>();
340 lines.addAll(getLines());
341 for (Line line : lines)
342 line.replaceLineEnd(this, merger);
343 this.delete();
344 return merger;
345 }
346
347 // if the item being merged with is a Line
348 if (merger instanceof Line) {
349 Line line = (Line) merger;
350 // if this dot is part of the line then keep it, otherwise it
351 // can be removed
352 if (line.getOppositeEnd(this) != null && getLines().contains(line))
353 return merger;
354 else
355 return null;
356 }
357
358 return merger;
359 }
360
361 @Override
362 public String getTypeAndID() {
363 return "P " + getID();
364 }
365
366 @Override
367 public void delete() {
368 super.delete();
369
370 for (Line l : this.getLines())
371 l.delete();
372 }
373
374 @Override
375 public void anchor() {
376 Frame current = getParentOrCurrentFrame();
377 // This is to make lines anchored across frames be on one frame
378 for (Line l : getLines()) {
379 Frame parent = l.getOppositeEnd(this).getParent();
380 if (parent != null && parent != current) {
381 this.setParent(parent);
382 if (DisplayController.getCurrentSide() == DisplayController.TwinFramesSide.LEFT)
383 this.setX(this.getX() - DisplayController.getTwinFramesSeparatorX());
384 else
385 this.setX(this.getX() + DisplayController.getTwinFramesSeparatorX());
386 }
387 break;
388 }
389
390 super.anchor();
391
392 // TODO is the code below needed... what for?
393 for (Line line : getLines()) {
394 if (line.getID() < 0 && !current.getItems().contains(line)) {
395 line.setID(current.getNextItemID());
396 line.setHighlightColorToDefault();
397 // Mike: Why was this line here?
398 // anchor(line);
399 }
400 }
401 }
402
403 @Override
404 public void addLine(Line line) {
405 super.addLine(line);
406 line.setColor(getColor());
407 line.setThickness(getThickness());
408 line.setLinePattern(getLinePattern());
409 }
410
411 @Override
412 public void lineColorChanged(Colour c) {
413 if (getColor() != c) {
414 setColor(c);
415 }
416 }
417
418 @Override
419 public boolean dontSave() {
420 if (getThickness() <= 1 && (getLines().size() == 0)
421 && getConstraints().size() == 0) {
422 return true;
423 }
424 return super.dontSave();
425 }
426
427 @Override
428 public float getSize()
429 {
430 return getThickness();
431 }
432}
Note: See TracBrowser for help on using the repository browser.