private void paintBox(Graphics g, MapView mv, EastNorthBound img, Color color) { Point[] croppedPoint = new Point[5]; croppedPoint[0] = mv.getPoint(img.min); croppedPoint[1] = mv.getPoint(new EastNorth(img.min.east(), img.max.north())); croppedPoint[2] = mv.getPoint(img.max); croppedPoint[3] = mv.getPoint(new EastNorth(img.max.east(), img.min.north())); croppedPoint[4] = croppedPoint[0]; for (int i = 0; i < 4; i++) { g.setColor(color); g.drawLine( croppedPoint[i].x, croppedPoint[i].y, croppedPoint[i + 1].x, croppedPoint[i + 1].y); } }
/** * Draws a circle around the node * * @param n The node * @param color The circle color */ public void drawNode(Node n, Color color) { Point p = mv.getPoint(n); g.setColor(color); if (selected) { g.fillOval(p.x - 5, p.y - 5, 10, 10); } else g.drawOval(p.x - 5, p.y - 5, 10, 10); }
/** * Checks if the given segment is in the visible area. NOTE: This will return true for a small * number of non-visible segments. * * @param ls The segment to check * @return true if the segment is visible */ protected boolean isSegmentVisible(Node n1, Node n2) { Point p1 = mv.getPoint(n1); Point p2 = mv.getPoint(n2); if ((p1.x < 0) && (p2.x < 0)) return false; if ((p1.y < 0) && (p2.y < 0)) return false; if ((p1.x > mv.getWidth()) && (p2.x > mv.getWidth())) return false; if ((p1.y > mv.getHeight()) && (p2.y > mv.getHeight())) return false; return true; }
/** * Draw all primitives in this layer but do not draw modified ones (they are drawn by the edit * layer). Draw nodes last to overlap the ways they belong to. */ @Override public void paint(final Graphics g, final MapView mv) { boolean active = true; boolean inactive = false; boolean virtual = false; // draw the hatched area for non-downloaded region. only draw if we're // the active // and bounds are defined; don't draw for inactive layers or loaded GPX // files etc if (active && Main.pref.getBoolean("draw.data.downloaded_area", true) && !data.dataSources.isEmpty()) { // initialize area with current viewport Rectangle b = Main.map.mapView.getBounds(); // on some platforms viewport bounds seem to be offset from the // left, // over-grow it just to be sure b.grow(100, 100); Area a = new Area(b); // now succesively subtract downloaded areas for (DataSource src : data.dataSources) { if (src.bounds != null && !src.bounds.min.equals(src.bounds.max)) { EastNorth en1 = Main.proj.latlon2eastNorth(src.bounds.min); EastNorth en2 = Main.proj.latlon2eastNorth(src.bounds.max); Point p1 = mv.getPoint(en1); Point p2 = mv.getPoint(en2); Rectangle r = new Rectangle( Math.min(p1.x, p2.x), Math.min(p1.y, p2.y), Math.abs(p2.x - p1.x), Math.abs(p2.y - p1.y)); a.subtract(new Area(r)); } } // paint remainder ((Graphics2D) g).setPaint(hatched); ((Graphics2D) g).fill(a); } SimplePaintVisitor painter; if (Main.pref.getBoolean("draw.wireframe")) painter = new SimplePaintVisitor(); else painter = new MapPaintVisitor(); painter.setGraphics(g); painter.setNavigatableComponent(mv); painter.inactive = inactive; painter.visitAll(data, virtual); // Main.map.conflictDialog.paintConflicts(g, mv); }
/** * Checks if the given node is in the visible area. * * @param n The node to check for visibility * @return true if the node is visible */ protected boolean isNodeVisible(Node n) { Point p = mv.getPoint(n); return !((p.x < 0) || (p.y < 0) || (p.x > mv.getWidth()) || (p.y > mv.getHeight())); }
/** * Draws a line around the segment * * @param s The segment * @param color The color */ public void drawSegment(Node n1, Node n2, Color color) { drawSegment(mv.getPoint(n1), mv.getPoint(n2), color); }
@Override public void paint(Graphics2D g, MapView mv, Bounds bounds) { int width = mv.getWidth(); int height = mv.getHeight(); Rectangle clip = g.getClipBounds(); if (useThumbs) { if (!thumbsLoaded) { startLoadThumbs(); } if (null == offscreenBuffer || offscreenBuffer.getWidth() != width // reuse the old buffer if possible || offscreenBuffer.getHeight() != height) { offscreenBuffer = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); updateOffscreenBuffer = true; } if (updateOffscreenBuffer) { Graphics2D tempG = offscreenBuffer.createGraphics(); tempG.setColor(new Color(0, 0, 0, 0)); Composite saveComp = tempG.getComposite(); tempG.setComposite(AlphaComposite.Clear); // remove the old images tempG.fillRect(0, 0, width, height); tempG.setComposite(saveComp); if (data != null) { for (ImageEntry e : data) { if (e.getPos() == null) { continue; } Point p = mv.getPoint(e.getPos()); if (e.hasThumbnail()) { Dimension d = scaledDimension(e.getThumbnail()); Rectangle target = new Rectangle(p.x - d.width / 2, p.y - d.height / 2, d.width, d.height); if (clip.intersects(target)) { tempG.drawImage( e.getThumbnail(), target.x, target.y, target.width, target.height, null); } } else { // thumbnail not loaded yet icon.paintIcon( mv, tempG, p.x - icon.getIconWidth() / 2, p.y - icon.getIconHeight() / 2); } } } updateOffscreenBuffer = false; } g.drawImage(offscreenBuffer, 0, 0, null); } else if (data != null) { for (ImageEntry e : data) { if (e.getPos() == null) { continue; } Point p = mv.getPoint(e.getPos()); icon.paintIcon(mv, g, p.x - icon.getIconWidth() / 2, p.y - icon.getIconHeight() / 2); } } if (currentPhoto >= 0 && currentPhoto < data.size()) { ImageEntry e = data.get(currentPhoto); if (e.getPos() != null) { Point p = mv.getPoint(e.getPos()); int imgWidth; int imgHeight; if (useThumbs && e.hasThumbnail()) { Dimension d = scaledDimension(e.getThumbnail()); imgWidth = d.width; imgHeight = d.height; } else { imgWidth = selectedIcon.getIconWidth(); imgHeight = selectedIcon.getIconHeight(); } if (e.getExifImgDir() != null) { // Multiplier must be larger than sqrt(2)/2=0.71. double arrowlength = Math.max(25, Math.max(imgWidth, imgHeight) * 0.85); double arrowwidth = arrowlength / 1.4; double dir = e.getExifImgDir(); // Rotate 90 degrees CCW double headdir = (dir < 90) ? dir + 270 : dir - 90; double leftdir = (headdir < 90) ? headdir + 270 : headdir - 90; double rightdir = (headdir > 270) ? headdir - 270 : headdir + 90; double ptx = p.x + Math.cos(Math.toRadians(headdir)) * arrowlength; double pty = p.y + Math.sin(Math.toRadians(headdir)) * arrowlength; double ltx = p.x + Math.cos(Math.toRadians(leftdir)) * arrowwidth / 2; double lty = p.y + Math.sin(Math.toRadians(leftdir)) * arrowwidth / 2; double rtx = p.x + Math.cos(Math.toRadians(rightdir)) * arrowwidth / 2; double rty = p.y + Math.sin(Math.toRadians(rightdir)) * arrowwidth / 2; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setColor(new Color(255, 255, 255, 192)); int[] xar = {(int) ltx, (int) ptx, (int) rtx, (int) ltx}; int[] yar = {(int) lty, (int) pty, (int) rty, (int) lty}; g.fillPolygon(xar, yar, 4); g.setColor(Color.black); g.setStroke(new BasicStroke(1.2f)); g.drawPolyline(xar, yar, 3); } if (useThumbs && e.hasThumbnail()) { g.setColor(new Color(128, 0, 0, 122)); g.fillRect(p.x - imgWidth / 2, p.y - imgHeight / 2, imgWidth, imgHeight); } else { selectedIcon.paintIcon(mv, g, p.x - imgWidth / 2, p.y - imgHeight / 2); } } } }
Point getPoint(LatLon p) { return mv.getPoint(p); }
@Override public void paint(Graphics2D g, MapView mv, Bounds bounds) { int width = Main.map.mapView.getWidth(); int height = Main.map.mapView.getHeight(); Rectangle clip = g.getClipBounds(); if (useThumbs) { if (null == offscreenBuffer || offscreenBuffer.getWidth() != width // reuse the old buffer if possible || offscreenBuffer.getHeight() != height) { offscreenBuffer = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); updateOffscreenBuffer = true; } if (updateOffscreenBuffer) { Graphics2D tempG = offscreenBuffer.createGraphics(); tempG.setColor(new Color(0, 0, 0, 0)); Composite saveComp = tempG.getComposite(); tempG.setComposite(AlphaComposite.Clear); // remove the old images tempG.fillRect(0, 0, width, height); tempG.setComposite(saveComp); for (ImageEntry e : data) { if (e.getPos() == null) { continue; } Point p = mv.getPoint(e.getPos()); if (e.thumbnail != null) { Dimension d = scaledDimension(e.thumbnail); Rectangle target = new Rectangle(p.x - d.width / 2, p.y - d.height / 2, d.width, d.height); if (clip.intersects(target)) { tempG.drawImage(e.thumbnail, target.x, target.y, target.width, target.height, null); } } else { // thumbnail not loaded yet icon.paintIcon( mv, tempG, p.x - icon.getIconWidth() / 2, p.y - icon.getIconHeight() / 2); } } updateOffscreenBuffer = false; } g.drawImage(offscreenBuffer, 0, 0, null); } else { for (ImageEntry e : data) { if (e.getPos() == null) { continue; } Point p = mv.getPoint(e.getPos()); icon.paintIcon(mv, g, p.x - icon.getIconWidth() / 2, p.y - icon.getIconHeight() / 2); } } if (currentPhoto >= 0 && currentPhoto < data.size()) { ImageEntry e = data.get(currentPhoto); if (e.getPos() != null) { Point p = mv.getPoint(e.getPos()); if (e.thumbnail != null) { Dimension d = scaledDimension(e.thumbnail); g.setColor(new Color(128, 0, 0, 122)); g.fillRect(p.x - d.width / 2, p.y - d.height / 2, d.width, d.height); } else { if (e.getExifImgDir() != null) { double arrowlength = 25; double arrowwidth = 18; double dir = e.getExifImgDir(); // Rotate 90 degrees CCW double headdir = (dir < 90) ? dir + 270 : dir - 90; double leftdir = (headdir < 90) ? headdir + 270 : headdir - 90; double rightdir = (headdir > 270) ? headdir - 270 : headdir + 90; double ptx = p.x + Math.cos(Math.toRadians(headdir)) * arrowlength; double pty = p.y + Math.sin(Math.toRadians(headdir)) * arrowlength; double ltx = p.x + Math.cos(Math.toRadians(leftdir)) * arrowwidth / 2; double lty = p.y + Math.sin(Math.toRadians(leftdir)) * arrowwidth / 2; double rtx = p.x + Math.cos(Math.toRadians(rightdir)) * arrowwidth / 2; double rty = p.y + Math.sin(Math.toRadians(rightdir)) * arrowwidth / 2; g.setColor(Color.white); int[] xar = {(int) ltx, (int) ptx, (int) rtx, (int) ltx}; int[] yar = {(int) lty, (int) pty, (int) rty, (int) lty}; g.fillPolygon(xar, yar, 4); } selectedIcon.paintIcon( mv, g, p.x - selectedIcon.getIconWidth() / 2, p.y - selectedIcon.getIconHeight() / 2); } } } }
@Override public void paint(Graphics2D g, MapView mv, Bounds box) { final int iconHeight = ImageProvider.ImageSizes.SMALLICON.getAdjustedHeight(); final int iconWidth = ImageProvider.ImageSizes.SMALLICON.getAdjustedWidth(); for (Note note : noteData.getNotes()) { Point p = mv.getPoint(note.getLatLon()); ImageIcon icon; if (note.getId() < 0) { icon = ImageProvider.get("dialogs/notes", "note_new", ImageProvider.ImageSizes.SMALLICON); } else if (note.getState() == State.CLOSED) { icon = ImageProvider.get("dialogs/notes", "note_closed", ImageProvider.ImageSizes.SMALLICON); } else { icon = ImageProvider.get("dialogs/notes", "note_open", ImageProvider.ImageSizes.SMALLICON); } int width = icon.getIconWidth(); int height = icon.getIconHeight(); g.drawImage(icon.getImage(), p.x - (width / 2), p.y - height, Main.map.mapView); } if (noteData.getSelectedNote() != null) { StringBuilder sb = new StringBuilder("<html>"); sb.append(tr("Note")).append(' ').append(noteData.getSelectedNote().getId()); for (NoteComment comment : noteData.getSelectedNote().getComments()) { String commentText = comment.getText(); // closing a note creates an empty comment that we don't want to show if (commentText != null && !commentText.trim().isEmpty()) { sb.append("<hr/>"); String userName = XmlWriter.encode(comment.getUser().getName()); if (userName == null || userName.trim().isEmpty()) { userName = "******"; } sb.append(userName); sb.append(" on "); sb.append( DateUtils.getDateFormat(DateFormat.MEDIUM).format(comment.getCommentTimestamp())); sb.append(":<br/>"); String htmlText = XmlWriter.encode(comment.getText(), true); htmlText = htmlText.replace( "
", "<br/>"); // encode method leaves us with entity instead of \n htmlText = htmlText.replace("/", "/\u200b"); // zero width space to wrap long URLs (see #10864) sb.append(htmlText); } } sb.append("</html>"); JToolTip toolTip = new JToolTip(); toolTip.setTipText(sb.toString()); Point p = mv.getPoint(noteData.getSelectedNote().getLatLon()); g.setColor(ColorHelper.html2color(Main.pref.get("color.selected"))); g.drawRect(p.x - (iconWidth / 2), p.y - iconHeight, iconWidth - 1, iconHeight - 1); int tx = p.x + (iconWidth / 2) + 5; int ty = p.y - iconHeight - 1; g.translate(tx, ty); // Carried over from the OSB plugin. Not entirely sure why it is needed // but without it, the tooltip doesn't get sized correctly for (int x = 0; x < 2; x++) { Dimension d = toolTip.getUI().getPreferredSize(toolTip); d.width = Math.min(d.width, mv.getWidth() / 2); if (d.width > 0 && d.height > 0) { toolTip.setSize(d); try { toolTip.paint(g); } catch (IllegalArgumentException e) { // See #11123 - https://bugs.openjdk.java.net/browse/JDK-6719550 // Ignore the exception, as Netbeans does: // http://hg.netbeans.org/main-silver/rev/c96f4d5fbd20 Main.error(e, false); } } } g.translate(-tx, -ty); } }