1 | package iodb;
|
---|
2 |
|
---|
3 | import java.awt.*;
|
---|
4 | import javax.swing.Icon;
|
---|
5 | import javax.swing.ImageIcon;
|
---|
6 | import javax.swing.JButton;
|
---|
7 | import org.openstreetmap.josm.gui.layer.ImageryLayer;
|
---|
8 | import org.openstreetmap.josm.tools.ImageProvider;
|
---|
9 |
|
---|
10 | /**
|
---|
11 | * A button which shows offset information.
|
---|
12 | *
|
---|
13 | * @author zverik
|
---|
14 | */
|
---|
15 | public class OffsetDialogButton extends JButton {
|
---|
16 |
|
---|
17 | private ImageryOffsetBase offset;
|
---|
18 | private double offsetLength;
|
---|
19 | private double distance;
|
---|
20 | private double direction;
|
---|
21 |
|
---|
22 | public OffsetDialogButton( ImageryOffsetBase offset ) {
|
---|
23 | super();
|
---|
24 | this.offset = offset;
|
---|
25 | // setMinimumSize(new Dimension(500, 10));
|
---|
26 | // setMaximumSize(new Dimension(500, 150));
|
---|
27 | setRelevantText();
|
---|
28 | setIcon(new OffsetIcon(offset));
|
---|
29 |
|
---|
30 | offsetLength = offset instanceof ImageryOffset ? getLengthAndDirection((ImageryOffset)offset)[0] : 0.0;
|
---|
31 | // todo: layout, info, map distance and direction
|
---|
32 | // http://stackoverflow.com/questions/1048224/get-height-of-multi-line-text-with-fixed-width-to-make-dialog-resize-properly
|
---|
33 | // http://docs.oracle.com/javase/tutorial/uiswing/layout/box.html#size
|
---|
34 | // http://stackoverflow.com/questions/8012646/setting-size-of-jbutton-inside-jpanel-with-boxlayout-doesnt-work-as-expected
|
---|
35 | // http://blog.nobel-joergensen.com/2009/01/18/changing-preferred-size-of-a-html-jlabel/
|
---|
36 | // http://thebadprogrammer.com/swing-layout-manager-sizing/
|
---|
37 | // http://stackoverflow.com/questions/3692987/why-will-boxlayout-not-allow-me-to-change-the-width-of-a-jbutton-but-let-me-chan
|
---|
38 |
|
---|
39 | // http://stackoverflow.com/questions/2158/creating-a-custom-button-in-java
|
---|
40 | }
|
---|
41 |
|
---|
42 | /**
|
---|
43 | * Update text on the button. This method is to be deleted by release.
|
---|
44 | */
|
---|
45 | public void setRelevantText() {
|
---|
46 | setText("<html><div style=\"width: 400px;\">"
|
---|
47 | + ImageryOffsetTools.formatDistance(offset.getPosition().greatCircleDistance(ImageryOffsetTools.getMapCenter()))
|
---|
48 | + ": " + offset.getDescription() + "</div></html>");
|
---|
49 | }
|
---|
50 |
|
---|
51 | public ImageryOffsetBase getOffset() {
|
---|
52 | return offset;
|
---|
53 | }
|
---|
54 |
|
---|
55 | /* @Override
|
---|
56 | public Dimension getPreferredSize() {
|
---|
57 | Dimension size = super.getPreferredSize();
|
---|
58 | size.width = 500;
|
---|
59 | size.height = 70;
|
---|
60 | return size;
|
---|
61 | }*/
|
---|
62 |
|
---|
63 | /**
|
---|
64 | * Update arrow for the offset location.
|
---|
65 | */
|
---|
66 | public void updateLocation() {
|
---|
67 | // map was moved, update arrow.
|
---|
68 | setRelevantText();
|
---|
69 | }
|
---|
70 |
|
---|
71 | private double[] getLengthAndDirection( ImageryOffset offset ) {
|
---|
72 | ImageryLayer layer = ImageryOffsetTools.getTopImageryLayer();
|
---|
73 | double[] dxy = layer == null ? new double[] {0.0, 0.0} : new double[] {layer.getDx(), layer.getDy()};
|
---|
74 | return ImageryOffsetTools.getLengthAndDirection((ImageryOffset)offset, dxy[0], dxy[1]);
|
---|
75 | }
|
---|
76 |
|
---|
77 | class OffsetIcon implements Icon {
|
---|
78 | private boolean isDeprecated;
|
---|
79 | private boolean isCalibration;
|
---|
80 | private double direction = -1.0;
|
---|
81 | private double length;
|
---|
82 | private ImageIcon background;
|
---|
83 |
|
---|
84 | public OffsetIcon( ImageryOffsetBase offset ) {
|
---|
85 | isDeprecated = offset.isDeprecated();
|
---|
86 | isCalibration = offset instanceof CalibrationObject;
|
---|
87 | if( offset instanceof ImageryOffset ) {
|
---|
88 | background = ImageProvider.get("offset");
|
---|
89 | ImageryLayer layer = ImageryOffsetTools.getTopImageryLayer();
|
---|
90 | double[] dxy = layer == null ? new double[] {0.0, 0.0} : new double[] { layer.getDx(), layer.getDy() };
|
---|
91 | double[] ld = ImageryOffsetTools.getLengthAndDirection((ImageryOffset)offset, dxy[0], dxy[1]);
|
---|
92 | length = ld[0];
|
---|
93 | direction = ld[1];
|
---|
94 | } else {
|
---|
95 | background = ImageProvider.get("calibration");
|
---|
96 | }
|
---|
97 | }
|
---|
98 |
|
---|
99 | public void paintIcon( Component comp, Graphics g, int x, int y ) {
|
---|
100 | background.paintIcon(comp, g, x, y);
|
---|
101 |
|
---|
102 | Graphics2D g2 = (Graphics2D)g.create();
|
---|
103 | g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
---|
104 | if( direction >= 0 ) {
|
---|
105 | g2.setColor(Color.black);
|
---|
106 | Point c = new Point(x + getIconWidth() / 2, y + getIconHeight() / 2);
|
---|
107 | if( length < 1e-2 ) {
|
---|
108 | // no offset
|
---|
109 | g2.fillOval(c.x - 3, c.y - 3, 7, 7);
|
---|
110 | } else {
|
---|
111 | // draw an arrow
|
---|
112 | double arrowLength = length < 5 ? getIconWidth() / 2 - 1 : getIconWidth() - 4;
|
---|
113 | g2.setStroke(new BasicStroke(2));
|
---|
114 | int dx = (int)Math.round(Math.sin(direction) * arrowLength / 2);
|
---|
115 | int dy = (int)Math.round(Math.cos(direction) * arrowLength / 2);
|
---|
116 | g2.drawLine(c.x - dx, c.y - dy, c.x + dx, c.y + dy);
|
---|
117 | double wingLength = arrowLength / 3;
|
---|
118 | double d1 = direction - Math.PI / 6;
|
---|
119 | int dx1 = (int)Math.round(Math.sin(d1) * wingLength);
|
---|
120 | int dy1 = (int)Math.round(Math.cos(d1) * wingLength);
|
---|
121 | g2.drawLine(c.x + dx, c.y + dy, c.x + dx - dx1, c.y + dy - dy1);
|
---|
122 | double d2 = direction + Math.PI / 6;
|
---|
123 | int dx2 = (int)Math.round(Math.sin(d2) * wingLength);
|
---|
124 | int dy2 = (int)Math.round(Math.cos(d2) * wingLength);
|
---|
125 | g2.drawLine(c.x + dx, c.y + dy, c.x + dx - dx2, c.y + dy - dy2);
|
---|
126 | }
|
---|
127 | }
|
---|
128 | if( isDeprecated ) {
|
---|
129 | // big red X
|
---|
130 | g2.setColor(Color.red);
|
---|
131 | g2.setStroke(new BasicStroke(5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
|
---|
132 | g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f));
|
---|
133 | g2.drawLine(x + 2, y + 2, x + getIconWidth() - 2, y + getIconHeight() - 2);
|
---|
134 | g2.drawLine(x + 2, y + getIconHeight() - 2, x + getIconWidth() - 2, y + 2);
|
---|
135 | }
|
---|
136 | }
|
---|
137 |
|
---|
138 | public int getIconWidth() {
|
---|
139 | return background.getIconWidth();
|
---|
140 | }
|
---|
141 |
|
---|
142 | public int getIconHeight() {
|
---|
143 | return background.getIconHeight();
|
---|
144 | }
|
---|
145 | }
|
---|
146 | }
|
---|