Changeset 2365 in josm for trunk/src/org


Ignore:
Timestamp:
2009-10-31T21:18:59+01:00 (14 years ago)
Author:
Gubaer
Message:

applied #3771: patch by bastiK: add nicer symbols for relation member connectedness

Location:
trunk/src/org/openstreetmap/josm/gui/dialogs/relation
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableLinkedCellRenderer.java

    r2311 r2365  
    1717    final static Image arrowUp = ImageProvider.get("dialogs", "arrowup").getImage();
    1818    final static Image arrowDown = ImageProvider.get("dialogs", "arrowdown").getImage();
     19    final static Image corners = ImageProvider.get("dialogs", "roundedcorners").getImage();
    1920    private WayConnectionType value = new WayConnectionType();
    2021
     
    3435    public void paintComponent(Graphics g) {
    3536        super.paintComponent(g);
    36         if (value == null || value.invalid) {
     37        if (value == null || !value.isValid()) {
    3738            return;
    3839        }
    3940
    40         Image image = null;
     41        Image arrow = null;
    4142        switch (value.direction) {
    4243            case 1:
    43                 image = arrowDown;
     44                arrow = arrowDown;
    4445                break;
    4546            case -1:
    46                 image = arrowUp;
     47                arrow = arrowUp;
    4748                break;
    4849        }
    4950
    5051        int ymax=this.getSize().height - 1;
     52        int xloop = 8;
    5153        int xoff = this.getSize().width / 2;
     54        if (value.isLoop) {
     55            xoff -= xloop / 2 - 1;
     56        }
    5257        int w = 2;
    5358        int p = 2 + w + 1;
     
    5560        int y2 = 0;
    5661
    57         if (image != null && (value.connectedToPrevious || value.connectedToNext)) {
    58             g.drawImage(image, xoff-3, ymax / 2 - 2, null);
     62
     63        if (value.linkPrev) {
     64            g.setColor(Color.black);
     65            g.fillRect(xoff - 1, 0, 3, 1);
     66            y1 = 0;
     67        } else {
     68            if (value.isLoop) {
     69                g.setColor(Color.black);
     70                y1 = 5;
     71                g.drawImage(corners,xoff,y1-3,xoff+3,y1, 0,0,3,3, new Color(0,0,0,0), null);
     72                g.drawImage(corners,xoff+xloop-2,y1-3,xoff+xloop+1,y1, 2,0,5,3, new Color(0,0,0,0), null);
     73                g.drawLine(xoff+3,y1-3,xoff+xloop-3,y1-3);
     74            }
     75            else {
     76                g.setColor(Color.red);
     77                g.drawRect(xoff-1, p - 1 - w, w, w);
     78                y1 = p;
     79            }
    5980        }
    6081
    61         if (value.connectedToPrevious) {
     82        if (value.linkNext) {
    6283            g.setColor(Color.black);
    63             g.fillRect(xoff - 2, 0, 5, 2);
    64             y1 = 0;
     84            g.fillRect(xoff - 1, ymax, 3, 1);
     85            y2 = ymax;
    6586        } else {
    66             g.setColor(Color.red);
    67             g.drawRect(xoff-1, p - 1 - w, w, w);
    68             y1 = p;
     87            if (value.isLoop) {
     88                g.setColor(Color.black);
     89                y2 = ymax - 5;
     90                g.fillRect(xoff-1, y2+2, 3, 3);
     91                g.drawLine(xoff, y2, xoff, y2+2);
     92                g.drawImage(corners,xoff+xloop-2,y2+1,xoff+xloop+1,y2+4, 2,2,5,5, new Color(0,0,0,0), null);
     93                g.drawLine(xoff+3-1,y2+3,xoff+xloop-3,y2+3);
     94            }
     95            else {
     96                g.setColor(Color.red);
     97                g.drawRect(xoff-1, ymax - p + 1, w, w);
     98                y2 = ymax - p;
     99            }
    69100        }
    70101
    71         if (value.connectedToNext) {
    72             g.setColor(Color.black);
    73             g.fillRect(xoff - 2, ymax - 1, 5, 2);
    74             y2 = ymax;
    75         } else {
    76             g.setColor(Color.red);
    77             g.drawRect(xoff-1, ymax - p + 1, w, w);
    78             y2 = ymax - p;
     102        if ((arrow != null) && (value.linkPrev || value.linkNext)) {
     103            g.drawImage(arrow, xoff-3, (y1 + y2) / 2 - 2, null);
    79104        }
     105
    80106        g.setColor(Color.black);
    81107        g.drawLine(xoff, y1, xoff, y2);
     108        if (value.isLoop) {
     109            g.drawLine(xoff+xloop, y1, xoff+xloop, y2);
     110        }
     111       
    82112    }
    83113}
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTableModel.java

    r2317 r2365  
    1616import javax.swing.ListSelectionModel;
    1717import javax.swing.table.AbstractTableModel;
     18import javax.swing.event.TableModelListener;
     19import javax.swing.event.TableModelEvent;
    1820
    1921import org.openstreetmap.josm.Main;
     
    2527import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    2628
    27 public class MemberTableModel extends AbstractTableModel {
    28 
     29public class MemberTableModel extends AbstractTableModel implements TableModelListener {
     30
     31    /**
     32     * data of the table model: The list of members and the cached WayConnectionType of each member.
     33     **/
    2934    private ArrayList<RelationMember> members;
     35    private ArrayList<WayConnectionType> connectionType = null;
     36   
    3037    private DefaultListSelectionModel listSelectionModel;
    3138    private CopyOnWriteArrayList<IMemberModelListener> listeners;
     
    3946        listeners = new CopyOnWriteArrayList<IMemberModelListener>();
    4047        this.layer = layer;
     48        addTableModelListener(this);
    4149    }
    4250
     
    99107    public boolean isCellEditable(int rowIndex, int columnIndex) {
    100108        return columnIndex == 0;
    101     }
    102 
    103     @Override
    104     public void setValueAt(Object value, int rowIndex, int columnIndex) {
    105         RelationMember member = members.get(rowIndex);
    106         RelationMember newMember = new RelationMember(value.toString(), member.getMember());
    107         members.remove(rowIndex);
    108         members.add(rowIndex, newMember);
    109109    }
    110110
     
    661661    }
    662662
    663     // simple version of code that was removed from GenericReleationEditor
    664     // no recursion and no forward/backward support
    665     // TODO: add back the number of linked elements
    666     // Returns +1 if member i and (i+1) are ways and could be combined without changing
    667     // the direction of one of them. If they are linked "head to head" or "tail to tail"
    668     // -1 is returned.
    669     // In all other cases the result is null.
    670     private Integer linked(int i) {
    671         // this method is aimed at finding out whether the
    672         // relation member is "linked" with the next, i.e. whether
    673         // (if both are ways) these ways are connected.
    674 
    675         Integer link = null;
    676         RelationMember m1 = members.get(i);
    677         RelationMember m2 = members.get((i + 1) % members.size());
    678         Way way1 = null;
    679         Way way2 = null;
    680 
    681         if (m1.isWay()) {
    682             way1 = m1.getWay();
    683         }
    684         if (m2.isWay()) {
    685             way2 = m2.getWay();
    686         }
    687         if ((way1 != null) && (way2 != null)) {
    688             Node way1first = way1.firstNode();
    689             Node way1last = way1.lastNode();
    690             Node way2first = way2.firstNode();
    691             Node way2last = way2.lastNode();
    692             if (way1first != null && way2first != null && (way1first == way2first)) {
    693                 link = -1;
    694             } else if (way1first != null && way2last != null && (way1first == way2last)) {
    695                 link = 1;
    696             } else if (way1last != null && way2first != null && (way1last == way2first)) {
    697                 link = 1;
    698             } else if (way1last != null && way2last != null && (way1last == way2last)) {
    699                 link = -1;
    700             }
    701         }
    702 
    703         return link;
     663/**
     664 * Determines the direction of way k with reference to the way ref_i.
     665 * The direction of way ref_i is ref_direction.
     666 *
     667 * ref_i is usually the predecessor of k.
     668 *
     669 * direction:
     670 * Let the relation be a route of oneway streets, and someone travels them in the given order.
     671 * Direction is 1 for if it is legel and -1 if it is illegal to do so for the given way.
     672 *
     673 * If the two ways are not properly linked the return value is 0.
     674 **/
     675    private int determineDirection(int ref_i,int ref_direction, int k) {
     676        if (ref_i < 0 || k < 0 || ref_i >= members.size() || k >= members.size()) {
     677            return 0;
     678        }
     679        if (ref_direction == 0) {
     680            return 0;
     681        }
     682       
     683        RelationMember m_ref = members.get(ref_i);
     684        RelationMember m = members.get(k);
     685        Way way_ref = null;
     686        Way way = null;
     687
     688        if (m_ref.isWay()) {
     689            way_ref = m_ref.getWay();
     690        }
     691        if (m.isWay()) {
     692            way = m.getWay();
     693        }
     694       
     695        if (way_ref == null || way == null) {
     696            return 0;
     697        }
     698       
     699        Node nRef = ref_direction > 0 ? way_ref.lastNode() : way_ref.firstNode();
     700        if (nRef == null) {
     701            return 0;
     702        }
     703       
     704        if (nRef == way.firstNode()) {
     705            return 1;
     706        }
     707        if (nRef == way.lastNode()) {
     708            return -1;
     709        }
     710        return 0;
    704711    }
    705712
    706713    private WayConnectionType wayConnection(int i) {
    707         RelationMember m = members.get(i);
    708         if (! m.isWay())
    709             return new WayConnectionType();
    710         Way w = m.getWay();
    711         if (w == null || w.incomplete)
    712             return new WayConnectionType();
    713 
    714         int ip = (i - 1 + members.size()) % members.size();
    715         Integer link_p = linked(ip);
    716         Integer link_n = linked(i);
    717         Integer dir = 1;
    718         // FIXME: It is somewhat stupid to loop here, but
    719         // there shouldn't be a performance problem in practice.
    720         for (int k = i - 1; k >= 0; --k) {
    721             Integer link = linked(k);
    722             if (link != null) {
    723                 dir *= link;
    724             } else {
    725                 break;
    726             }
    727         }
    728         return new WayConnectionType(link_p != null, link_n != null, dir);
     714        if (connectionType == null) {
     715            updateLinks();
     716        }
     717        return connectionType.get(i);
     718    }
     719
     720    public void tableChanged(TableModelEvent e) {
     721        connectionType = null;
     722    }
     723
     724    public void updateLinks() {
     725        connectionType = null;
     726        ArrayList<WayConnectionType> con = new ArrayList<WayConnectionType>();
     727
     728        for (int i=0; i<members.size(); ++i) con.add(null);
     729
     730        int firstGroupIdx=0;
     731        boolean resetFirstGoupIdx=false;
     732
     733        for (int i=0; i<members.size(); ++i) {
     734            if (resetFirstGoupIdx) {
     735                firstGroupIdx = i;
     736                resetFirstGoupIdx = false;
     737            }
     738
     739            RelationMember m = members.get(i);
     740            if (! m.isWay()) {
     741                con.set(i, new WayConnectionType());
     742                resetFirstGoupIdx = true;
     743                continue;
     744            }
     745
     746            Way w = m.getWay();
     747            if (w == null || w.incomplete) {
     748                con.set(i, new WayConnectionType());
     749                resetFirstGoupIdx = true;
     750                continue;
     751            }
     752
     753            boolean linkPrev = (i != firstGroupIdx);
     754            boolean linkNext;
     755            int dir;
     756            if (linkPrev) {
     757                dir = determineDirection(i-1, con.get(i-1).direction, i);
     758                linkNext = (determineDirection(i, dir, i+1) != 0);
     759            }
     760            else {
     761                dir = determineDirection(i, +1, i+1) != 0 ? +1 : 0;
     762                if (dir == 0) {
     763                    dir = determineDirection(i, -1, i+1) != 0 ? -1 : 0;
     764                }
     765                linkNext = (dir != 0);
     766            }
     767
     768            con.set(i, new WayConnectionType(linkPrev, linkNext, dir));
     769
     770            if (! linkNext) {
     771                boolean loop;
     772                if (i == firstGroupIdx) {
     773                    loop = determineDirection(i, 1, i) == 1;
     774                } else {
     775                    loop = determineDirection(i, dir, firstGroupIdx) == con.get(firstGroupIdx).direction;
     776                }
     777                if (loop) {
     778                    for (int j=firstGroupIdx; j <= i; ++j) {
     779                        con.get(j).isLoop = true;
     780                    }
     781                }
     782                resetFirstGoupIdx = true;
     783            }
     784        }
     785        connectionType = con;
    729786    }
    730787}
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/RelationNodeMap.java

    r1938 r2365  
    22
    33import java.util.ArrayList;
     4import java.util.TreeSet;
    45
    56import org.openstreetmap.josm.data.osm.Node;
     
    1415 */
    1516public class RelationNodeMap {
    16     private java.util.HashMap<Node, java.util.TreeSet<Integer>> points;
     17    /**
     18     * For each way endpoint, list all ways that share this node
     19     */
     20    private java.util.HashMap<Node, TreeSet<Integer>> points;
     21    /**
     22     * Singleton nodes
     23     */
    1724    private java.util.HashMap<Node, Integer> nodes;
    1825    private java.util.Vector<Integer> remaining;
    19     private ArrayList<RelationMember> members;
     26    /**
     27     * read only list
     28     */
     29    private final ArrayList<RelationMember> members;
    2030
    2131    RelationNodeMap(ArrayList<RelationMember> members) {
     
    2333
    2434        this.members = members;
    25         points = new java.util.HashMap<Node, java.util.TreeSet<Integer>>();
     35        points = new java.util.HashMap<Node, TreeSet<Integer>>();
    2636        nodes = new java.util.HashMap<Node, Integer>();
    2737        remaining = new java.util.Vector<Integer>();
     
    6373            if (w.lastNode() == w.firstNode())
    6474            {
    65                 nodes.put(w.firstNode(), Integer.valueOf(n));
     75                nodes.put(w.firstNode(), n);
    6676            }
    6777            else
    6878            {
    6979                if (!points.containsKey(w.firstNode())) {
    70                     points.put(w.firstNode(), new java.util.TreeSet<Integer>());
     80                    points.put(w.firstNode(), new TreeSet<Integer>());
    7181                }
    72                 points.get(w.firstNode()).add(Integer.valueOf(n));
     82                points.get(w.firstNode()).add(n);
    7383
    7484                if (!points.containsKey(w.lastNode())) {
    75                     points.put(w.lastNode(), new java.util.TreeSet<Integer>());
     85                    points.put(w.lastNode(), new TreeSet<Integer>());
    7686                }
    77                 points.get(w.lastNode()).add(Integer.valueOf(n));
     87                points.get(w.lastNode()).add(n);
    7888            }
    7989        } else if (m.isNode()) {
    8090            Node node = m.getNode();
    81             nodes.put(node, Integer.valueOf(n));
     91            nodes.put(node, n);
    8292        } else {
    83             remaining.add(Integer.valueOf(n));
     93            remaining.add(n);
    8494        }
    8595    }
     
    104114    }
    105115
    106     void move(int from, int to) {
    107         if (from != to) {
    108             RelationMember b = members.get(from);
    109             RelationMember a = members.get(to);
    110 
    111             remove(to, b);
    112             add(to, a);
    113         }
    114     }
    115 
    116116    // no node-mapped entries left
    117117    boolean isEmpty() {
     
    132132            nodes.remove(node);
    133133        } else if (!points.isEmpty()) {
    134             for (java.util.TreeSet<Integer> set : points.values()) {
     134            for (TreeSet<Integer> set : points.values()) {
    135135                if (!set.isEmpty()) {
    136136                    result = set.first();
  • trunk/src/org/openstreetmap/josm/gui/dialogs/relation/WayConnectionType.java

    r2311 r2365  
    66public class WayConnectionType {
    77
    8     public final boolean connectedToPrevious;
    9     public final boolean connectedToNext;
    10     /** Is 1 if way has the same direction as the first way in the set of connected ways. Else it is (-1) */
     8    /** True, if the corresponding primitive is not a way or the way is incomplete */
     9    private final boolean invalid;
     10
     11    /** True, if linked to the previous / next member.  */
     12    public final boolean linkPrev;
     13    public final boolean linkNext;
     14
     15    /**
     16     * direction is +1 if the first node of this way is connected to the previous way
     17     * and / or the last node of this way is connected to the next way.
     18     * direction is -1 if it is the other way around.
     19     * If this way is neither connected to the previous nor to the next way, then
     20     * direction has the value 0.
     21     */
    1122    public final int direction;
    12     /** The WayConnectionType is invalid, if the corresponding primitive is not a way or the way is incomplete */
    13     public final boolean invalid;
    1423
    15     public WayConnectionType(boolean connectedToPrevious, boolean connectedToNext, int direction) {
    16         this.connectedToPrevious = connectedToPrevious;
    17         this.connectedToNext = connectedToNext;
     24    /** True, if the element is part of a closed loop of ways. */
     25    public boolean isLoop;
     26
     27    public WayConnectionType(boolean linkPrev, boolean linkNext, int direction) {
     28        this.linkPrev = linkPrev;
     29        this.linkNext = linkNext;
     30        this.isLoop = false;
    1831        this.direction = direction;
    1932        invalid = false;
    2033    }
    2134
     35    /** construct invalid instance */
    2236    public WayConnectionType() {
    23         connectedToPrevious = false;
    24         connectedToNext = false;
    25         direction = 1;
     37        this.linkPrev = false;
     38        this.linkNext = false;
     39        this.isLoop = false;
     40        this.direction = 0;
    2641        invalid = true;
    2742    }
     43   
     44    public boolean isValid() {
     45        return !invalid;   
     46    }
    2847
    29 //    @Override
    30 //    public String toString() {
    31 //        return ...
    32 //    }
     48    @Override
     49    public String toString() {
     50        return "[P "+linkPrev+" ;N "+linkNext+" ;D "+direction+" ;L "+isLoop+"]";
     51    }
    3352
    3453    public String getToolTip() {
    35         if (invalid) {
     54        if (!isValid()) {
    3655            return "";
    3756        }
    38         else if (connectedToPrevious && connectedToNext) {
     57        else if (linkPrev && linkNext) {
    3958            return tr("way is connected");
    4059        }
    41         else if (connectedToPrevious) {
     60        else if (linkPrev) {
    4261            return tr("way is connected to previous relation member");
    4362        }
    44         else if (connectedToNext) {
     63        else if (linkNext) {
    4564            return tr("way is connected to next relation member");
    4665        }
    4766        else {
    4867            return tr("way is not connected to previous or next relation member");
    49         }
     68        }//FIXME: isLoop & direction
    5069    }
    5170}
Note: See TracChangeset for help on using the changeset viewer.