Changeset 2741 in josm for trunk/src/org/openstreetmap


Ignore:
Timestamp:
2010-01-05T21:55:49+01:00 (15 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.