Skip to content

Commit 7ebc956

Browse files
committed
Factor out Annotation interface and create minimal DefaultAnnotation
1 parent 9041d63 commit 7ebc956

File tree

3 files changed

+70
-243
lines changed

3 files changed

+70
-243
lines changed
Lines changed: 23 additions & 241 deletions
Original file line numberDiff line numberDiff line change
@@ -1,248 +1,30 @@
1+
/*
2+
* OpenSlide, a library for reading whole slide image files
3+
*
4+
* Copyright (c) 2007-2010 Carnegie Mellon University
5+
* All rights reserved.
6+
*
7+
* OpenSlide is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU Lesser General Public License as
9+
* published by the Free Software Foundation, version 2.1.
10+
*
11+
* OpenSlide is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public
17+
* License along with OpenSlide. If not, see
18+
* <http://www.gnu.org/licenses/>.
19+
*
20+
*/
21+
122
package edu.cmu.cs.openslide.gui;
223

3-
import java.awt.Rectangle;
424
import java.awt.Shape;
5-
import java.awt.geom.*;
6-
import java.util.Collections;
7-
import java.util.HashMap;
8-
import java.util.Map;
9-
10-
public class Annotation {
11-
public static class Bean {
12-
public static class Pair {
13-
public Pair(String name, String value) {
14-
this.name = name;
15-
this.value = value;
16-
}
17-
18-
public Pair() {
19-
};
20-
21-
public String getName() {
22-
return name;
23-
}
24-
25-
public void setName(String name) {
26-
this.name = name;
27-
}
28-
29-
public String getValue() {
30-
return value;
31-
}
32-
33-
public void setValue(String value) {
34-
this.value = value;
35-
}
36-
37-
private String name;
38-
39-
private String value;
40-
}
41-
42-
private Pair annotations[];
43-
44-
private String shape;
45-
46-
public String getShape() {
47-
return shape;
48-
}
49-
50-
public Pair[] getAnnotations() {
51-
return annotations;
52-
}
53-
54-
public void setAnnotations(Pair[] annotations) {
55-
this.annotations = annotations;
56-
}
57-
58-
public void setShape(String shape) {
59-
this.shape = shape;
60-
}
61-
62-
public Bean() {
63-
}
64-
65-
public Annotation toAnnotation() {
66-
Map<String, String> annotations;
67-
if (this.annotations != null) {
68-
annotations = new HashMap<String, String>();
69-
for (int i = 0; i < this.annotations.length; i++) {
70-
Pair p = this.annotations[i];
71-
annotations.put(p.getName(), p.getValue());
72-
}
73-
} else {
74-
annotations = Collections.emptyMap();
75-
}
76-
77-
String[] segs = shape.split(" ");
78-
Path2D p = new Path2D.Double();
79-
80-
int i = 0;
81-
while (i < segs.length) {
82-
switch (segs[i++].charAt(0)) {
83-
case 'Z':
84-
p.closePath();
85-
break;
86-
case 'C':
87-
p.curveTo(Double.parseDouble(segs[i++]), Double
88-
.parseDouble(segs[i++]), Double
89-
.parseDouble(segs[i++]), Double
90-
.parseDouble(segs[i++]), Double
91-
.parseDouble(segs[i++]), Double
92-
.parseDouble(segs[i++]));
93-
break;
94-
case 'L':
95-
p.lineTo(Double.parseDouble(segs[i++]), Double
96-
.parseDouble(segs[i++]));
97-
break;
98-
case 'M':
99-
p.moveTo(Double.parseDouble(segs[i++]), Double
100-
.parseDouble(segs[i++]));
101-
break;
102-
case 'Q':
103-
p.quadTo(Double.parseDouble(segs[i++]), Double
104-
.parseDouble(segs[i++]), Double
105-
.parseDouble(segs[i++]), Double
106-
.parseDouble(segs[i++]));
107-
break;
108-
}
109-
}
110-
return new Annotation(p, annotations);
111-
}
112-
113-
Bean(Shape shape, Map<String, String> annotations) {
114-
this.shape = serialize(shape);
115-
this.annotations = new Pair[annotations.size()];
116-
int i = 0;
117-
for (Map.Entry<String, String> e : annotations.entrySet()) {
118-
this.annotations[i] = new Pair(e.getKey(), e.getValue());
119-
i++;
120-
}
121-
}
122-
123-
private static String serialize(Shape s) {
124-
PathIterator p = s.getPathIterator(null);
125-
StringBuilder sb = new StringBuilder();
126-
127-
while (!p.isDone()) {
128-
double coords[] = new double[6];
129-
130-
switch (p.currentSegment(coords)) {
131-
case PathIterator.SEG_CLOSE:
132-
sb.append(" Z");
133-
break;
134-
case PathIterator.SEG_CUBICTO:
135-
sb.append(" C");
136-
sb.append(" " + coords[0]);
137-
sb.append(" " + coords[1]);
138-
sb.append(" " + coords[2]);
139-
sb.append(" " + coords[3]);
140-
sb.append(" " + coords[4]);
141-
sb.append(" " + coords[5]);
142-
break;
143-
case PathIterator.SEG_LINETO:
144-
sb.append(" L");
145-
sb.append(" " + coords[0]);
146-
sb.append(" " + coords[1]);
147-
break;
148-
case PathIterator.SEG_MOVETO:
149-
sb.append(" M");
150-
sb.append(" " + coords[0]);
151-
sb.append(" " + coords[1]);
152-
break;
153-
case PathIterator.SEG_QUADTO:
154-
sb.append(" Q");
155-
sb.append(" " + coords[0]);
156-
sb.append(" " + coords[1]);
157-
sb.append(" " + coords[2]);
158-
sb.append(" " + coords[3]);
159-
sb.append(" " + coords[4]);
160-
sb.append(" " + coords[5]);
161-
break;
162-
}
163-
164-
p.next();
165-
}
166-
return sb.toString().trim();
167-
}
168-
}
169-
170-
final private Map<String, String> annotations;
171-
172-
final private Shape shape;
173-
174-
final static private Map<String, String> EMPTY_MAP = Collections.emptyMap();
175-
176-
public Annotation(Shape shape, Map<String, String> annotations) {
177-
if (shape == null) {
178-
throw new NullPointerException("shape cannot be null");
179-
}
180-
this.shape = new ImmutableShape(shape);
181-
182-
this.annotations = Collections.unmodifiableMap(annotations);
183-
}
184-
185-
public Annotation(Shape shape) {
186-
this(shape, EMPTY_MAP);
187-
}
188-
189-
public Map<String, String> getAnnotations() {
190-
return annotations;
191-
}
192-
193-
public Shape getShape() {
194-
return shape;
195-
}
196-
197-
final private static class ImmutableShape implements Shape {
198-
final private Shape shape;
199-
200-
public boolean contains(double x, double y, double w, double h) {
201-
return shape.contains(x, y, w, h);
202-
}
203-
204-
public boolean contains(double x, double y) {
205-
return shape.contains(x, y);
206-
}
207-
208-
public boolean contains(Point2D p) {
209-
return shape.contains(p);
210-
}
211-
212-
public boolean contains(Rectangle2D r) {
213-
return shape.contains(r);
214-
}
215-
216-
public Rectangle getBounds() {
217-
return shape.getBounds();
218-
}
219-
220-
public Rectangle2D getBounds2D() {
221-
return shape.getBounds2D();
222-
}
223-
224-
public PathIterator getPathIterator(AffineTransform at, double flatness) {
225-
return shape.getPathIterator(at, flatness);
226-
}
227-
228-
public PathIterator getPathIterator(AffineTransform at) {
229-
return shape.getPathIterator(at);
230-
}
231-
232-
public boolean intersects(double x, double y, double w, double h) {
233-
return shape.intersects(x, y, w, h);
234-
}
23525

236-
public boolean intersects(Rectangle2D r) {
237-
return shape.intersects(r);
238-
}
26+
public interface Annotation {
23927

240-
public ImmutableShape(Shape s) {
241-
shape = s;
242-
}
243-
}
28+
Shape getShape();
24429

245-
public Bean toBean() {
246-
return new Bean(shape, annotations);
247-
}
24830
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* OpenSlide, a library for reading whole slide image files
3+
*
4+
* Copyright (c) 2007-2010 Carnegie Mellon University
5+
* All rights reserved.
6+
*
7+
* OpenSlide is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU Lesser General Public License as
9+
* published by the Free Software Foundation, version 2.1.
10+
*
11+
* OpenSlide is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public
17+
* License along with OpenSlide. If not, see
18+
* <http://www.gnu.org/licenses/>.
19+
*
20+
*/
21+
22+
package edu.cmu.cs.openslide.gui;
23+
24+
import java.awt.Shape;
25+
26+
// very minimal class, does not do defensive copying of shape
27+
class DefaultAnnotation implements Annotation {
28+
final private Shape shape;
29+
30+
public DefaultAnnotation(Shape shape) {
31+
if (shape == null) {
32+
throw new NullPointerException("shape cannot be null");
33+
}
34+
this.shape = shape;
35+
}
36+
37+
public Shape getShape() {
38+
return shape;
39+
}
40+
41+
@Override
42+
public String toString() {
43+
return shape.toString();
44+
}
45+
}

src/edu/cmu/cs/openslide/gui/OpenSlideView.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ public void mouseReleased(MouseEvent e) {
367367
if (selectionBeingDrawn != null) {
368368
Rectangle bb = selectionBeingDrawn.getBounds();
369369
if (bb.height != 0 && bb.width != 0) {
370-
selections.add(new Annotation(selectionBeingDrawn));
370+
selections.add(new DefaultAnnotation(selectionBeingDrawn));
371371
selectionBeingDrawn = null;
372372
}
373373
}
@@ -821,7 +821,7 @@ private void paintSelection(Graphics2D g) {
821821
}
822822

823823
public void addSelection(Shape s) {
824-
selections.add(new Annotation(s));
824+
selections.add(new DefaultAnnotation(s));
825825
repaint();
826826
}
827827

0 commit comments

Comments
 (0)