Changeset 2741 in josm


Ignore:
Timestamp:
Jan 5, 2010 9:55:49 PM (3 years ago)
Author:
jttt
Message:

Fixed #4261 Selection information is not updated after undo/redo, minor optimalizations

Location:
trunk/src/org/openstreetmap/josm
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/osm/Way.java

    r2678 r2741  
    216216        WayData data = new WayData(); 
    217217        saveCommonAttributes(data); 
    218         for (Node node:getNodes()) { 
     218        for (Node node:nodes) { 
    219219            data.getNodes().add(node.getUniqueId()); 
    220220        } 
     
    387387 
    388388    public boolean hasIncompleteNodes() { 
    389         for (Node node:getNodes()) { 
     389        for (Node node:nodes) { 
    390390            if (node.isIncomplete()) 
    391391                return true; 
  • trunk/src/org/openstreetmap/josm/data/osm/event/DataChangedEvent.java

    r2711 r2741  
    1010public class DataChangedEvent extends AbstractDatasetChangedEvent { 
    1111 
     12    private final List<AbstractDatasetChangedEvent> events; 
     13 
     14    public DataChangedEvent(DataSet dataSet, List<AbstractDatasetChangedEvent> events) { 
     15        super(dataSet); 
     16        this.events = events; 
     17    } 
     18 
    1219    public DataChangedEvent(DataSet dataSet) { 
    13         super(dataSet); 
     20        this(dataSet, null); 
    1421    } 
    1522 
     
    3239    } 
    3340 
     41    /** 
     42     *  
     43     * @return List of events that caused this DataChangedEvent. Might be null 
     44     */ 
     45    public List<AbstractDatasetChangedEvent> getEvents() { 
     46        return events; 
     47    } 
     48 
    3449} 
  • trunk/src/org/openstreetmap/josm/data/osm/event/DatasetEventManager.java

    r2711 r2741  
    22package org.openstreetmap.josm.data.osm.event; 
    33 
     4import java.util.ArrayList; 
     5import java.util.Arrays; 
     6import java.util.List; 
    47import java.util.Queue; 
    58import java.util.concurrent.CopyOnWriteArrayList; 
     
    811import javax.swing.SwingUtilities; 
    912 
     13import org.openstreetmap.josm.data.osm.DataSet; 
    1014import org.openstreetmap.josm.data.osm.event.DataSetListenerAdapter.Listener; 
    1115import org.openstreetmap.josm.gui.MapView; 
     
    2529    private static final DatasetEventManager instance = new DatasetEventManager(); 
    2630 
     31    public enum FireMode { 
     32        IMMEDIATELY, 
     33        IN_EDT, 
     34        /** 
     35         * Fire in event dispatch thread. If more than one event arrived when event queue is checked, merged them to 
     36         * one event 
     37         */ 
     38        IN_EDT_CONSOLIDATED} 
     39 
     40    private static class ListenerInfo { 
     41        final DataSetListener listener; 
     42        final boolean consolidate; 
     43 
     44        public ListenerInfo(DataSetListener listener, boolean consolidate) { 
     45            this.listener = listener; 
     46            this.consolidate = consolidate; 
     47        } 
     48 
     49        @Override 
     50        public int hashCode() { 
     51            return listener.hashCode(); 
     52        } 
     53 
     54        @Override 
     55        public boolean equals(Object o) { 
     56            return o instanceof ListenerInfo && ((ListenerInfo)o).listener == listener; 
     57        } 
     58    } 
     59 
    2760    public static DatasetEventManager getInstance() { 
    2861        return instance; 
     
    3063 
    3164    private final Queue<AbstractDatasetChangedEvent> eventsInEDT = new LinkedBlockingQueue<AbstractDatasetChangedEvent>(); 
    32     private final CopyOnWriteArrayList<DataSetListener> inEDTListeners = new CopyOnWriteArrayList<DataSetListener>(); 
    33     private final CopyOnWriteArrayList<DataSetListener> normalListeners = new CopyOnWriteArrayList<DataSetListener>(); 
     65    private final CopyOnWriteArrayList<ListenerInfo> inEDTListeners = new CopyOnWriteArrayList<ListenerInfo>(); 
     66    private final CopyOnWriteArrayList<ListenerInfo> normalListeners = new CopyOnWriteArrayList<ListenerInfo>(); 
    3467    private final DataSetListener myListener = new DataSetListenerAdapter(this); 
    3568 
     
    4477     * instead of thread that caused the dataset change 
    4578     */ 
    46     public void addDatasetListener(DataSetListener listener, boolean fireInEDT) { 
    47         if (fireInEDT) { 
    48             inEDTListeners.addIfAbsent(listener); 
     79    public void addDatasetListener(DataSetListener listener, FireMode fireMode) { 
     80        if (fireMode == FireMode.IN_EDT || fireMode == FireMode.IN_EDT_CONSOLIDATED) { 
     81            inEDTListeners.addIfAbsent(new ListenerInfo(listener, fireMode == FireMode.IN_EDT_CONSOLIDATED)); 
    4982        } else { 
    50             normalListeners.addIfAbsent(listener); 
     83            normalListeners.addIfAbsent(new ListenerInfo(listener, false)); 
    5184        } 
    5285    } 
    5386 
    5487    public void removeDatasetListener(DataSetListener listener) { 
    55         inEDTListeners.remove(listener); 
    56         normalListeners.remove(listener); 
     88        ListenerInfo searchListener = new ListenerInfo(listener, false); 
     89        inEDTListeners.remove(searchListener); 
     90        normalListeners.remove(searchListener); 
    5791    } 
    5892 
     
    70104    } 
    71105 
     106    private void fireEvents(List<ListenerInfo> listeners, AbstractDatasetChangedEvent event) { 
     107        for (ListenerInfo listener: listeners) { 
     108            if (!listener.consolidate) { 
     109                event.fire(listener.listener); 
     110            } 
     111        } 
     112    } 
     113 
     114    private void fireConsolidatedEvents(List<ListenerInfo> listeners, AbstractDatasetChangedEvent event) { 
     115        for (ListenerInfo listener: listeners) { 
     116            if (listener.consolidate) { 
     117                event.fire(listener.listener); 
     118            } 
     119        } 
     120    } 
     121 
    72122    public void processDatasetEvent(AbstractDatasetChangedEvent event) { 
    73         for (DataSetListener listener: normalListeners) { 
    74             event.fire(listener); 
    75         } 
     123        fireEvents(normalListeners, event); 
    76124        eventsInEDT.add(event); 
    77125        SwingUtilities.invokeLater(edtRunnable); 
     
    80128    private final Runnable edtRunnable = new Runnable() { 
    81129        public void run() { 
    82             AbstractDatasetChangedEvent event = null; 
    83             while ((event = eventsInEDT.poll()) != null) { 
    84                 for (DataSetListener listener: inEDTListeners) { 
    85                     event.fire(listener); 
     130            while (!eventsInEDT.isEmpty()) { 
     131                List<AbstractDatasetChangedEvent> events = new ArrayList<AbstractDatasetChangedEvent>(); 
     132                events.addAll(eventsInEDT); 
     133 
     134                DataSet dataSet = null; 
     135                AbstractDatasetChangedEvent consolidatedEvent = null; 
     136                AbstractDatasetChangedEvent event = null; 
     137 
     138                while ((event = eventsInEDT.poll()) != null) { 
     139                    fireEvents(inEDTListeners, event); 
     140 
     141                    // DataSet changed - fire consolidated event early 
     142                    if (consolidatedEvent != null && dataSet != event.getDataset()) { 
     143                        fireConsolidatedEvents(inEDTListeners, consolidatedEvent); 
     144                        dataSet = event.getDataset(); 
     145                        consolidatedEvent = null; 
     146                    } 
     147 
     148                    // Build consolidated event 
     149                    if (consolidatedEvent == null) { 
     150                        consolidatedEvent = event; 
     151                        dataSet = event.getDataset(); 
     152                    } else if (consolidatedEvent instanceof DataChangedEvent) { 
     153                        ((DataChangedEvent)consolidatedEvent).getEvents().add(event); 
     154                    } else { 
     155                        consolidatedEvent = new DataChangedEvent(dataSet, 
     156                                new ArrayList<AbstractDatasetChangedEvent>(Arrays.asList(consolidatedEvent))); 
     157                    } 
    86158                } 
     159 
     160                // Fire consolidated event 
     161                fireConsolidatedEvents(inEDTListeners, consolidatedEvent); 
    87162            } 
    88163        } 
  • trunk/src/org/openstreetmap/josm/gui/dialogs/ChangesetDialog.java

    r2711 r2741  
    2626import javax.swing.JPopupMenu; 
    2727import javax.swing.JScrollPane; 
    28 import javax.swing.JToolBar; 
    2928import javax.swing.ListSelectionModel; 
    3029import javax.swing.SwingUtilities; 
     
    3938import org.openstreetmap.josm.data.osm.OsmPrimitive; 
    4039import org.openstreetmap.josm.data.osm.event.DatasetEventManager; 
     40import org.openstreetmap.josm.data.osm.event.DatasetEventManager.FireMode; 
    4141import org.openstreetmap.josm.gui.MapFrame; 
    4242import org.openstreetmap.josm.gui.MapView; 
     
    154154    public void showNotify() { 
    155155        registerAsListener(); 
    156         DatasetEventManager.getInstance().addDatasetListener(inActiveDataLayerModel, true); 
     156        DatasetEventManager.getInstance().addDatasetListener(inActiveDataLayerModel, FireMode.IN_EDT); 
    157157    } 
    158158 
  • trunk/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java

    r2710 r2741  
    2222import javax.swing.DefaultListSelectionModel; 
    2323import javax.swing.JList; 
     24import javax.swing.JPanel; 
    2425import javax.swing.JPopupMenu; 
    2526import javax.swing.JScrollPane; 
    26 import javax.swing.JPanel; 
    2727import javax.swing.KeyStroke; 
    2828import javax.swing.ListSelectionModel; 
     
    4646import org.openstreetmap.josm.data.osm.event.TagsChangedEvent; 
    4747import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent; 
     48import org.openstreetmap.josm.data.osm.event.DatasetEventManager.FireMode; 
    4849import org.openstreetmap.josm.gui.DefaultNameFormatter; 
    4950import org.openstreetmap.josm.gui.MapView; 
     
    143144        MapView.addLayerChangeListener(newAction); 
    144145        newAction.updateEnabledState(); 
    145         DatasetEventManager.getInstance().addDatasetListener(this, true); 
     146        DatasetEventManager.getInstance().addDatasetListener(this, FireMode.IN_EDT); 
    146147        dataChanged(null); 
    147148    } 
     
    518519        } 
    519520 
    520         public synchronized void sort() { 
     521        public void sort() { 
    521522            Collections.sort( 
    522523                    relations, 
     
    535536        } 
    536537 
    537         public synchronized void setRelations(Collection<Relation> relations) { 
     538        public void setRelations(Collection<Relation> relations) { 
    538539            List<Relation> sel =  getSelectedRelations(); 
    539540            this.relations.clear(); 
     
    561562         * ways, and relations. 
    562563         */ 
    563         public synchronized void addRelations(Collection<? extends OsmPrimitive> addedPrimitives) { 
     564        public void addRelations(Collection<? extends OsmPrimitive> addedPrimitives) { 
    564565            boolean added = false; 
    565566            for (OsmPrimitive p: addedPrimitives) { 
     
    591592         *   and relations 
    592593         */ 
    593         public synchronized void removeRelations(Collection<? extends OsmPrimitive> removedPrimitives) { 
     594        public void removeRelations(Collection<? extends OsmPrimitive> removedPrimitives) { 
    594595            if (removedPrimitives == null) return; 
    595596            // extract the removed relations 
     
    664665         * @return sel the list of selected relations 
    665666         */ 
    666         public synchronized void setSelectedRelations(List<Relation> sel) { 
     667        public void setSelectedRelations(List<Relation> sel) { 
    667668            selectionModel.clearSelection(); 
    668669            if (sel == null || sel.isEmpty()) 
  • trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java

    r2723 r2741  
    1111import java.awt.Font; 
    1212import java.awt.GridBagLayout; 
    13 import java.awt.GridLayout; 
    1413import java.awt.Point; 
    1514import java.awt.event.ActionEvent; 
     
    6564import org.openstreetmap.josm.data.osm.RelationMember; 
    6665import org.openstreetmap.josm.data.osm.Way; 
     66import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent; 
     67import org.openstreetmap.josm.data.osm.event.DataSetListenerAdapter; 
    6768import org.openstreetmap.josm.data.osm.event.DatasetEventManager; 
     69import org.openstreetmap.josm.data.osm.event.DatasetEventManager.FireMode; 
    6870import org.openstreetmap.josm.gui.DefaultNameFormatter; 
    6971import org.openstreetmap.josm.gui.ExtendedDialog; 
     
    99101 * @author imi 
    100102 */ 
    101 public class PropertiesDialog extends ToggleDialog implements SelectionChangedListener, MapView.EditLayerChangeListener { 
     103public class PropertiesDialog extends ToggleDialog implements SelectionChangedListener, MapView.EditLayerChangeListener, DataSetListenerAdapter.Listener { 
    102104    /** 
    103105     * Watches for double clicks and from editing or new property, depending on the 
     
    144146    private final ListOfUsedTags listOfUsedTags = new ListOfUsedTags(); 
    145147 
     148    private DataSetListenerAdapter dataChangedAdapter = new DataSetListenerAdapter(this); 
     149 
    146150    @Override 
    147151    public void showNotify() { 
    148         DatasetEventManager.getInstance().addDatasetListener(listOfUsedTags, false); 
     152        DatasetEventManager.getInstance().addDatasetListener(listOfUsedTags, FireMode.IMMEDIATELY); 
     153        DatasetEventManager.getInstance().addDatasetListener(dataChangedAdapter, FireMode.IN_EDT_CONSOLIDATED); 
    149154        listOfUsedTags.rebuildNecessary(); 
    150155        DataSet.selListeners.add(this); 
     
    155160    public void hideNotify() { 
    156161        DatasetEventManager.getInstance().removeDatasetListener(listOfUsedTags); 
     162        DatasetEventManager.getInstance().removeDatasetListener(dataChangedAdapter); 
    157163        DataSet.selListeners.remove(this); 
    158164    } 
     
    310316     * @param row 
    311317     */ 
     318    @SuppressWarnings("unchecked") 
    312319    void membershipEdit(int row) { 
    313320        Relation relation = (Relation)membershipData.getValueAt(row, 0); 
     
    455462                    if (value instanceof String) { 
    456463                        str = (String) value; 
    457                     } else if (value instanceof Map) { 
    458                         Map v = (Map) value; 
     464                    } else if (value instanceof Map<?, ?>) { 
     465                        Map<?, ?> v = (Map<?, ?>) value; 
    459466                        if (v.size() != 1) { 
    460467                            str=tr("<different>"); 
    461468                            c.setFont(c.getFont().deriveFont(Font.ITALIC)); 
    462469                        } else { 
    463                             final Map.Entry entry = (Map.Entry) v.entrySet().iterator().next(); 
     470                            final Map.Entry<?, ?> entry = v.entrySet().iterator().next(); 
    464471                            str = (String) entry.getKey(); 
    465472                        } 
     
    810817    } 
    811818 
     819    public void processDatasetEvent(AbstractDatasetChangedEvent event) { 
     820        updateSelection(); 
     821    } 
     822 
    812823    class DeleteAction extends AbstractAction implements ListSelectionListener { 
    813824 
     
    922933    } 
    923934 
    924     class SelectRelationAction extends AbstractAction { 
     935    static class SelectRelationAction extends AbstractAction { 
    925936        boolean selectionmode; 
    926937        Relation relation; 
     
    929940            relation = r; 
    930941            if(select) { 
    931               putValue(NAME, tr("Select relation")); 
    932               putValue(SHORT_DESCRIPTION, tr("Select relation in main selection.")); 
     942                putValue(NAME, tr("Select relation")); 
     943                putValue(SHORT_DESCRIPTION, tr("Select relation in main selection.")); 
    933944            } else { 
    934               putValue(NAME, tr("Select in relation list")); 
    935               putValue(SHORT_DESCRIPTION, tr("Select relation in relation list.")); 
     945                putValue(NAME, tr("Select in relation list")); 
     946                putValue(SHORT_DESCRIPTION, tr("Select relation in relation list.")); 
    936947            } 
    937948        } 
    938949 
    939950        public void actionPerformed(ActionEvent e) { 
    940             if(selectionmode) 
     951            if(selectionmode) { 
    941952                Main.map.mapView.getEditLayer().data.setSelected(relation); 
    942             else 
     953            } else { 
    943954                Main.map.relationListDialog.selectRelation(relation); 
     955            } 
    944956        } 
    945957    } 
  • trunk/src/org/openstreetmap/josm/tools/CopyList.java

    r2512 r2741  
    2222 
    2323import java.util.AbstractList; 
     24import java.util.ConcurrentModificationException; 
     25import java.util.Iterator; 
     26import java.util.NoSuchElementException; 
    2427import java.util.RandomAccess; 
    2528 
     
    3235 * @author nenik 
    3336 */ 
    34 public class CopyList<E> extends AbstractList<E> implements RandomAccess, Cloneable { 
     37public final class CopyList<E> extends AbstractList<E> implements RandomAccess, Cloneable { 
    3538    private E[] array; 
    3639    private int size; 
     
    107110 
    108111    public @Override void clear() { 
    109     modCount++; 
     112        modCount++; 
    110113 
    111114        // clean up the array 
    112         while (size > 0) array[--size] = null; 
     115        while (size > 0) { 
     116            array[--size] = null; 
     117        } 
    113118    } 
    114119 
     
    125130 
    126131    private void rangeCheck(int index) { 
    127     if (index >= size || index < 0) throw new IndexOutOfBoundsException(); 
     132        if (index >= size || index < 0) throw new IndexOutOfBoundsException(); 
    128133    } 
    129134 
     
    145150            System.arraycopy(old, 0, array, 0, size); 
    146151            pristine = false; 
    147     } 
    148     } 
     152        } 
     153    } 
     154 
     155    @Override 
     156    public Iterator<E> iterator() { 
     157        return new Itr(); 
     158    } 
     159 
     160    private class Itr implements Iterator<E> { 
     161        /** 
     162         * Index of element to be returned by subsequent call to next. 
     163         */ 
     164        int cursor = 0; 
     165 
     166        /** 
     167         * Index of element returned by most recent call to next or 
     168         * previous.  Reset to -1 if this element is deleted by a call 
     169         * to remove. 
     170         */ 
     171        int lastRet = -1; 
     172 
     173        /** 
     174         * The modCount value that the iterator believes that the backing 
     175         * List should have.  If this expectation is violated, the iterator 
     176         * has detected concurrent modification. 
     177         */ 
     178        int expectedModCount = modCount; 
     179 
     180        public boolean hasNext() { 
     181            return cursor != size; 
     182        } 
     183 
     184        public E next() { 
     185            checkForComodification(); 
     186            try { 
     187                E next = array[cursor]; 
     188                lastRet = cursor++; 
     189                return next; 
     190            } catch (IndexOutOfBoundsException e) { 
     191                checkForComodification(); 
     192                throw new NoSuchElementException(); 
     193            } 
     194        } 
     195 
     196        public void remove() { 
     197            if (lastRet == -1) 
     198                throw new IllegalStateException(); 
     199            checkForComodification(); 
     200 
     201            try { 
     202                CopyList.this.remove(lastRet); 
     203                if (lastRet < cursor) { 
     204                    cursor--; 
     205                } 
     206                lastRet = -1; 
     207                expectedModCount = modCount; 
     208            } catch (IndexOutOfBoundsException e) { 
     209                throw new ConcurrentModificationException(); 
     210            } 
     211        } 
     212 
     213        final void checkForComodification() { 
     214            if (modCount != expectedModCount) 
     215                throw new ConcurrentModificationException(); 
     216        } 
     217    } 
     218 
    149219} 
Note: See TracChangeset for help on using the changeset viewer.