2 Copyright (C) 2001, 2006, 2007 United States Government
3 as represented by the Administrator of the
4 National Aeronautics and Space Administration.
7 package gov
.nasa
.worldwind
.examples
;
9 import gov
.nasa
.worldwind
.layers
.*;
10 import gov
.nasa
.worldwind
.geom
.*;
11 import gov
.nasa
.worldwind
.render
.*;
12 import gov
.nasa
.worldwind
.event
.SelectListener
;
13 import gov
.nasa
.worldwind
.event
.SelectEvent
;
14 import gov
.nasa
.worldwind
.View
;
15 import gov
.nasa
.worldwind
.awt
.WorldWindowGLCanvas
;
16 import gov
.nasa
.worldwind
.pick
.PickedObjectList
;
17 import gov
.nasa
.worldwind
.pick
.PickedObject
;
18 import gov
.nasa
.worldwind
.avlist
.AVKey
;
21 import javax
.swing
.event
.ChangeListener
;
22 import javax
.swing
.event
.ChangeEvent
;
23 import javax
.swing
.border
.CompoundBorder
;
24 import javax
.swing
.border
.TitledBorder
;
25 import javax
.media
.opengl
.GL
;
27 import java
.awt
.image
.BufferedImage
;
28 import java
.awt
.event
.ActionListener
;
29 import java
.awt
.event
.ActionEvent
;
30 import java
.util
.Iterator
;
32 import com
.sun
.opengl
.util
.j2d
.TextRenderer
;
35 * @author Patrick Murris
36 * @version $Id: Annotations.java 3541 2007-11-15 23:41:07Z patrickmurris $
38 public class Annotations
extends ApplicationTemplate
40 private static class AppFrame
extends ApplicationTemplate
.AppFrame
// implements MouseListener
42 private AnnotationLayer layer
;
43 private Annotation currentAnnotation
;
46 private final static String IMAGE_WWJ_SPLASH
= "images/400x230-splash-nww.png";
47 private final static String IMAGE_NASA
= "images/32x32-icon-nasa.png";
48 private final static String IMAGE_EARTH
= "images/32x32-icon-earth.png";
51 private JTextArea inputTextArea
;
52 private JCheckBox cbAdjustWidth
;
53 private JSlider widthSlider
, heightSlider
;
54 private JSlider scaleSlider
, opacitySlider
, cornerRadiusSlider
, borderWidthSlider
, stippleFactorSlider
;
55 private JComboBox cbFontName
, cbFontStyle
, cbFontSize
, cbTextAlign
, cbShape
, cbLeader
;
56 private JComboBox cbImage
, cbImageRepeat
, cbAntialias
, cbTextEffect
;
57 private JSlider imageOpacitySlider
, imageScaleSlider
, imageOffsetXSlider
, imageOffsetYSlider
;
58 private JSlider offsetXSlider
, offsetYSlider
;
59 private JSlider distanceMinScaleSlider
, distanceMaxScaleSlider
, distanceMinOpacitySlider
;
60 private JSlider highlightScaleSlider
;
61 private JSpinner insetsTop
, insetsRight
, insetsBottom
, insetsLeft
;
62 private JButton btTextColor
, btBackColor
, btBorderColor
;
63 private JComboBox cbTextColorAlpha
, cbBackColorAlpha
, cbBorderColorAlpha
;
64 private JButton btAdd
, btApply
, btRemove
;
66 private boolean suspendUpdate
= false;
67 private Color savedBorderColor
;
68 private BufferedImage savedImage
;
70 private Annotation lastPickedObject
;
74 // Create a renderable layer with one stand alone annotations
75 RenderableLayer rl
= new RenderableLayer();
76 rl
.addRenderable(new GlobeAnnotation("Lat-Lon zero",
77 Position
.fromDegrees(0, 0, 0)));
78 insertBeforeCompass(this.getWwd(), rl
);
80 // Create an AnnotationLayer with lots of annotations
81 this.layer
= new AnnotationLayer();
84 // Add some annotations to the layer
85 // NOTE: use unicode for annotation text
88 layer
.addAnnotation(new GlobeAnnotation("MONACO", Position
.fromDegrees(43.7340, 7.4211, 0), Font
.decode("Arial-BOLD-12")));
89 layer
.addAnnotation(new GlobeAnnotation("NICE", Position
.fromDegrees(43.696, 7.27, 0), Font
.decode("Arial-BOLD-12")));
90 layer
.addAnnotation(new GlobeAnnotation("ANTIBES", Position
.fromDegrees(43.5810, 7.1248, 0), Font
.decode("Arial-BOLD-12")));
91 layer
.addAnnotation(new GlobeAnnotation("CANNES", Position
.fromDegrees(43.5536, 7.0171, 0), Font
.decode("Arial-BOLD-12")));
92 layer
.addAnnotation(new GlobeAnnotation("GRASSE", Position
.fromDegrees(43.6590, 6.9240, 0), Font
.decode("Arial-BOLD-12")));
93 layer
.addAnnotation(new GlobeAnnotation("FREJUS", Position
.fromDegrees(43.4326, 6.7356, 0), Font
.decode("Arial-BOLD-12")));
94 layer
.addAnnotation(new GlobeAnnotation("SAINTE MAXIME", Position
.fromDegrees(43.3087, 6.6353, 0), Font
.decode("Arial-BOLD-12")));
95 layer
.addAnnotation(new GlobeAnnotation("SAINT TROPEZ", Position
.fromDegrees(43.2710, 6.6386, 0), Font
.decode("Arial-BOLD-12")));
96 layer
.addAnnotation(new GlobeAnnotation("TOULON", Position
.fromDegrees(43.1264, 5.9126, 0), Font
.decode("Arial-BOLD-12")));
97 layer
.addAnnotation(new GlobeAnnotation("MARSEILLE", Position
.fromDegrees(43.2904, 5.3806, 0), Font
.decode("Arial-BOLD-12")));
98 layer
.addAnnotation(new GlobeAnnotation("AIX EN PROVENCE", Position
.fromDegrees(43.5286, 5.4485, 0), Font
.decode("Arial-BOLD-12")));
100 layer
.addAnnotation(new GlobeAnnotation("A\u00e9roport International\nNice C\u00f4te d'Azur", Position
.fromDegrees(43.6582, 7.2167, 0), Font
.decode("Arial-BOLDITALIC-10"), Color
.YELLOW
));
101 layer
.addAnnotation(new GlobeAnnotation("Sophia Antipolis", Position
.fromDegrees(43.6222, 7.0474, 0), Font
.decode("Arial-BOLDITALIC-10"), Color
.YELLOW
));
103 // Geographical features - use a common default AnnotationAttributes object
104 AnnotationAttributes geoAttr
= new AnnotationAttributes();
105 geoAttr
.setFrameShape(FrameFactory
.SHAPE_NONE
); // No frame
106 geoAttr
.setFont(Font
.decode("Arial-ITALIC-10"));
107 geoAttr
.setTextColor(Color
.GREEN
);
108 geoAttr
.setTextAlign(MultiLineTextRenderer
.ALIGN_CENTER
);
109 geoAttr
.setDrawOffset(new Point(0, 5)); // centered just above
110 geoAttr
.setEffect(MultiLineTextRenderer
.EFFECT_OUTLINE
); // Black outline
111 geoAttr
.setBackgroundColor(Color
.BLACK
);
112 layer
.addAnnotation(new GlobeAnnotation("Mont Chauve\nFort militaire\nAlt: 853m", Position
.fromDegrees(43.7701, 7.2544, 0), geoAttr
));
113 layer
.addAnnotation(new GlobeAnnotation("Mont Agel\nFort militaire\nAlt: 1148m", Position
.fromDegrees(43.7704, 7.4203, 0), geoAttr
));
114 layer
.addAnnotation(new GlobeAnnotation("Cap Ferrat", Position
.fromDegrees(43.6820, 7.3290, 0), geoAttr
));
115 layer
.addAnnotation(new GlobeAnnotation("Gorges du Loup", Position
.fromDegrees(43.7351, 6.9988, 0), geoAttr
));
116 layer
.addAnnotation(new GlobeAnnotation("Cap d'Antibes", Position
.fromDegrees(43.5526, 7.1297, 0), geoAttr
));
117 layer
.addAnnotation(new GlobeAnnotation("Iles de L\u00e9rins", Position
.fromDegrees(43.5125, 7.0467, 0), geoAttr
));
118 layer
.addAnnotation(new GlobeAnnotation("Montagne du Cheiron\nAlt: 1778m", Position
.fromDegrees(43.8149, 6.9669, 0), geoAttr
));
119 layer
.addAnnotation(new GlobeAnnotation("Giens", Position
.fromDegrees(43.0394, 6.1384, 0), geoAttr
));
120 layer
.addAnnotation(new GlobeAnnotation("Iles de Porquerolles", Position
.fromDegrees(42.9974, 6.2147, 0), geoAttr
));
121 layer
.addAnnotation(new GlobeAnnotation("Ile du Levent", Position
.fromDegrees(43.0315, 6.4702, 0), geoAttr
));
122 layer
.addAnnotation(new GlobeAnnotation("Ile de Port Cros", Position
.fromDegrees(43.0045, 6.3959, 0), geoAttr
));
123 layer
.addAnnotation(new GlobeAnnotation("Montagne Sainte Victoire\nAlt: 1010m", Position
.fromDegrees(43.5319, 5.6120, 0), geoAttr
));
124 layer
.addAnnotation(new GlobeAnnotation("Sainte Baume\nAlt: 1147m", Position
.fromDegrees(43.3373, 5.8008, 0), geoAttr
));
125 layer
.addAnnotation(new GlobeAnnotation("Pic de l'Ours\nAlt: 496m", Position
.fromDegrees(43.4763, 6.9042, 0), geoAttr
));
127 // Water bodies - ellipse shape and centered text
128 ga
= new GlobeAnnotation("Lac de Sainte Croix", Position
.fromDegrees(43.7720, 6.1879, 0), Font
.decode("Arial-ITALIC-10"), Color
.CYAN
);
129 ga
.getAttributes().setFrameShape(FrameFactory
.SHAPE_ELLIPSE
);
130 ga
.getAttributes().setTextAlign(MultiLineTextRenderer
.ALIGN_CENTER
);
131 ga
.getAttributes().setInsets(new Insets(8, 12, 9, 12));
132 layer
.addAnnotation(ga
);
133 ga
= new GlobeAnnotation("Lac de Castillon", Position
.fromDegrees(43.9008, 6.5348, 0), Font
.decode("Arial-ITALIC-10"), Color
.CYAN
);
134 ga
.getAttributes().setFrameShape(FrameFactory
.SHAPE_ELLIPSE
);
135 ga
.getAttributes().setTextAlign(MultiLineTextRenderer
.ALIGN_CENTER
);
136 ga
.getAttributes().setInsets(new Insets(8, 12, 9, 12));
137 layer
.addAnnotation(ga
);
138 ga
= new GlobeAnnotation("Lac de Serre Pon\u00e7on", Position
.fromDegrees(44.5081, 6.3242, 0), Font
.decode("Arial-ITALIC-10"), Color
.CYAN
);
139 ga
.getAttributes().setFrameShape(FrameFactory
.SHAPE_ELLIPSE
);
140 ga
.getAttributes().setTextAlign(MultiLineTextRenderer
.ALIGN_CENTER
);
141 ga
.getAttributes().setInsets(new Insets(8, 12, 9, 12));
142 layer
.addAnnotation(ga
);
144 // Longer text, custom colors and text align
145 ga
= new GlobeAnnotation("Transition Permien-Trias\nDate: 251Ma \nPlus grand \u00e9pisode d'extinction massive.",
146 Position
.fromDegrees(44.0551, 7.1215, 0), Font
.decode("Arial-ITALIC-12"), Color
.DARK_GRAY
);
147 ga
.getAttributes().setTextAlign(MultiLineTextRenderer
.ALIGN_RIGHT
);
148 ga
.getAttributes().setBackgroundColor(new Color(.8f
, .8f
, .8f
, .7f
));
149 ga
.getAttributes().setBorderColor(Color
.BLACK
);
150 layer
.addAnnotation(ga
);
152 // With HTML tags and background image no repeat
153 ga
= new GlobeAnnotation("<p>\n<b><font color=\"#664400\">LA CLAPI\u00c8RE</font></b><br />\n<i>Alt: 1100-1700m</i>\n</p>\n<p>\n<b>Glissement de terrain majeur</b> dans la haute Tin\u00e9e, sur un flanc du <a href=\"http://www.mercantour.eu\">Parc du Mercantour</a>, Alpes Maritimes.\n</p>\n<p>\nRisque aggravé d'<b>inondation</b> du village de <i>Saint \u00c9tienne de Tin\u00e9e</i> juste en amont.\n</p>",
154 Position
.fromDegrees(44.2522, 6.9424, 0), Font
.decode("Serif-PLAIN-14"), Color
.DARK_GRAY
);
155 ga
.getAttributes().setTextAlign(MultiLineTextRenderer
.ALIGN_RIGHT
);
156 ga
.getAttributes().setBackgroundColor(new Color(1f
, 1f
, 1f
, .7f
));
157 ga
.getAttributes().setBorderColor(Color
.BLACK
);
158 ga
.getAttributes().setSize(new Dimension(220, 0)); // Preferred max width, no length limit (default max width is 160)
159 ga
.getAttributes().setImageSource(IMAGE_EARTH
);
160 ga
.getAttributes().setImageRepeat(Annotation
.IMAGE_REPEAT_NONE
);
161 ga
.getAttributes().setImageOpacity(.6);
162 ga
.getAttributes().setImageScale(.7);
163 ga
.getAttributes().setImageOffset(new Point(7, 7));
164 layer
.addAnnotation(ga
);
166 // With some border stippling, width and antialias
167 ga
= new GlobeAnnotation("Latitude: 44.0 N\nLongitude: 7.0 W",
168 Position
.fromDegrees(44.0000, 7.000, 0), Font
.decode("Arial-ITALIC-12"), Color
.DARK_GRAY
);
169 ga
.getAttributes().setTextAlign(MultiLineTextRenderer
.ALIGN_CENTER
);
170 ga
.getAttributes().setBackgroundColor(new Color(.9f
, .9f
, .8f
, .7f
));
171 ga
.getAttributes().setBorderColor(Color
.BLACK
);
172 ga
.getAttributes().setBorderWidth(2);
173 ga
.getAttributes().setBorderStippleFactor(3);
174 ga
.getAttributes().setAntiAliasHint(Annotation
.ANTIALIAS_NICEST
);
175 layer
.addAnnotation(ga
);
177 // With background texture repeat Y
178 ga
= new GlobeAnnotation("SAHARA DESERT\n\nThe Sahara is technically the world's second largest desert after Antarctica.\n\nAt over 9,000,000 square kilometres (3,500,000 sq mi), it covers most parts of northern Africa. ", Position
.fromDegrees(22, 12, 0), Font
.decode("Arial-BOLD-12"));
179 ga
.getAttributes().setImageSource(IMAGE_NASA
);
180 ga
.getAttributes().setImageRepeat(Annotation
.IMAGE_REPEAT_Y
);
181 ga
.getAttributes().setImageOpacity(.6);
182 ga
.getAttributes().setImageScale(.7);
183 ga
.getAttributes().setImageOffset(new Point(1, 1));
184 ga
.getAttributes().setInsets(new Insets(6, 28, 6, 6));
185 layer
.addAnnotation(ga
);
187 // Splash screen with NPOT background texture
188 ga
= new GlobeAnnotation("Java SDK", Position
.fromDegrees(20, 00, 0), Font
.decode("Arial-BOLD-14"));
189 ga
.getAttributes().setTextAlign(MultiLineTextRenderer
.ALIGN_RIGHT
);
190 ga
.getAttributes().setImageSource(IMAGE_WWJ_SPLASH
);
191 ga
.getAttributes().setImageRepeat(Annotation
.IMAGE_REPEAT_NONE
);
192 ga
.getAttributes().setImageOpacity(.7);
193 ga
.getAttributes().setImageScale(.5); // scale texture to half size
194 ga
.getAttributes().setSize(new Dimension(200, 115)); // use this dimensions (half texture)
195 ga
.getAttributes().setAdjustWidthToText(Annotation
.SIZE_FIXED
); // use strict dimension - dont follow text width
196 layer
.addAnnotation(ga
);
198 // With background pattern and forced height
199 ga
= new GlobeAnnotation("Background patterns...", Position
.fromDegrees(10, 100, 0), Font
.decode("Arial-BOLD-16"), Color
.GRAY
);
200 ga
.getAttributes().setImageSource(PatternFactory
.createPattern(PatternFactory
.GRADIENT_VLINEAR
, new Dimension(32, 128), 1f
, Color
.WHITE
, new Color(0f
, 0f
, 0f
, 0f
))); // White to transparent
201 ga
.getAttributes().setSize(new Dimension(200, 128)); // force height to 128
202 layer
.addAnnotation(ga
);
203 ga
= new GlobeAnnotation("Background patterns...", Position
.fromDegrees(10, 110, 0), Font
.decode("Arial-BOLD-16"), Color
.GRAY
);
204 ga
.getAttributes().setImageSource(PatternFactory
.createPattern(PatternFactory
.GRADIENT_VLINEAR
, new Dimension(32, 64), 1f
, Color
.LIGHT_GRAY
, Color
.WHITE
)); // gray/white
205 ga
.getAttributes().setSize(new Dimension(200, 128));
206 layer
.addAnnotation(ga
);
207 ga
= new GlobeAnnotation("Background patterns...", Position
.fromDegrees(10, 120, 0), Font
.decode("Arial-BOLD-16"), Color
.BLACK
);
208 ga
.getAttributes().setImageSource(PatternFactory
.createPattern(PatternFactory
.PATTERN_DIAGONAL_UP
, Color
.YELLOW
)); // yellow stripes
209 ga
.getAttributes().setSize(new Dimension(200, 128));
210 layer
.addAnnotation(ga
);
212 ga
= new GlobeAnnotation("Background patterns...", Position
.fromDegrees(0, 100, 0), Font
.decode("Arial-BOLD-16"), Color
.GRAY
);
213 ga
.getAttributes().setImageSource(PatternFactory
.createPattern(PatternFactory
.GRADIENT_HLINEAR
, new Dimension(256, 32), 1f
, Color
.WHITE
, new Color(0f
, 0f
, 0f
, 0f
))); // White to transparent
214 ga
.getAttributes().setSize(new Dimension(200, 128));
215 layer
.addAnnotation(ga
);
216 ga
= new GlobeAnnotation("Background patterns...", Position
.fromDegrees(0, 110, 0), Font
.decode("Arial-BOLD-16"), Color
.GRAY
);
217 ga
.getAttributes().setImageSource(PatternFactory
.createPattern(PatternFactory
.GRADIENT_HLINEAR
, new Dimension(32, 64), 1f
, Color
.LIGHT_GRAY
, Color
.WHITE
)); // gray/white
218 ga
.getAttributes().setSize(new Dimension(200, 128));
219 layer
.addAnnotation(ga
);
220 ga
= new GlobeAnnotation("Background patterns...", Position
.fromDegrees(0, 120, 0), Font
.decode("Arial-BOLD-16"), Color
.BLACK
);
221 ga
.getAttributes().setImageSource(PatternFactory
.createPattern(PatternFactory
.PATTERN_SQUARES
, Color
.YELLOW
)); // yellow circles
222 ga
.getAttributes().setSize(new Dimension(200, 128));
223 layer
.addAnnotation(ga
);
225 ga
= new GlobeAnnotation("Background patterns...", Position
.fromDegrees(-10, 100, 0), Font
.decode("Arial-BOLD-16"), Color
.GRAY
);
226 ga
.getAttributes().setImageSource(PatternFactory
.createPattern(PatternFactory
.GRADIENT_HLINEAR
, new Dimension(16, 16), 1f
, Color
.BLACK
, Color
.WHITE
)); // Black to white
227 ga
.getAttributes().setImageRepeat(Annotation
.IMAGE_REPEAT_Y
);
228 ga
.getAttributes().setBackgroundColor(Color
.WHITE
);
229 ga
.getAttributes().setSize(new Dimension(200, 128));
230 layer
.addAnnotation(ga
);
231 ga
= new GlobeAnnotation("Background patterns...", Position
.fromDegrees(-10, 110, 0), Font
.decode("Arial-BOLD-16"), Color
.GRAY
);
232 ga
.getAttributes().setImageSource(PatternFactory
.createPattern(PatternFactory
.GRADIENT_VLINEAR
, new Dimension(16, 16), 1f
, Color
.BLACK
, Color
.WHITE
)); // Black to white
233 ga
.getAttributes().setImageRepeat(Annotation
.IMAGE_REPEAT_X
);
234 ga
.getAttributes().setBackgroundColor(Color
.WHITE
);
235 ga
.getAttributes().setSize(new Dimension(200, 128));
236 layer
.addAnnotation(ga
);
237 ga
= new GlobeAnnotation("Background patterns...", Position
.fromDegrees(-10, 120, 0), Font
.decode("Arial-BOLD-16"), Color
.BLACK
);
238 ga
.getAttributes().setImageSource(PatternFactory
.createPattern(PatternFactory
.PATTERN_HVLINE
, .15f
, Color
.GREEN
)); // green + lines
239 ga
.getAttributes().setImageScale(.4);
240 ga
.getAttributes().setSize(new Dimension(200, 128));
241 layer
.addAnnotation(ga
);
242 // Shows pattern scale effect on circles pattern
243 for (int i
= 1; i
<= 10; i
++)
245 ga
= new GlobeAnnotation("Pattern scale:" + (float)i
/ 10, Position
.fromDegrees(-20, 97 + i
* 3, 0), Font
.decode("Arial-BOLD-16"), Color
.GRAY
);
246 ga
.getAttributes().setImageSource(PatternFactory
.createPattern(PatternFactory
.PATTERN_CIRCLES
, (float)i
/ 10, Color
.LIGHT_GRAY
));
247 ga
.getAttributes().setImageScale(.4);
248 ga
.getAttributes().setSize(new Dimension(160, 60));
249 layer
.addAnnotation(ga
);
252 // Using a GlobeAnnotation subclass to override drawing
253 class SimpleGlobeAnnotation
extends GlobeAnnotation
255 TextRenderer textRenderer
;
256 Font font
= Font
.decode("Arial-PLAIN-12");
258 public SimpleGlobeAnnotation(String text
, Position position
)
260 super(text
, position
);
263 public void drawAnnotation(DrawContext dc
, Point screenPoint
, double drawScale
, double drawAlpha
, Position pickPosition
)
265 if(this.textRenderer
== null)
266 this.textRenderer
= getTextRenderer(dc
, this.font
);
267 // Draw text centered just above the screen point - use annotation's colors
268 String text
= getText().split("\n")[0]; // First line only
269 int textWidth
= (int)this.textRenderer
.getBounds(text
).getWidth();
270 Color textColor
= getAttributes().getTextColor();
271 Color backColor
= getAttributes().getBackgroundColor();
272 this.textRenderer
.begin3DRendering();
273 this.textRenderer
.setColor(backColor
);
274 this.textRenderer
.draw(text
, - textWidth
/ 2 + 1, 12 - 1); // Background 'shadow'
275 this.textRenderer
.setColor(textColor
);
276 this.textRenderer
.draw(text
, - textWidth
/ 2, 12); // Foreground text
277 this.textRenderer
.end3DRendering();
279 // Draw little square around screen point - use annotation's color
280 Color borderColor
= getAttributes().getBorderColor();
281 setDrawColor(dc
, borderColor
);
282 // Draw 3x3 shape from its bottom left corner
283 dc
.getGL().glTranslated(-1, -1, 0);
284 FrameFactory
.drawShape(dc
, FrameFactory
.SHAPE_RECTANGLE
, 3, 3, GL
.GL_LINE_STRIP
, 0);
288 ga
= new SimpleGlobeAnnotation("Mount Rainier\nAlt: 4392m", Position
.fromDegrees(46.8534, -121.7609, 0));
289 layer
.addAnnotation(ga
);
290 ga
= new SimpleGlobeAnnotation("Mount Adams\nAlt: 3742m", Position
.fromDegrees(46.2018, -121.4931, 0));
291 layer
.addAnnotation(ga
);
292 ga
= new SimpleGlobeAnnotation("Mount Saint Helens\nAlt: 4392m", Position
.fromDegrees(46.1991, -122.1882, 0));
293 layer
.addAnnotation(ga
);
295 // Using an anonymous subclass to change annotation text on the fly
296 ga
= new GlobeAnnotation("DRAG ME!", Position
.fromDegrees(42, -118, 0), Font
.decode("Arial-BOLD-18"))
298 public void drawAnnotation(DrawContext dc
, Point screenPoint
, double drawScale
, double drawAlpha
, Position pickPosition
)
300 // if annotation has moved, set its text
301 if(getPosition().getLatitude().degrees
!= 42 || getPosition().getLongitude().degrees
!= -118)
302 setText(String
.format("Lat %7.4f\u00B0\nLon %7.4f\u00B0", getPosition().getLatitude().degrees
, getPosition().getLongitude().degrees
));
305 super.drawAnnotation(dc
, screenPoint
, drawScale
, drawAlpha
, pickPosition
);
308 layer
.addAnnotation(ga
);
310 // Using post drawing code in an anonymous subclass
311 ga
= new GlobeAnnotation("Annotation with extra frames drawn by a render delegate.", Position
.fromDegrees(40, -116, 0), Font
.decode("Serif-BOLD-18"), Color
.DARK_GRAY
)
313 public void drawAnnotation(DrawContext dc
, Point screenPoint
, double drawScale
, double drawAlpha
, Position pickPosition
)
315 // Let normal rendering happen
316 super.drawAnnotation(dc
, screenPoint
, drawScale
, drawAlpha
, pickPosition
);
318 // Draw second light gray frame outside draw rectangle
319 // Refers to scaleFactor, alphaFactor, drawRectangle and freeRectangle which have been
320 // set during drawing.
321 setDrawColor(dc
, new Color(0f
, 0f
, 0f
, .5f
* (float)alphaFactor
));
322 dc
.getGL().glLineWidth((float)(scaleFactor
));
323 // Translate to draw area bottom left corner, 2 pixels outside
324 dc
.getGL().glTranslated(-screenPoint
.x
+ drawRectangle
.x
- 3, -screenPoint
.y
+ drawRectangle
.y
- 3, 0);
325 FrameFactory
.drawShape(dc
, FrameFactory
.SHAPE_RECTANGLE
, drawRectangle
.width
+ 6, drawRectangle
.height
+ 6, GL
.GL_LINE_STRIP
, 4);
327 // Draw another frame in the free space if any
328 if(freeRectangle
.height
> 0)
330 dc
.getGL().glTranslated(+3, +3, 0);
331 FrameFactory
.drawShape(dc
, FrameFactory
.SHAPE_ELLIPSE
, freeRectangle
.width
, freeRectangle
.height
, GL
.GL_TRIANGLE_FAN
, 0);
336 ga
.getAttributes().setTextAlign(MultiLineTextRenderer
.ALIGN_CENTER
);
337 ga
.getAttributes().setBackgroundColor(new Color(1f
, 1f
, 1f
, .7f
));
338 ga
.getAttributes().setBorderColor(Color
.BLACK
);
339 ga
.getAttributes().setSize(new Dimension(160, 200));
340 layer
.addAnnotation(ga
);
343 // Using a ScreenAnnotation
344 ScreenAnnotation sa
= new ScreenAnnotation("Fixed position annotation", new Point(20, 20));
345 sa
.getAttributes().setCornerRadius(0);
346 sa
.getAttributes().setSize(new Dimension(200, 0));
347 sa
.getAttributes().setAdjustWidthToText(Annotation
.SIZE_FIXED
); // use strict dimension width - 200
348 sa
.getAttributes().setDrawOffset(new Point(100, 0)); // screen point is annotation bottom left corner
349 sa
.getAttributes().setHighlightScale(1); // No highlighting either
350 layer
.addAnnotation(sa
);
353 // Add layer to the layer list and update the layer panel
354 insertBeforeCompass(this.getWwd(), layer
);
355 getLayerPanel().update(getWwd());
358 this.getLayerPanel().add(makeControlPanel(), BorderLayout
.SOUTH
);
360 // Test save as kml placemarks
363 // Add a select listener to select or highlight annotations on rollover
364 this.getWwd().addSelectListener(new SelectListener()
366 private BasicDragger dragger
= new BasicDragger(getWwd());
368 public void selected(SelectEvent event
)
370 // Select/unselect on left click on annotations
371 if (event
.getEventAction().equals(SelectEvent
.LEFT_CLICK
))
373 if (event
.hasObjects())
375 if (event
.getTopObject() instanceof Annotation
)
377 // Check for text or url
378 PickedObject po
= event
.getTopPickedObject();
379 if(po
.getValue(AVKey
.TEXT
) != null)
381 System
.out
.println("Text: \"" + po
.getValue(AVKey
.TEXT
) + "\" Hyperlink: " + po
.getValue(AVKey
.URL
));
382 if(AppFrame
.this.currentAnnotation
== event
.getTopObject())
385 // Left click on an annotation - select
386 if(AppFrame
.this.currentAnnotation
!= null)
389 //AppFrame.this.currentAnnotation.getAttributes().setHighlighted(false);
390 AppFrame
.this.currentAnnotation
.getAttributes().setBorderColor(AppFrame
.this.savedBorderColor
);
392 if(AppFrame
.this.currentAnnotation
!= event
.getTopObject())
394 // Select new one if not current one already
395 AppFrame
.this.currentAnnotation
= (Annotation
)event
.getTopObject();
396 //AppFrame.this.currentAnnotation.getAttributes().setHighlighted(true);
397 AppFrame
.this.savedBorderColor
= AppFrame
.this.currentAnnotation
.getAttributes().getBorderColor();
398 AppFrame
.this.savedImage
= AppFrame
.this.currentAnnotation
.getAttributes()
399 .getImageSource() instanceof BufferedImage ?
400 (BufferedImage
)AppFrame
.this.currentAnnotation
.getAttributes().getImageSource() : null;
401 AppFrame
.this.currentAnnotation
.getAttributes().setBorderColor(Color
.YELLOW
);
405 // Clear current annotation
406 AppFrame
.this.currentAnnotation
= null; // switch off
408 // Update control panel
409 AppFrame
.this.updateControlPanel();
412 System
.out
.println("Left click on " + event
.getTopObject());
416 // Highlight on rollover
417 else if (event
.getEventAction().equals(SelectEvent
.ROLLOVER
) && !this.dragger
.isDragging())
419 AppFrame
.this.highlight(event
.getTopObject());
421 // Have drag events drag the selected object.
422 else if (event
.getEventAction().equals(SelectEvent
.DRAG_END
)
423 || event
.getEventAction().equals(SelectEvent
.DRAG
))
425 if (event
.hasObjects())
427 // If selected annotation delegate dragging computations to a dragger.
428 if(event
.getTopObject() == AppFrame
.this.currentAnnotation
)
429 this.dragger
.selected(event
);
432 // We missed any roll-over events while dragging, so highlight any under the cursor now,
433 // or de-highlight the dragged shape if it's no longer under the cursor.
434 if (event
.getEventAction().equals(SelectEvent
.DRAG_END
))
436 PickedObjectList pol
= getWwd().getObjectsAtCurrentPosition();
439 AppFrame
.this.highlight(pol
.getTopObject());
440 AppFrame
.this.getWwd().repaint();
449 private void highlight(Object o
)
451 // Manage highlighting of Annotations.
452 if (this.lastPickedObject
== o
)
453 return; // same thing selected
455 // Turn off highlight if on.
456 if (this.lastPickedObject
!= null) // && this.lastPickedObject != this.currentAnnotation)
458 this.lastPickedObject
.getAttributes().setHighlighted(false);
459 this.lastPickedObject
= null;
462 // Turn on highlight if object selected.
463 if (o
!= null && o
instanceof Annotation
)
465 this.lastPickedObject
= (Annotation
) o
;
466 this.lastPickedObject
.getAttributes().setHighlighted(true);
470 // -- Control panel ---------------------------------------------------------------
472 private JPanel
makeControlPanel()
475 //-- Annotation text area. ----------------------------------------------
476 this.inputTextArea
= new JTextArea();
477 this.inputTextArea
.setFont(new Font("Sans_Serif", Font
.PLAIN
, 16));
478 this.inputTextArea
.setLineWrap(true);
479 this.inputTextArea
.setWrapStyleWord(true);
480 JScrollPane textScrollPane
= new JScrollPane(this.inputTextArea
);
481 textScrollPane
.setVerticalScrollBarPolicy(JScrollPane
.VERTICAL_SCROLLBAR_ALWAYS
);
482 textScrollPane
.setPreferredSize(new Dimension(200, 100));
483 textScrollPane
.setBorder(BorderFactory
.createEmptyBorder(5,5,5,5));
485 //-- Width panel --------------------------------------------------------
486 JPanel sizePanel
= new JPanel(new GridLayout(0, 1, 0, 0));
488 new CompoundBorder(BorderFactory
.createEmptyBorder(4, 4, 4, 4), new TitledBorder("Width and Height")));
489 this.widthSlider
= new JSlider(JSlider
.HORIZONTAL
, 0, 800, 160);
490 this.widthSlider
.setMajorTickSpacing(100);
491 this.widthSlider
.setMinorTickSpacing(10);
492 //this.widthSlider.setPaintTicks(true);
493 this.widthSlider
.setPaintLabels(true);
494 this.widthSlider
.setToolTipText("Preferred annotation width");
495 this.widthSlider
.addChangeListener(new ChangeListener()
497 public void stateChanged(ChangeEvent event
)
499 JSlider s
= (JSlider
)event
.getSource();
500 if (currentAnnotation
!= null)
507 sizePanel
.add(this.widthSlider
);
508 this.heightSlider
= new JSlider(JSlider
.HORIZONTAL
, 0, 800, 0);
509 this.heightSlider
.setMajorTickSpacing(100);
510 this.heightSlider
.setMinorTickSpacing(10);
511 //this.widthSlider.setPaintTicks(true);
512 this.heightSlider
.setPaintLabels(true);
513 this.heightSlider
.setToolTipText("Preferred annotation height, zero = no limit");
514 this.heightSlider
.addChangeListener(new ChangeListener()
516 public void stateChanged(ChangeEvent event
)
518 JSlider s
= (JSlider
)event
.getSource();
519 if (currentAnnotation
!= null)
526 sizePanel
.add(this.heightSlider
);
528 //-- Corner radius panel ----------------------------------------------------
529 JPanel cornerRadiusPanel
= new JPanel();
530 cornerRadiusPanel
.setLayout(new BoxLayout(cornerRadiusPanel
, BoxLayout
.X_AXIS
));
531 cornerRadiusPanel
.setBorder(BorderFactory
.createEmptyBorder(4, 4, 4, 4));
532 cornerRadiusPanel
.add(new JLabel("Corner radius:"));
533 cornerRadiusPanel
.add(Box
.createRigidArea(new Dimension(10, 0)));
534 this.cornerRadiusSlider
= new JSlider(JSlider
.HORIZONTAL
, 0, 50, 10);
535 this.cornerRadiusSlider
.setMajorTickSpacing(10);
536 this.cornerRadiusSlider
.setMinorTickSpacing(1);
537 //this.cornerRadiusSlider.setPaintTicks(true);
538 this.cornerRadiusSlider
.setPaintLabels(true);
539 this.cornerRadiusSlider
.setToolTipText("Rounded corners radius");
540 this.cornerRadiusSlider
.addChangeListener(new ChangeListener()
542 public void stateChanged(ChangeEvent event
)
544 if (currentAnnotation
!= null)
551 cornerRadiusPanel
.add(this.cornerRadiusSlider
);
553 //-- Insets panel ----------------------------------------------------
554 JPanel insetsPanel
= new JPanel();
555 insetsPanel
.setLayout(new BoxLayout(insetsPanel
, BoxLayout
.X_AXIS
));
556 insetsPanel
.setBorder(BorderFactory
.createEmptyBorder(4, 4, 4, 4));
557 insetsPanel
.add(new JLabel("Insets:"));
558 insetsPanel
.add(Box
.createRigidArea(new Dimension(10, 0)));
559 this.insetsTop
= new JSpinner();
560 this.insetsTop
.addChangeListener(new ChangeListener()
562 public void stateChanged(ChangeEvent event
)
564 if (currentAnnotation
!= null)
571 this.insetsRight
= new JSpinner();
572 this.insetsRight
.addChangeListener(new ChangeListener()
574 public void stateChanged(ChangeEvent event
)
576 if (currentAnnotation
!= null)
583 this.insetsBottom
= new JSpinner();
584 this.insetsBottom
.addChangeListener(new ChangeListener()
586 public void stateChanged(ChangeEvent event
)
588 if (currentAnnotation
!= null)
595 this.insetsLeft
= new JSpinner();
596 this.insetsLeft
.addChangeListener(new ChangeListener()
598 public void stateChanged(ChangeEvent event
)
600 if (currentAnnotation
!= null)
607 insetsPanel
.add(this.insetsTop
);
608 insetsPanel
.add(Box
.createRigidArea(new Dimension(10, 0)));
609 insetsPanel
.add(this.insetsRight
);
610 insetsPanel
.add(Box
.createRigidArea(new Dimension(10, 0)));
611 insetsPanel
.add(this.insetsBottom
);
612 insetsPanel
.add(Box
.createRigidArea(new Dimension(10, 0)));
613 insetsPanel
.add(this.insetsLeft
);
616 //-- Border width panel ----------------------------------------------------
617 JPanel borderWidthPanel
= new JPanel();
618 borderWidthPanel
.setLayout(new BoxLayout(borderWidthPanel
, BoxLayout
.X_AXIS
));
619 borderWidthPanel
.setBorder(BorderFactory
.createEmptyBorder(4, 4, 4, 4));
620 borderWidthPanel
.add(new JLabel("Border width:"));
621 borderWidthPanel
.add(Box
.createRigidArea(new Dimension(10, 0)));
622 this.borderWidthSlider
= new JSlider(JSlider
.HORIZONTAL
, 0, 50, 10);
623 this.borderWidthSlider
.setMajorTickSpacing(10);
624 this.borderWidthSlider
.setMinorTickSpacing(1);
625 //this.borderWidthSlider.setPaintTicks(true);
626 this.borderWidthSlider
.setPaintLabels(true);
627 this.borderWidthSlider
.setToolTipText("Border width 1/10th");
628 this.borderWidthSlider
.addChangeListener(new ChangeListener()
630 public void stateChanged(ChangeEvent event
)
632 if (currentAnnotation
!= null)
639 borderWidthPanel
.add(this.borderWidthSlider
);
641 //-- Stipple factor panel ----------------------------------------------------
642 JPanel stippleFactorPanel
= new JPanel();
643 stippleFactorPanel
.setLayout(new BoxLayout(stippleFactorPanel
, BoxLayout
.X_AXIS
));
644 stippleFactorPanel
.setBorder(BorderFactory
.createEmptyBorder(4, 4, 4, 4));
645 stippleFactorPanel
.add(new JLabel("Stipple factor:"));
646 stippleFactorPanel
.add(Box
.createRigidArea(new Dimension(10, 0)));
647 this.stippleFactorSlider
= new JSlider(JSlider
.HORIZONTAL
, 0, 10, 0);
648 this.stippleFactorSlider
.setMajorTickSpacing(1);
649 this.stippleFactorSlider
.setPaintLabels(true);
650 this.stippleFactorSlider
.setToolTipText("Border line pattern repeat factor");
651 this.stippleFactorSlider
.addChangeListener(new ChangeListener()
653 public void stateChanged(ChangeEvent event
)
655 if (currentAnnotation
!= null)
662 stippleFactorPanel
.add(this.stippleFactorSlider
);
665 // -- Border antialias panel -----------------------------------------------
666 final JPanel antialiasPanel
= new JPanel(new GridLayout(0, 2, 5, 5));
667 antialiasPanel
.setBorder(BorderFactory
.createEmptyBorder(4, 4, 4, 4));
669 antialiasPanel
.add(new JLabel("Antialias:"));
670 this.cbAntialias
= new JComboBox(new String
[] {"Dont care", "Fastest", "Nicest"});
671 this.cbAntialias
.addActionListener(new ActionListener()
673 public void actionPerformed(ActionEvent actionEvent
)
675 if(currentAnnotation
!= null)
681 antialiasPanel
.add(this.cbAntialias
);
683 //-- Scale and opacity panel ----------------------------------------------------
684 JPanel scalePanel
= new JPanel(new GridLayout(0, 1, 0, 0));
685 scalePanel
.setBorder(
686 new CompoundBorder(BorderFactory
.createEmptyBorder(4, 4, 4, 4), new TitledBorder("Scale and Opacity")));
687 this.scaleSlider
= new JSlider(JSlider
.HORIZONTAL
, 0, 30, 10);
688 this.scaleSlider
.setMajorTickSpacing(10);
689 this.scaleSlider
.setMinorTickSpacing(1);
690 //this.scaleSlider.setPaintTicks(true);
691 this.scaleSlider
.setPaintLabels(true);
692 this.scaleSlider
.setToolTipText("Annotation scaling");
693 this.scaleSlider
.addChangeListener(new ChangeListener()
695 public void stateChanged(ChangeEvent event
)
697 JSlider s
= (JSlider
)event
.getSource();
698 if (currentAnnotation
!= null)
705 scalePanel
.add(this.scaleSlider
);
706 this.opacitySlider
= new JSlider(JSlider
.HORIZONTAL
, 0, 10, 10);
707 this.opacitySlider
.setMajorTickSpacing(1);
708 //this.opacitySlider.setMinorTickSpacing(1);
709 //this.opacitySlider.setPaintTicks(true);
710 this.opacitySlider
.setPaintLabels(true);
711 this.opacitySlider
.setToolTipText("Annotation opacity");
712 this.opacitySlider
.addChangeListener(new ChangeListener()
714 public void stateChanged(ChangeEvent event
)
716 JSlider s
= (JSlider
)event
.getSource();
717 if (currentAnnotation
!= null)
724 scalePanel
.add(this.opacitySlider
);
726 // -- Font --------------------------------------------------------------
727 JPanel fontPanel
= new JPanel();
728 fontPanel
.setLayout(new BoxLayout(fontPanel
, BoxLayout
.X_AXIS
));
729 fontPanel
.setBorder(BorderFactory
.createEmptyBorder(4, 4, 4, 4));
731 fontPanel
.add(new JLabel("Font"));
732 fontPanel
.add(Box
.createRigidArea(new Dimension(10, 0)));
733 this.cbFontName
= new JComboBox(new String
[] {"Arial", "SansSerif", "Serif", "Courier", "Times", "Helvetica", "Trebuchet", "Tahoma"});
734 this.cbFontName
.addActionListener(new ActionListener()
736 public void actionPerformed(ActionEvent actionEvent
)
738 if(currentAnnotation
!= null)
744 fontPanel
.add(this.cbFontName
);
745 fontPanel
.add(Box
.createRigidArea(new Dimension(10, 0)));
746 this.cbFontStyle
= new JComboBox(new String
[] {"Plain", "Bold", "Italic", "BoldItalic"});
747 this.cbFontStyle
.addActionListener(new ActionListener()
749 public void actionPerformed(ActionEvent actionEvent
)
751 if(currentAnnotation
!= null)
757 fontPanel
.add(this.cbFontStyle
);
758 fontPanel
.add(Box
.createRigidArea(new Dimension(10, 0)));
759 this.cbFontSize
= new JComboBox(new String
[] {"10", "12", "14", "16", "18", "20", "24", "28", "34", "48", "64"});
760 this.cbFontSize
.addActionListener(new ActionListener()
762 public void actionPerformed(ActionEvent actionEvent
)
764 if(currentAnnotation
!= null)
770 fontPanel
.add(this.cbFontSize
);
771 //fontPanel.add(Box.createRigidArea(new Dimension(10, 0)));
773 // -- Text align panel -------------------------------------------------------
774 final JPanel alignPanel
= new JPanel(new GridLayout(0, 3, 5, 5));
775 alignPanel
.setBorder(BorderFactory
.createEmptyBorder(4, 4, 4, 4));
776 alignPanel
.add(new JLabel("Align & Effect:"));
777 this.cbTextAlign
= new JComboBox(new String
[] {"Left", "Center", "Right"});
778 this.cbTextAlign
.addActionListener(new ActionListener()
780 public void actionPerformed(ActionEvent actionEvent
)
782 if(currentAnnotation
!= null)
788 alignPanel
.add(this.cbTextAlign
);
789 this.cbTextEffect
= new JComboBox(new String
[] {"None", "Shadow", "Outline"});
790 this.cbTextEffect
.addActionListener(new ActionListener()
792 public void actionPerformed(ActionEvent actionEvent
)
794 if(currentAnnotation
!= null)
800 alignPanel
.add(this.cbTextEffect
);
802 // -- Adjust width panel -------------------------------------------------------
803 final JPanel adjustWidthPanel
= new JPanel(new GridLayout(0, 1, 5, 5));
804 adjustWidthPanel
.setBorder(BorderFactory
.createEmptyBorder(4, 4, 4, 4));
805 this.cbAdjustWidth
= new JCheckBox("Adjust width to text");
806 this.cbAdjustWidth
.addActionListener(new ActionListener()
808 public void actionPerformed(ActionEvent actionEvent
)
810 if(currentAnnotation
!= null)
816 this.cbAdjustWidth
.setSelected(true);
817 adjustWidthPanel
.add(this.cbAdjustWidth
);
819 // -- Shape and leader panel -----------------------------------------------
820 final JPanel shapePanel
= new JPanel(new GridLayout(0, 2, 5, 5));
821 shapePanel
.setBorder(BorderFactory
.createEmptyBorder(4, 4, 4, 4));
823 shapePanel
.add(new JLabel("Shape:"));
824 this.cbShape
= new JComboBox(new String
[] {"Rectangle", "Ellipse", "None"});
825 this.cbShape
.addActionListener(new ActionListener()
827 public void actionPerformed(ActionEvent actionEvent
)
829 if(currentAnnotation
!= null)
835 shapePanel
.add(this.cbShape
);
836 shapePanel
.add(new JLabel("Leader:"));
837 this.cbLeader
= new JComboBox(new String
[] {"Triangle", "None"});
838 this.cbLeader
.addActionListener(new ActionListener()
840 public void actionPerformed(ActionEvent actionEvent
)
842 if(currentAnnotation
!= null)
848 shapePanel
.add(this.cbLeader
);
851 // -- Image select panel -----------------------------------------------
852 final JPanel imagePanel
= new JPanel(new GridLayout(0, 2, 5, 5));
853 imagePanel
.setBorder(BorderFactory
.createEmptyBorder(4, 4, 4, 4));
855 imagePanel
.add(new JLabel("Image:"));
856 this.cbImage
= new JComboBox(new String
[] {"None", "Earth", "NASA", "WWJ Splash", "Custom"});
857 this.cbImage
.addActionListener(new ActionListener()
859 public void actionPerformed(ActionEvent actionEvent
)
861 if(currentAnnotation
!= null)
867 imagePanel
.add(this.cbImage
);
868 imagePanel
.add(new JLabel("Repeat:"));
869 this.cbImageRepeat
= new JComboBox(new String
[] {"None", "Repeat-X", "Repeat-Y", "Repeat-XY"});
870 this.cbImageRepeat
.addActionListener(new ActionListener()
872 public void actionPerformed(ActionEvent actionEvent
)
874 if(currentAnnotation
!= null)
880 imagePanel
.add(this.cbImageRepeat
);
883 //-- Image scale and opacity panel ----------------------------------------------
884 JPanel imageScalePanel
= new JPanel(new GridLayout(0, 1, 0, 0));
885 imageScalePanel
.setBorder(
886 new CompoundBorder(BorderFactory
.createEmptyBorder(4, 4, 4, 4), new TitledBorder("Scale and Opacity")));
887 this.imageScaleSlider
= new JSlider(JSlider
.HORIZONTAL
, 0, 30, 10);
888 this.imageScaleSlider
.setMajorTickSpacing(10);
889 this.imageScaleSlider
.setMinorTickSpacing(1);
890 this.imageScaleSlider
.setPaintLabels(true);
891 this.imageScaleSlider
.setToolTipText("Background image scaling");
892 this.imageScaleSlider
.addChangeListener(new ChangeListener()
894 public void stateChanged(ChangeEvent event
)
896 JSlider s
= (JSlider
)event
.getSource();
897 if (currentAnnotation
!= null)
904 imageScalePanel
.add(this.imageScaleSlider
);
905 this.imageOpacitySlider
= new JSlider(JSlider
.HORIZONTAL
, 0, 10, 10);
906 this.imageOpacitySlider
.setMajorTickSpacing(1);
907 this.imageOpacitySlider
.setPaintLabels(true);
908 this.imageOpacitySlider
.setToolTipText("Background image opacity");
909 this.imageOpacitySlider
.addChangeListener(new ChangeListener()
911 public void stateChanged(ChangeEvent event
)
913 JSlider s
= (JSlider
)event
.getSource();
914 if (currentAnnotation
!= null)
921 imageScalePanel
.add(this.imageOpacitySlider
);
923 //-- Image offset panel ----------------------------------------------
924 JPanel imageOffsetPanel
= new JPanel(new GridLayout(0, 1, 0, 0));
925 imageOffsetPanel
.setBorder(
926 new CompoundBorder(BorderFactory
.createEmptyBorder(4, 4, 4, 4), new TitledBorder("Offset")));
927 this.imageOffsetXSlider
= new JSlider(JSlider
.HORIZONTAL
, -200, 200, 0);
928 this.imageOffsetXSlider
.setMajorTickSpacing(100);
929 this.imageOffsetXSlider
.setMinorTickSpacing(1);
930 this.imageOffsetXSlider
.setPaintLabels(true);
931 this.imageOffsetXSlider
.setToolTipText("Background image horizontal offset (X)");
932 this.imageOffsetXSlider
.addChangeListener(new ChangeListener()
934 public void stateChanged(ChangeEvent event
)
936 JSlider s
= (JSlider
)event
.getSource();
937 if (currentAnnotation
!= null)
944 imageOffsetPanel
.add(this.imageOffsetXSlider
);
945 this.imageOffsetYSlider
= new JSlider(JSlider
.HORIZONTAL
, -200, 200, 0);
946 this.imageOffsetYSlider
.setMajorTickSpacing(100);
947 this.imageOffsetXSlider
.setMinorTickSpacing(1);
948 this.imageOffsetYSlider
.setPaintLabels(true);
949 this.imageOffsetYSlider
.setToolTipText("Background image vertical offset (Y)");
950 this.imageOffsetYSlider
.addChangeListener(new ChangeListener()
952 public void stateChanged(ChangeEvent event
)
954 JSlider s
= (JSlider
)event
.getSource();
955 if (currentAnnotation
!= null)
962 imageOffsetPanel
.add(this.imageOffsetYSlider
);
964 //-- Annotation offset panel ----------------------------------------------
965 JPanel offsetPanel
= new JPanel(new GridLayout(0, 1, 0, 0));
966 offsetPanel
.setBorder(
967 new CompoundBorder(BorderFactory
.createEmptyBorder(4, 4, 4, 4), new TitledBorder("Draw offset")));
968 this.offsetXSlider
= new JSlider(JSlider
.HORIZONTAL
, -200, 200, 0);
969 this.offsetXSlider
.setMajorTickSpacing(100);
970 this.offsetXSlider
.setMinorTickSpacing(1);
971 this.offsetXSlider
.setPaintLabels(true);
972 this.offsetXSlider
.setToolTipText("Annotation horizontal offset (X)");
973 this.offsetXSlider
.addChangeListener(new ChangeListener()
975 public void stateChanged(ChangeEvent event
)
977 JSlider s
= (JSlider
)event
.getSource();
978 if (currentAnnotation
!= null)
985 offsetPanel
.add(this.offsetXSlider
);
986 this.offsetYSlider
= new JSlider(JSlider
.HORIZONTAL
, 0, 200, 0);
987 this.offsetYSlider
.setMajorTickSpacing(100);
988 this.offsetYSlider
.setMinorTickSpacing(1);
989 this.offsetYSlider
.setPaintLabels(true);
990 this.offsetYSlider
.setToolTipText("Annotation vertical offset (Y)");
991 this.offsetYSlider
.addChangeListener(new ChangeListener()
993 public void stateChanged(ChangeEvent event
)
995 JSlider s
= (JSlider
)event
.getSource();
996 if (currentAnnotation
!= null)
1003 offsetPanel
.add(this.offsetYSlider
);
1005 //-- Annotation distance scalling panel ---------------------------------------
1006 JPanel distancePanel
= new JPanel(new GridLayout(0, 1, 0, 0));
1007 distancePanel
.setBorder(
1008 new CompoundBorder(BorderFactory
.createEmptyBorder(4, 4, 4, 4), new TitledBorder("Distance min/max scale and opacity")));
1009 this.distanceMinScaleSlider
= new JSlider(JSlider
.HORIZONTAL
, 0, 30, 10);
1010 this.distanceMinScaleSlider
.setMajorTickSpacing(10);
1011 this.distanceMinScaleSlider
.setMinorTickSpacing(1);
1012 this.distanceMinScaleSlider
.setPaintLabels(true);
1013 this.distanceMinScaleSlider
.setToolTipText("Minimum scale 1/10th");
1014 this.distanceMinScaleSlider
.addChangeListener(new ChangeListener()
1016 public void stateChanged(ChangeEvent event
)
1018 JSlider s
= (JSlider
)event
.getSource();
1019 if (currentAnnotation
!= null)
1026 distancePanel
.add(this.distanceMinScaleSlider
);
1027 this.distanceMaxScaleSlider
= new JSlider(JSlider
.HORIZONTAL
, 0, 30, 10);
1028 this.distanceMaxScaleSlider
.setMajorTickSpacing(10);
1029 this.distanceMaxScaleSlider
.setMinorTickSpacing(1);
1030 this.distanceMaxScaleSlider
.setPaintLabels(true);
1031 this.distanceMaxScaleSlider
.setToolTipText("Maximum scale 1/10th");
1032 this.distanceMaxScaleSlider
.addChangeListener(new ChangeListener()
1034 public void stateChanged(ChangeEvent event
)
1036 JSlider s
= (JSlider
)event
.getSource();
1037 if (currentAnnotation
!= null)
1044 distancePanel
.add(this.distanceMaxScaleSlider
);
1045 this.distanceMinOpacitySlider
= new JSlider(JSlider
.HORIZONTAL
, 0, 10, 10);
1046 this.distanceMinOpacitySlider
.setMajorTickSpacing(1);
1047 this.distanceMinOpacitySlider
.setPaintLabels(true);
1048 this.distanceMinOpacitySlider
.setToolTipText("Minimum opacity");
1049 this.distanceMinOpacitySlider
.addChangeListener(new ChangeListener()
1051 public void stateChanged(ChangeEvent event
)
1053 JSlider s
= (JSlider
)event
.getSource();
1054 if (currentAnnotation
!= null)
1061 distancePanel
.add(this.distanceMinOpacitySlider
);
1063 //-- Highlight scale panel ---------------------------------------
1064 JPanel highlightPanel
= new JPanel(new GridLayout(0, 1, 0, 0));
1065 highlightPanel
.setBorder(
1066 new CompoundBorder(BorderFactory
.createEmptyBorder(4, 4, 4, 4), new TitledBorder("Highlight scale")));
1067 this.highlightScaleSlider
= new JSlider(JSlider
.HORIZONTAL
, 0, 30, 10);
1068 this.highlightScaleSlider
.setMajorTickSpacing(10);
1069 this.highlightScaleSlider
.setMinorTickSpacing(1);
1070 this.highlightScaleSlider
.setPaintLabels(true);
1071 this.highlightScaleSlider
.setToolTipText("Highlight scale 1/10th");
1072 this.highlightScaleSlider
.addChangeListener(new ChangeListener()
1074 public void stateChanged(ChangeEvent event
)
1076 JSlider s
= (JSlider
)event
.getSource();
1077 if (currentAnnotation
!= null)
1084 highlightPanel
.add(this.highlightScaleSlider
);
1086 // -- Color panel -------------------------------------------------------
1087 final JPanel colorPanel
= new JPanel(new GridLayout(0, 3, 5, 5));
1088 colorPanel
.setBorder(BorderFactory
.createEmptyBorder(4, 4, 4, 4));
1090 colorPanel
.add(new JLabel("Text color:"));
1091 this.btTextColor
= new JButton("");
1092 this.btTextColor
.addActionListener(new ActionListener() {
1093 public void actionPerformed(ActionEvent event
)
1095 Color c
= JColorChooser
.showDialog(colorPanel
,
1096 "Choose a color...", ((JButton
)event
.getSource()).getBackground());
1099 ((JButton
)event
.getSource()).setBackground(c
);
1100 if(currentAnnotation
!= null)
1105 colorPanel
.add(this.btTextColor
);
1106 this.cbTextColorAlpha
= new JComboBox(new String
[] {"10", "9", "8", "7", "6", "5", "4", "3", "2", "1", "0"});
1107 this.cbTextColorAlpha
.addActionListener(new ActionListener()
1109 public void actionPerformed(ActionEvent actionEvent
)
1111 if(currentAnnotation
!= null)
1117 colorPanel
.add(this.cbTextColorAlpha
);
1119 colorPanel
.add(new JLabel("Back color:"));
1120 this.btBackColor
= new JButton("");
1121 this.btBackColor
.addActionListener(new ActionListener() {
1122 public void actionPerformed(ActionEvent event
)
1124 Color c
= JColorChooser
.showDialog(colorPanel
,
1125 "Choose a color...", ((JButton
)event
.getSource()).getBackground());
1128 ((JButton
)event
.getSource()).setBackground(c
);
1129 if(currentAnnotation
!= null)
1134 colorPanel
.add(this.btBackColor
);
1135 this.cbBackColorAlpha
= new JComboBox(new String
[] {"10", "9", "8", "7", "6", "5", "4", "3", "2", "1", "0"});
1136 this.cbBackColorAlpha
.addActionListener(new ActionListener()
1138 public void actionPerformed(ActionEvent actionEvent
)
1140 if(currentAnnotation
!= null)
1146 colorPanel
.add(this.cbBackColorAlpha
);
1148 colorPanel
.add(new JLabel("Border color:"));
1149 this.btBorderColor
= new JButton("");
1150 this.btBorderColor
.addActionListener(new ActionListener() {
1151 public void actionPerformed(ActionEvent event
)
1153 Color c
= JColorChooser
.showDialog(colorPanel
,
1154 "Choose a color...", ((JButton
)event
.getSource()).getBackground());
1157 ((JButton
)event
.getSource()).setBackground(c
);
1158 if(currentAnnotation
!= null)
1163 colorPanel
.add(this.btBorderColor
);
1164 this.cbBorderColorAlpha
= new JComboBox(new String
[] {"10", "9", "8", "7", "6", "5", "4", "3", "2", "1", "0"});
1165 this.cbBorderColorAlpha
.addActionListener(new ActionListener()
1167 public void actionPerformed(ActionEvent actionEvent
)
1169 if(currentAnnotation
!= null)
1175 colorPanel
.add(this.cbBorderColorAlpha
);
1177 // -- Button panel ------------------------------------------------------
1178 JPanel buttonPanel
= new JPanel();
1179 buttonPanel
.setLayout(new BoxLayout(buttonPanel
, BoxLayout
.X_AXIS
));
1180 buttonPanel
.setBorder(BorderFactory
.createEmptyBorder(14, 4, 4, 4));
1182 // Apply changes button
1183 this.btApply
= new JButton("Apply");
1184 this.btApply
.setEnabled(false);
1185 this.btApply
.addActionListener(new ActionListener() {
1186 public void actionPerformed(ActionEvent event
)
1188 if(currentAnnotation
!= null)
1195 // Add annotation button
1196 this.btAdd
= new JButton("Add new");
1197 this.btAdd
.addActionListener(new ActionListener() {
1198 public void actionPerformed(ActionEvent event
)
1200 Position lookAtPos
= computeGroundPosition(getWwd());
1201 if(lookAtPos
!= null && inputTextArea
.getText().length() > 0)
1203 Annotation a
= currentAnnotation
;
1204 currentAnnotation
= new GlobeAnnotation(inputTextArea
.getText(), lookAtPos
);
1206 layer
.addAnnotation(currentAnnotation
);
1207 currentAnnotation
= a
;
1214 this.btRemove
= new JButton("Remove");
1215 this.btRemove
.setEnabled(false);
1216 this.btRemove
.addActionListener(new ActionListener() {
1217 public void actionPerformed(ActionEvent event
)
1219 if(currentAnnotation
!= null)
1221 layer
.removeAnnotation(currentAnnotation
);
1222 // Clear current annotation
1223 currentAnnotation
= null;
1224 inputTextArea
.setText("");
1225 widthSlider
.setEnabled(false);
1226 btApply
.setEnabled(false);
1227 btRemove
.setEnabled(false);
1233 buttonPanel
.add(this.btAdd
);
1234 buttonPanel
.add(Box
.createRigidArea(new Dimension(10, 0)));
1235 buttonPanel
.add(this.btApply
);
1236 buttonPanel
.add(Box
.createRigidArea(new Dimension(10, 0)));
1237 buttonPanel
.add(this.btRemove
);
1238 //-- end button panel
1240 //-- Tabbed pane assembly ---------------
1241 JTabbedPane tabbedPane
= new JTabbedPane();
1244 JPanel controlPanel
= new JPanel();
1245 controlPanel
.setLayout(new BoxLayout(controlPanel
, BoxLayout
.Y_AXIS
));
1246 controlPanel
.setBorder(BorderFactory
.createEmptyBorder(9, 9, 9, 9));
1247 controlPanel
.setToolTipText("Text and Colors");
1248 controlPanel
.add(textScrollPane
);
1249 controlPanel
.add(fontPanel
);
1250 controlPanel
.add(alignPanel
);
1251 controlPanel
.add(colorPanel
);
1252 tabbedPane
.add(controlPanel
);
1253 tabbedPane
.setTitleAt(0, "Text");
1255 // Size, scale and opacity
1256 controlPanel
= new JPanel();
1257 controlPanel
.setLayout(new BoxLayout(controlPanel
, BoxLayout
.Y_AXIS
));
1258 controlPanel
.setBorder(BorderFactory
.createEmptyBorder(9, 9, 9, 9));
1259 controlPanel
.setToolTipText("Size, scale and opacity");
1260 controlPanel
.add(adjustWidthPanel
);
1261 controlPanel
.add(sizePanel
);
1262 controlPanel
.add(scalePanel
);
1263 tabbedPane
.add(controlPanel
);
1264 tabbedPane
.setTitleAt(1, "Size");
1266 // Shape, insets, corner radius
1267 controlPanel
= new JPanel();
1268 controlPanel
.setLayout(new BoxLayout(controlPanel
, BoxLayout
.Y_AXIS
));
1269 controlPanel
.setBorder(BorderFactory
.createEmptyBorder(9, 9, 9, 9));
1270 controlPanel
.setToolTipText("Shape, insets, corner radius, border width and patterns");
1271 controlPanel
.add(shapePanel
);
1272 controlPanel
.add(cornerRadiusPanel
);
1273 controlPanel
.add(insetsPanel
);
1274 controlPanel
.add(borderWidthPanel
);
1275 controlPanel
.add(stippleFactorPanel
);
1276 controlPanel
.add(antialiasPanel
);
1277 tabbedPane
.add(controlPanel
);
1278 tabbedPane
.setTitleAt(2, "Shape");
1281 controlPanel
= new JPanel();
1282 controlPanel
.setLayout(new BoxLayout(controlPanel
, BoxLayout
.Y_AXIS
));
1283 controlPanel
.setBorder(BorderFactory
.createEmptyBorder(9, 9, 9, 9));
1284 controlPanel
.setToolTipText("Background image texture controls");
1285 controlPanel
.add(imagePanel
);
1286 controlPanel
.add(imageScalePanel
);
1287 controlPanel
.add(imageOffsetPanel
);
1288 tabbedPane
.add(controlPanel
);
1289 tabbedPane
.setTitleAt(3, "Image");
1292 controlPanel
= new JPanel();
1293 controlPanel
.setLayout(new BoxLayout(controlPanel
, BoxLayout
.Y_AXIS
));
1294 controlPanel
.setBorder(BorderFactory
.createEmptyBorder(9, 9, 9, 9));
1295 controlPanel
.setToolTipText("Offset, distance scaling and fading, highlight");
1296 controlPanel
.add(offsetPanel
);
1297 controlPanel
.add(distancePanel
);
1298 controlPanel
.add(highlightPanel
);
1299 tabbedPane
.add(controlPanel
);
1300 tabbedPane
.setTitleAt(4, "Misc.");
1302 //-- Combine tabbed panes with buttons at the bottom
1303 controlPanel
= new JPanel();
1304 controlPanel
.setBorder(
1305 new CompoundBorder(BorderFactory
.createEmptyBorder(9, 9, 9, 9), new TitledBorder("Annotation")));
1306 controlPanel
.setToolTipText("Current or new annotation");
1307 controlPanel
.setLayout(new BorderLayout());
1308 controlPanel
.add(tabbedPane
, BorderLayout
.NORTH
);
1309 controlPanel
.add(buttonPanel
, BorderLayout
.SOUTH
);
1311 return controlPanel
;
1314 private void updateControlPanel()
1316 if(this.currentAnnotation
!= null)
1318 this.suspendUpdate
= true;
1319 this.inputTextArea
.setText(this.currentAnnotation
.getText());
1320 this.widthSlider
.setValue(this.currentAnnotation
.getAttributes().getSize().width
);
1321 this.heightSlider
.setValue(this.currentAnnotation
.getAttributes().getSize().height
);
1322 this.scaleSlider
.setValue((int)(this.currentAnnotation
.getAttributes().getScale() * 10));
1323 this.opacitySlider
.setValue((int)(this.currentAnnotation
.getAttributes().getOpacity() * 10));
1324 this.cbAdjustWidth
.setSelected(this.currentAnnotation
.getAttributes()
1325 .getAdjustWidthToText().compareTo(Annotation
.SIZE_FIT_TEXT
) == 0);
1327 Font font
= currentAnnotation
.getAttributes().getFont();
1330 this.cbFontName
.setSelectedItem(font
.getName());
1331 this.cbFontStyle
.setSelectedIndex(font
.getStyle());
1332 this.cbFontSize
.setSelectedItem(String
.valueOf(font
.getSize()));
1336 this.cbFontName
.setSelectedItem("Arial");
1337 this.cbFontStyle
.setSelectedItem("Plain");
1338 this.cbFontSize
.setSelectedItem("12");
1340 Color color
= currentAnnotation
.getAttributes().getTextColor();
1341 String colorAlpha
= color
!= null ? String
.valueOf((int)Math
.round((float)color
.getAlpha() / 25.5f
)) : "8";
1342 this.btTextColor
.setBackground(color
!= null ?
new Color(color
.getRed(), color
.getGreen(), color
.getBlue()) : Color
.WHITE
);
1343 this.cbTextColorAlpha
.setSelectedItem(colorAlpha
);
1345 color
= currentAnnotation
.getAttributes().getBackgroundColor();
1346 colorAlpha
= color
!= null ? String
.valueOf((int)Math
.round((float)color
.getAlpha() / 25.5f
)) : "4";
1347 this.btBackColor
.setBackground(color
!= null ?
new Color(color
.getRed(), color
.getGreen(), color
.getBlue()) : Color
.BLACK
);
1348 this.cbBackColorAlpha
.setSelectedItem(colorAlpha
);
1350 //color = currentAnnotation.getBorderColor();
1351 color
= this.savedBorderColor
;
1352 colorAlpha
= color
!= null ? String
.valueOf((int)Math
.round((float)color
.getAlpha() / 25.5f
)) : "7";
1353 this.btBorderColor
.setBackground(color
!= null ?
new Color(color
.getRed(), color
.getGreen(), color
.getBlue()) : Color
.WHITE
);
1354 this.cbBorderColorAlpha
.setSelectedItem(colorAlpha
);
1356 switch (currentAnnotation
.getAttributes().getTextAlign())
1358 case MultiLineTextRenderer
.ALIGN_LEFT
: {cbTextAlign
.setSelectedIndex(0); break;}
1359 case MultiLineTextRenderer
.ALIGN_CENTER
: {cbTextAlign
.setSelectedIndex(1); break;}
1360 case MultiLineTextRenderer
.ALIGN_RIGHT
: {cbTextAlign
.setSelectedIndex(2); break;}
1363 if (currentAnnotation
.getAttributes().getEffect().compareTo(MultiLineTextRenderer
.EFFECT_NONE
) == 0)
1364 cbTextEffect
.setSelectedIndex(0);
1365 else if (currentAnnotation
.getAttributes().getEffect().compareTo(MultiLineTextRenderer
.EFFECT_SHADOW
) == 0)
1366 cbTextEffect
.setSelectedIndex(1);
1367 else if (currentAnnotation
.getAttributes().getEffect().compareTo(MultiLineTextRenderer
.EFFECT_OUTLINE
) == 0)
1368 cbTextEffect
.setSelectedIndex(2);
1370 if (currentAnnotation
.getAttributes().getFrameShape().compareTo(FrameFactory
.SHAPE_RECTANGLE
) == 0)
1371 cbShape
.setSelectedIndex(0);
1372 else if (currentAnnotation
.getAttributes().getFrameShape().compareTo(FrameFactory
.SHAPE_ELLIPSE
) == 0)
1373 cbShape
.setSelectedIndex(1);
1375 cbShape
.setSelectedIndex(2);
1377 if (currentAnnotation
.getAttributes().getLeader().compareTo(FrameFactory
.LEADER_TRIANGLE
) == 0)
1378 cbLeader
.setSelectedIndex(0);
1380 cbLeader
.setSelectedIndex(1);
1382 this.cornerRadiusSlider
.setValue(currentAnnotation
.getAttributes().getCornerRadius());
1384 Insets insets
= currentAnnotation
.getAttributes().getInsets();
1385 this.insetsTop
.setValue(insets
.top
);
1386 this.insetsRight
.setValue(insets
.right
);
1387 this.insetsBottom
.setValue(insets
.bottom
);
1388 this.insetsLeft
.setValue(insets
.left
);
1390 this.borderWidthSlider
.setValue((int)(currentAnnotation
.getAttributes().getBorderWidth() * 10));
1391 this.stippleFactorSlider
.setValue((int)(currentAnnotation
.getAttributes().getBorderStippleFactor()));
1393 switch (currentAnnotation
.getAttributes().getAntiAliasHint())
1395 case Annotation
.ANTIALIAS_DONT_CARE
: this.cbAntialias
.setSelectedIndex(0); break;
1396 case Annotation
.ANTIALIAS_FASTEST
: this.cbAntialias
.setSelectedIndex(1); break;
1397 case Annotation
.ANTIALIAS_NICEST
: this.cbAntialias
.setSelectedIndex(2); break;
1400 if (currentAnnotation
.getAttributes().getImageSource() != null)
1402 if (currentAnnotation
.getAttributes().getImageSource() instanceof String
)
1404 String image
= (String
)currentAnnotation
.getAttributes().getImageSource();
1405 if(image
.compareTo(IMAGE_EARTH
) == 0) this.cbImage
.setSelectedIndex(1);
1406 else if(image
.compareTo(IMAGE_NASA
) == 0) this.cbImage
.setSelectedIndex(2);
1407 else if(image
.compareTo(IMAGE_WWJ_SPLASH
) == 0) this.cbImage
.setSelectedIndex(3);
1408 else this.cbImage
.setSelectedIndex(4); // Custom
1411 this.cbImage
.setSelectedIndex(4); // Custom
1414 this.cbImage
.setSelectedIndex(0); // None
1416 String imageRepeat
= currentAnnotation
.getAttributes().getImageRepeat();
1417 if (imageRepeat
.compareTo(Annotation
.IMAGE_REPEAT_NONE
) == 0) this.cbImageRepeat
.setSelectedIndex(0);
1418 else if (imageRepeat
.compareTo(Annotation
.IMAGE_REPEAT_X
) == 0) this.cbImageRepeat
.setSelectedIndex(1);
1419 else if (imageRepeat
.compareTo(Annotation
.IMAGE_REPEAT_Y
) == 0) this.cbImageRepeat
.setSelectedIndex(2);
1420 else if (imageRepeat
.compareTo(Annotation
.IMAGE_REPEAT_XY
) == 0) this.cbImageRepeat
.setSelectedIndex(3);
1422 this.imageScaleSlider
.setValue((int)(this.currentAnnotation
.getAttributes().getImageScale() * 10));
1423 this.imageOpacitySlider
.setValue((int)(this.currentAnnotation
.getAttributes().getImageOpacity() * 10));
1424 this.imageOffsetXSlider
.setValue((int)(this.currentAnnotation
.getAttributes().getImageOffset().x
));
1425 this.imageOffsetYSlider
.setValue((int)(this.currentAnnotation
.getAttributes().getImageOffset().y
));
1427 this.offsetXSlider
.setValue(this.currentAnnotation
.getAttributes().getDrawOffset().x
);
1428 this.offsetYSlider
.setValue(this.currentAnnotation
.getAttributes().getDrawOffset().y
);
1430 this.distanceMinScaleSlider
.setValue((int)(this.currentAnnotation
.getAttributes().getDistanceMinScale() * 10));
1431 this.distanceMaxScaleSlider
.setValue((int)(this.currentAnnotation
.getAttributes().getDistanceMaxScale() * 10));
1432 this.distanceMinOpacitySlider
.setValue((int)(this.currentAnnotation
.getAttributes().getDistanceMinOpacity() * 10));
1433 this.highlightScaleSlider
.setValue((int)(this.currentAnnotation
.getAttributes().getHighlightScale() * 10));
1435 AppFrame
.this.btApply
.setEnabled(true);
1436 AppFrame
.this.btRemove
.setEnabled(true);
1437 this.suspendUpdate
= false;
1441 this.inputTextArea
.setText("");
1442 AppFrame
.this.btApply
.setEnabled(false);
1443 AppFrame
.this.btRemove
.setEnabled(false);
1447 private void updateAnnotation()
1449 if(this.currentAnnotation
!= null && !this.suspendUpdate
)
1451 this.currentAnnotation
.setText(this.inputTextArea
.getText());
1452 this.currentAnnotation
.getAttributes().setSize(new Dimension(this.widthSlider
.getValue(), this.heightSlider
.getValue()));
1453 this.currentAnnotation
.getAttributes().setScale((double)this.scaleSlider
.getValue() / 10);
1454 this.currentAnnotation
.getAttributes().setOpacity((double)this.opacitySlider
.getValue() / 10);
1455 this.currentAnnotation
.getAttributes().setAdjustWidthToText(this.cbAdjustWidth
.isSelected() ?
1456 Annotation
.SIZE_FIT_TEXT
: Annotation
.SIZE_FIXED
);
1458 String fontString
= this.cbFontName
.getSelectedItem() + "-"
1459 + this.cbFontStyle
.getSelectedItem().toString().toUpperCase() + "-"
1460 + this.cbFontSize
.getSelectedItem();
1461 this.currentAnnotation
.getAttributes().setFont(Font
.decode(fontString
));
1463 Color color
= this.btTextColor
.getBackground();
1464 int alpha
= (int)(Float
.valueOf((String
)this.cbTextColorAlpha
.getSelectedItem()) * 25.5f
);
1465 this.currentAnnotation
.getAttributes().setTextColor(new Color(color
.getRed(), color
.getGreen(), color
.getBlue(), alpha
));
1467 color
= this.btBackColor
.getBackground();
1468 alpha
= (int)(Float
.valueOf((String
)this.cbBackColorAlpha
.getSelectedItem()) * 25.5f
);
1469 this.currentAnnotation
.getAttributes().setBackgroundColor(new Color(color
.getRed(), color
.getGreen(), color
.getBlue(), alpha
));
1471 color
= this.btBorderColor
.getBackground();
1472 alpha
= (int)(Float
.valueOf((String
)this.cbBorderColorAlpha
.getSelectedItem()) * 25.5f
);
1473 this.currentAnnotation
.getAttributes().setBorderColor(new Color(color
.getRed(), color
.getGreen(), color
.getBlue(), alpha
));
1474 this.savedBorderColor
= this.currentAnnotation
.getAttributes().getBorderColor();
1476 switch (cbTextAlign
.getSelectedIndex())
1478 case 0 : {this.currentAnnotation
.getAttributes().setTextAlign(MultiLineTextRenderer
.ALIGN_LEFT
); break;}
1479 case 1 : {this.currentAnnotation
.getAttributes().setTextAlign(MultiLineTextRenderer
.ALIGN_CENTER
); break;}
1480 case 2 : {this.currentAnnotation
.getAttributes().setTextAlign(MultiLineTextRenderer
.ALIGN_RIGHT
); break;}
1482 switch (cbTextEffect
.getSelectedIndex())
1484 case 0 : {this.currentAnnotation
.getAttributes().setEffect(MultiLineTextRenderer
.EFFECT_NONE
); break;}
1485 case 1 : {this.currentAnnotation
.getAttributes().setEffect(MultiLineTextRenderer
.EFFECT_SHADOW
); break;}
1486 case 2 : {this.currentAnnotation
.getAttributes().setEffect(MultiLineTextRenderer
.EFFECT_OUTLINE
); break;}
1488 switch (cbShape
.getSelectedIndex())
1490 case 0 : {this.currentAnnotation
.getAttributes().setFrameShape(FrameFactory
.SHAPE_RECTANGLE
); break;}
1491 case 1 : {this.currentAnnotation
.getAttributes().setFrameShape(FrameFactory
.SHAPE_ELLIPSE
); break;}
1492 case 2 : {this.currentAnnotation
.getAttributes().setFrameShape(FrameFactory
.SHAPE_NONE
); break;}
1494 switch (cbLeader
.getSelectedIndex())
1496 case 0 : {this.currentAnnotation
.getAttributes().setLeader(FrameFactory
.LEADER_TRIANGLE
); break;}
1497 case 1 : {this.currentAnnotation
.getAttributes().setLeader(FrameFactory
.LEADER_NONE
); break;}
1499 currentAnnotation
.getAttributes().setCornerRadius(this.cornerRadiusSlider
.getValue());
1500 currentAnnotation
.getAttributes().setInsets(new Insets(
1501 Integer
.parseInt(insetsTop
.getValue().toString()),
1502 Integer
.parseInt(insetsLeft
.getValue().toString()),
1503 Integer
.parseInt(insetsBottom
.getValue().toString()),
1504 Integer
.parseInt(insetsRight
.getValue().toString())));
1506 currentAnnotation
.getAttributes().setBorderWidth((double)borderWidthSlider
.getValue() / 10);
1507 currentAnnotation
.getAttributes().setBorderStippleFactor(stippleFactorSlider
.getValue());
1509 switch (cbAntialias
.getSelectedIndex())
1511 case 0: currentAnnotation
.getAttributes().setAntiAliasHint(Annotation
.ANTIALIAS_DONT_CARE
); break;
1512 case 1: currentAnnotation
.getAttributes().setAntiAliasHint(Annotation
.ANTIALIAS_FASTEST
); break;
1513 case 2: currentAnnotation
.getAttributes().setAntiAliasHint(Annotation
.ANTIALIAS_NICEST
); break;
1516 switch (cbImage
.getSelectedIndex())
1518 case 0: currentAnnotation
.getAttributes().setImageSource(null); break;
1519 case 1: currentAnnotation
.getAttributes().setImageSource(IMAGE_EARTH
); break;
1520 case 2: currentAnnotation
.getAttributes().setImageSource(IMAGE_NASA
); break;
1521 case 3: currentAnnotation
.getAttributes().setImageSource(IMAGE_WWJ_SPLASH
); break;
1522 case 4: currentAnnotation
.getAttributes().setImageSource(savedImage
); break;
1524 switch (cbImageRepeat
.getSelectedIndex())
1526 case 0: currentAnnotation
.getAttributes().setImageRepeat(Annotation
.IMAGE_REPEAT_NONE
); break;
1527 case 1: currentAnnotation
.getAttributes().setImageRepeat(Annotation
.IMAGE_REPEAT_X
); break;
1528 case 2: currentAnnotation
.getAttributes().setImageRepeat(Annotation
.IMAGE_REPEAT_Y
); break;
1529 case 3: currentAnnotation
.getAttributes().setImageRepeat(Annotation
.IMAGE_REPEAT_XY
); break;
1532 this.currentAnnotation
.getAttributes().setImageScale((double)this.imageScaleSlider
.getValue() / 10);
1533 this.currentAnnotation
.getAttributes().setImageOpacity((double)this.imageOpacitySlider
.getValue() / 10);
1534 this.currentAnnotation
.getAttributes().setImageOffset(new Point(imageOffsetXSlider
.getValue(),
1535 imageOffsetYSlider
.getValue()));
1537 this.currentAnnotation
.getAttributes().setDrawOffset(new Point(offsetXSlider
.getValue(), offsetYSlider
.getValue()));
1539 this.currentAnnotation
.getAttributes().setDistanceMinScale((double)this.distanceMinScaleSlider
.getValue() / 10);
1540 this.currentAnnotation
.getAttributes().setDistanceMaxScale((double)this.distanceMaxScaleSlider
.getValue() / 10);
1541 this.currentAnnotation
.getAttributes().setDistanceMinOpacity((double)this.distanceMinOpacitySlider
.getValue() / 10);
1542 this.currentAnnotation
.getAttributes().setHighlightScale((double)this.highlightScaleSlider
.getValue() / 10);
1548 private Position
computeGroundPosition(WorldWindowGLCanvas wwd
)
1550 View view
= wwd
.getView();
1555 Position groundPos
= view
.computePositionFromScreenPoint(
1556 view
.getViewport().getWidth() / 2, view
.getViewport().getHeight() / 2);
1561 * Simple (and unfinished) save annotations to a KML file.
1565 StringBuilder sb
= new StringBuilder();
1566 sb
.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
1567 sb
.append("<kml xmlns=\"http://earth.google.com/kml/2.2\">\n");
1568 sb
.append("<Folder>\n");
1569 sb
.append(" <name>WWJ Annotations</name>\n");
1570 Iterator
<Annotation
> annotations
= layer
.getAnnotations().iterator();
1571 while(annotations
.hasNext())
1573 GlobeAnnotation ga
= (GlobeAnnotation
)annotations
.next();
1574 String bgColor
= ga
.getAttributes().getBackgroundColor() != null ?
getHexaColorABGR(ga
.getAttributes().getBackgroundColor()) : "66000000";
1575 String textColor
= ga
.getAttributes().getTextColor() != null ?
getHexaColorABGR(ga
.getAttributes().getTextColor()) : "ccffffff";
1576 String borderColor
= ga
.getAttributes().getBorderColor() != null ?
getHexaColorABGR(ga
.getAttributes().getBorderColor()) : "ccffffff";
1577 sb
.append(" <Placemark>\n");
1578 sb
.append(" <Style>\n");
1579 sb
.append(" <BalloonStyle>\n");
1580 if(bgColor
.length() > 0) sb
.append(" <bgColor>" + bgColor
+ "</bgColor>\n");
1581 if(textColor
.length() > 0) sb
.append(" <textColor>" + textColor
+ "</textColor>\n");
1582 if(borderColor
.length() > 0) sb
.append(" <borderColor>" + borderColor
+ "</borderColor>\n");
1583 sb
.append(" </BalloonStyle>\n");
1584 sb
.append(" </Style>\n");
1585 sb
.append(" <name>");
1586 sb
.append(ga
.getText().length() > 50 ? ga
.getText().substring(0, 47) + "..." : ga
.getText() );
1587 sb
.append("</name>\n");
1588 sb
.append(" <description>");
1589 sb
.append("<![CDATA[" + ga
.getText().replaceAll("\n", "<br />") + "]]>");
1590 sb
.append("</description>\n");
1591 sb
.append(" <Point>");
1592 sb
.append("<coordinates>" + ga
.getPosition().getLongitude().degrees
+ ","
1593 + ga
.getPosition().getLatitude().degrees
+ ","
1594 + ga
.getPosition().getElevation() + "</coordinates>");
1595 sb
.append("</Point>\n");
1597 sb
.append(" </Placemark>\n");
1599 sb
.append("</Folder>\n");
1600 sb
.append("</kml>\n");
1602 System
.out
.println(sb
);
1605 private String
getHexaColorABGR(Color color
)
1607 return String
.format("%1$02x%2$02x%3$02x%4$02x", color
.getAlpha(), color
.getBlue(), color
.getGreen(), color
.getRed());
1613 public static void main(String
[] args
)
1615 ApplicationTemplate
.start("World Wind Annotations", AppFrame
.class);