Ignore:
Timestamp:
2011-08-21T13:12:53+02:00 (13 years ago)
Author:
xeen
Message:

updates visual appearance of highlights and adds them to select and delete action

in more detail:

  • add target highlighting to select action
  • add target cursor to select action
  • add target highlighting to delete action
  • unify ctrl/alt/shift modifier detection in MapMode actions
  • highlights are now a halo around the way/node instead of a color change
  • default highlight color is now the same as the select color (red)
  • ability to highlight WaySegments and VirtualNodes
  • various style/whitespace nits
  • fixes #2411

This patch touches a lot of areas, so please report any regressions in the map mode
tools. Also please add a comment to #2411 if you find to highlighting in select
mode distracting, so it can be fine tuned (or turned off by default).

Location:
trunk/src/org/openstreetmap/josm/data/osm/visitor/paint
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/MapPainter.java

    r4319 r4327  
    3535import org.openstreetmap.josm.data.osm.RelationMember;
    3636import org.openstreetmap.josm.data.osm.Way;
     37import org.openstreetmap.josm.data.osm.WaySegment;
    3738import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon;
    3839import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon.PolyData;
    3940import org.openstreetmap.josm.gui.NavigatableComponent;
    4041import org.openstreetmap.josm.gui.mappaint.BoxTextElemStyle;
     42import org.openstreetmap.josm.gui.mappaint.NodeElemStyle;
     43import org.openstreetmap.josm.gui.mappaint.TextElement;
    4144import org.openstreetmap.josm.gui.mappaint.BoxTextElemStyle.HorizontalTextAlignment;
    4245import org.openstreetmap.josm.gui.mappaint.BoxTextElemStyle.VerticalTextAlignment;
    43 import org.openstreetmap.josm.gui.mappaint.NodeElemStyle;
    4446import org.openstreetmap.josm.gui.mappaint.NodeElemStyle.Symbol;
    45 import org.openstreetmap.josm.gui.mappaint.TextElement;
    4647import org.openstreetmap.josm.tools.ImageProvider;
    4748import org.openstreetmap.josm.tools.Pair;
     
    5354    private final boolean inactive;
    5455    private final MapPaintSettings settings;
     56    private final Collection<WaySegment> highlightWaySegments;
    5557
    5658    private final boolean useStrokes;
     
    6466    private final Color relationSelectedColor;
    6567    private final Color nodeColor;
     68    private final Color highlightColor;
     69    private final Color highlightColorTransparent;
    6670    private final Color backgroundColor;
    6771
     
    8185    public MapPainter(MapPaintSettings settings, Graphics2D g,
    8286            boolean inactive, NavigatableComponent nc, boolean virtual,
    83             double circum, boolean leftHandTraffic){
     87            double circum, boolean leftHandTraffic,
     88            Collection<WaySegment> highlightWaySegments){
    8489        this.settings = settings;
    8590        this.g = g;
    8691        this.inactive = inactive;
    8792        this.nc = nc;
     93        this.highlightWaySegments = highlightWaySegments;
    8894        this.useStrokes = settings.getUseStrokesDistance() > circum;
    8995        this.showNames = settings.getShowNamesDistance() > circum;
     
    96102        this.relationSelectedColor = PaintColors.RELATIONSELECTED.get();
    97103        this.nodeColor = PaintColors.NODE.get();
     104        this.highlightColor = PaintColors.HIGHLIGHT.get();
     105        this.highlightColorTransparent = new Color(highlightColor.getRed(), highlightColor.getGreen(), highlightColor.getBlue(), 100);
    98106        this.backgroundColor = PaintColors.getBackgroundColor();
    99107
     
    131139        List<Node> wayNodes = way.getNodes();
    132140        if (wayNodes.size() < 2) return;
    133        
    134         Iterator<Point> it = new OffsetIterator(way.getNodes(), offset);
     141
     142        // only highlight the segment if the way itself is not highlighted
     143        if(!way.isHighlighted()) {
     144            GeneralPath highlightSegs = null;
     145            for(WaySegment ws : highlightWaySegments) {
     146                if(ws.way != way || ws.lowerIndex < offset) {
     147                    continue;
     148                }
     149                if(highlightSegs == null) {
     150                    highlightSegs = new GeneralPath();
     151                }
     152
     153                Point p1 = nc.getPoint(ws.getFirstNode());
     154                Point p2 = nc.getPoint(ws.getSecondNode());
     155                highlightSegs.moveTo(p1.x, p1.y);
     156                highlightSegs.lineTo(p2.x, p2.y);
     157            }
     158
     159            drawPathHighlight(highlightSegs, line);
     160        }
     161
     162
     163        Iterator<Point> it = new OffsetIterator(wayNodes, offset);
    135164        while (it.hasNext()) {
    136165            Point p = it.next();
     
    209238            lastPoint = p;
    210239        }
     240        if(way.isHighlighted()) {
     241            drawPathHighlight(path, line);
     242        }
    211243        displaySegments(path, orientationArrows, onewayArrows, onewayArrowsCasing, color, line, dashes, dashedColor);
    212244    }
     
    221253     */
    222254    public class OffsetIterator implements Iterator<Point> {
    223        
     255
    224256        private List<Node> nodes;
    225257        private int offset;
    226258        private int idx;
    227        
     259
    228260        private Point prev = null;
    229261        /* 'prev0' is a point that has distance 'offset' from 'prev' and the
     
    238270            idx = 0;
    239271        }
    240        
     272
    241273        @Override
    242274        public boolean hasNext() {
     
    247279        public Point next() {
    248280            if (offset == 0) return nc.getPoint(nodes.get(idx++));
    249            
     281
    250282            Point current = nc.getPoint(nodes.get(idx));
    251            
     283
    252284            if (idx == nodes.size() - 1) {
    253285                ++idx;
     
    277309                int dx_prev = current.x - prev.x;
    278310                int dy_prev = current.y - prev.y;
    279                
     311
    280312                // determine intersection of the lines parallel to the two
    281313                // segments
    282314                int det = dx_next*dy_prev - dx_prev*dy_next;
    283                
     315
    284316                if (det == 0) {
    285317                    ++idx;
     
    292324                int m = dx_next*(y_current0 - y_prev0) - dy_next*(x_current0 - x_prev0);
    293325
    294                 int cx_ = x_prev0 + (int) Math.round(m * dx_prev / det);
    295                 int cy_ = y_prev0 + (int) Math.round(m * dy_prev / det);
     326                int cx_ = x_prev0 + Math.round(m * dx_prev / det);
     327                int cy_ = y_prev0 + Math.round(m * dy_prev / det);
    296328                ++idx;
    297329                prev = current;
     
    307339        }
    308340    }
    309    
     341
    310342    private void displaySegments(GeneralPath path, GeneralPath orientationArrows, GeneralPath onewayArrows, GeneralPath onewayArrowsCasing,
    311343            Color color, BasicStroke line, BasicStroke dashes, Color dashedColor) {
     
    337369        if(useStrokes) {
    338370            g.setStroke(new BasicStroke());
     371        }
     372    }
     373
     374    /**
     375     * highlights a given GeneralPath using the settings from BasicStroke to match the line's
     376     * style. Width of the highlight is hard coded.
     377     * @param path
     378     * @param line
     379     */
     380    private void drawPathHighlight(GeneralPath path, BasicStroke line) {
     381        if(path == null)
     382            return;
     383        g.setColor(highlightColorTransparent);
     384        float w = (line.getLineWidth() + 4);
     385        while(w >= line.getLineWidth()) {
     386            g.setStroke(new BasicStroke(w, line.getEndCap(), line.getLineJoin(), line.getMiterLimit()));
     387            g.draw(path);
     388            w -= 4;
    339389        }
    340390    }
     
    498548    public void drawNodeIcon(Node n, ImageIcon icon, float iconAlpha, boolean selected, boolean member) {
    499549        Point p = nc.getPoint(n);
    500         if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth()) || (p.y > nc.getHeight())) return;
    501 
    502         int w = icon.getIconWidth(), h=icon.getIconHeight();
     550
     551        final int w = icon.getIconWidth(), h=icon.getIconHeight();
     552        if(n.isHighlighted()) {
     553            drawPointHighlight(p, Math.max(w, h));
     554        }
     555
    503556        if (iconAlpha != 1f) {
    504557            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, iconAlpha));
     
    530583    public void drawNodeSymbol(Node n, Symbol s, Color fillColor, Color strokeColor) {
    531584        Point p = nc.getPoint(n);
    532         if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth()) || (p.y > nc.getHeight())) return;
    533585        int radius = s.size / 2;
     586
     587        if(n.isHighlighted()) {
     588            drawPointHighlight(p, s.size);
     589        }
    534590
    535591        if (fillColor != null) {
     
    612668     */
    613669    public void drawNode(Node n, Color color, int size, boolean fill) {
     670        if(size <= 0 && !n.isHighlighted())
     671            return;
     672
     673        Point p = nc.getPoint(n);
     674
     675        if(n.isHighlighted()) {
     676            drawPointHighlight(p, size);
     677        }
     678
    614679        if (size > 1) {
    615             Point p = nc.getPoint(n);
    616680            if ((p.x < 0) || (p.y < 0) || (p.x > nc.getWidth()) || (p.y > nc.getHeight())) return;
    617681            int radius = size / 2;
     
    623687            }
    624688            if (fill) {
    625                 g.fillRect(p.x - radius, p.y - radius, size + 1, size + 1);
     689                g.fillRect(p.x-radius-1, p.y-radius-1, size + 1, size + 1);
    626690            } else {
    627                 g.drawRect(p.x - radius, p.y - radius, size, size);
    628             }
     691                g.drawRect(p.x-radius-1, p.y-radius-1, size, size);
     692            }
     693        }
     694    }
     695
     696    /**
     697     * highlights a given point by drawing a rounded rectangle around it. Give the
     698     * size of the object you want to be highlighted, width is added automatically.
     699     */
     700    private void drawPointHighlight(Point p, int size) {
     701        g.setColor(highlightColorTransparent);
     702        int s = size + 7;
     703        while(s >= size) {
     704            int r = (int) Math.floor(s/2);
     705            g.fillRoundRect(p.x-r, p.y-r, s, s, r, r);
     706            s -= 4;
    629707        }
    630708    }
     
    633711        if (!isShowNames() || bs == null)
    634712            return;
    635        
    636         Point p = nc.getPoint((Node) n);
     713
     714        Point p = nc.getPoint(n);
    637715        TextElement text = bs.text;
    638716        String s = text.labelCompositionStrategy.compose(n);
     
    823901
    824902    public void drawRestriction(Relation r, NodeElemStyle icon) {
    825 
    826903        Way fromWay = null;
    827904        Way toWay = null;
     
    9981075    }
    9991076
    1000     public void drawVirtualNodes(Collection<Way> ways) {
    1001 
    1002         if (virtualNodeSize != 0) {
    1003             GeneralPath path = new GeneralPath();
    1004             for (Way osm: ways){
    1005                 if (osm.isUsable() && !osm.isDisabled()) {
    1006                     visitVirtual(path, osm);
    1007                 }
    1008             }
    1009             g.setColor(nodeColor);
    1010             g.draw(path);
    1011         }
     1077    public void drawVirtualNodes(Collection<Way> ways, Collection<WaySegment> highlightVirtualNodes) {
     1078        if (virtualNodeSize == 0)
     1079            return;
     1080        // print normal virtual nodes
     1081        GeneralPath path = new GeneralPath();
     1082        for (Way osm: ways){
     1083            if (osm.isUsable() && !osm.isDisabled()) {
     1084                visitVirtual(path, osm);
     1085            }
     1086        }
     1087        g.setColor(nodeColor);
     1088        g.draw(path);
     1089        // print highlighted virtual nodes. Since only the color changes, simply
     1090        // drawing them over the existing ones works fine (at least in their current
     1091        // simple style)
     1092        path = new GeneralPath();
     1093        for (WaySegment wseg: highlightVirtualNodes){
     1094            if (wseg.way.isUsable() && !wseg.way.isDisabled()) {
     1095                visitVirtual(path, wseg.toWay());
     1096            }
     1097        }
     1098        g.setColor(highlightColor);
     1099        g.draw(path);
    10121100    }
    10131101
  • trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/PaintColors.java

    r3896 r4327  
    1010import org.openstreetmap.josm.data.Preferences.ColorKey;
    1111import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
     12import org.openstreetmap.josm.gui.mappaint.StyleSource;
    1213import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.MapPaintSylesUpdateListener;
    13 import org.openstreetmap.josm.gui.mappaint.StyleSource;
    1414
    1515public enum PaintColors implements ColorKey {
     
    2626    INCOMPLETE_WAY(marktr("incomplete way"), new Color(0,0,96)), // darker blue
    2727    BACKGROUND(marktr("background"), Color.BLACK),
    28     HIGHLIGHT(marktr("highlight"), new Color(0, 255, 186)), // lighteal
     28    HIGHLIGHT(marktr("highlight"), SELECTED.get()),
    2929
    3030    UNTAGGED(marktr("untagged"),Color.GRAY),
  • trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java

    r4317 r4327  
    55import java.awt.RenderingHints;
    66import java.util.ArrayList;
     7import java.util.Collection;
    78import java.util.Collections;
    89import java.util.List;
     
    1617import org.openstreetmap.josm.data.osm.Relation;
    1718import org.openstreetmap.josm.data.osm.Way;
     19import org.openstreetmap.josm.data.osm.WaySegment;
    1820import org.openstreetmap.josm.gui.NavigatableComponent;
    1921import org.openstreetmap.josm.gui.mappaint.AreaElemStyle;
     
    220222                        RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF);
    221223
    222         this.painter = new MapPainter(paintSettings, g, isInactiveMode, nc, renderVirtualNodes, circum, leftHandTraffic);
     224        Collection<WaySegment> hws = data.getHighlightedWaySegments();
     225
     226        this.painter = new MapPainter(paintSettings, g, isInactiveMode, nc, renderVirtualNodes, circum, leftHandTraffic, hws);
    223227
    224228        StyleCollector sc = new StyleCollector(drawArea, drawMultipolygon, drawRestriction);
     
    229233        sc.drawAll();
    230234        sc = null;
    231         painter.drawVirtualNodes(data.searchWays(bbox));
     235        painter.drawVirtualNodes(data.searchWays(bbox), data.getHighlightedVirtualNodes());
    232236
    233237        //long now = System.currentTimeMillis();
  • trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/WireframeMapRenderer.java

    r4087 r4327  
    2525import org.openstreetmap.josm.data.osm.RelationMember;
    2626import org.openstreetmap.josm.data.osm.Way;
     27import org.openstreetmap.josm.data.osm.WaySegment;
    2728import org.openstreetmap.josm.data.osm.visitor.Visitor;
    2829import org.openstreetmap.josm.gui.NavigatableComponent;
     
    168169            }
    169170        }
    170         drawVirtualNodes(data.searchWays(bbox));
     171        drawVirtualNodes(data.searchWays(bbox), data.getHighlightedVirtualNodes());
     172
     173        // draw highlighted way segments over the already drawn ways. Otherwise each
     174        // way would have to be checked if it contains a way segment to highlight when
     175        // in most of the cases there won't be more than one segment. Since the wireframe
     176        // renderer does not feature any transparency there should be no visual difference.
     177        for(final WaySegment wseg : data.getHighlightedWaySegments()) {
     178            drawSegment(nc.getPoint(wseg.getFirstNode()), nc.getPoint(wseg.getSecondNode()), highlightColor, false);
     179        }
     180        displaySegments();
    171181    }
    172182
     
    228238    }
    229239
    230     public void drawVirtualNodes(Collection<Way> ways) {
    231 
    232         if (virtualNodeSize != 0) {
    233             GeneralPath path = new GeneralPath();
    234             for (Way osm: ways){
    235                 if (osm.isUsable() && !osm.isDisabledAndHidden() && !osm.isDisabled()) {
    236                     visitVirtual(path, osm);
    237                 }
    238             }
    239             g.setColor(nodeColor);
    240             g.draw(path);
    241         }
     240    public void drawVirtualNodes(Collection<Way> ways, Collection<WaySegment> highlightVirtualNodes) {
     241        if (virtualNodeSize == 0)
     242            return;
     243        // print normal virtual nodes
     244        GeneralPath path = new GeneralPath();
     245        for (Way osm : ways) {
     246            if (osm.isUsable() && !osm.isDisabledAndHidden() && !osm.isDisabled()) {
     247                visitVirtual(path, osm);
     248            }
     249        }
     250        g.setColor(nodeColor);
     251        g.draw(path);
     252        // print highlighted virtual nodes. Since only the color changes, simply
     253        // drawing them over the existing ones works fine (at least in their current
     254        // simple style)
     255        path = new GeneralPath();
     256        for (WaySegment wseg: highlightVirtualNodes){
     257            if (wseg.way.isUsable() && !wseg.way.isDisabled()) {
     258                visitVirtual(path, wseg.toWay());
     259            }
     260        }
     261        g.setColor(highlightColor);
     262        g.draw(path);
    242263    }
    243264
Note: See TracChangeset for help on using the changeset viewer.