Ticket #12409: RecentRelationsAction.patch

File RecentRelationsAction.patch, 13.4 KB (added by kolesar, 10 years ago)
  • src/org/openstreetmap/josm/actions/CreateMultipolygonAction.java

    diff --git a/src/org/openstreetmap/josm/actions/CreateMultipolygonAction.java b/src/org/openstreetmap/josm/actions/CreateMultipolygonAction.java
    index 4f7c5aa..9d2ca14 100644
    a b public class CreateMultipolygonAction extends JosmAction {  
    120120
    121121                                editor.setModal(true);
    122122                                editor.setVisible(true);
     123                            } else {
     124                                Main.main.getEditLayer().setRecentRelation(relation);
    123125                            }
    124126                        }
    125127                    });
  • new file src/org/openstreetmap/josm/actions/relation/RecentRelationsAction.java

    diff --git a/src/org/openstreetmap/josm/actions/relation/RecentRelationsAction.java b/src/org/openstreetmap/josm/actions/relation/RecentRelationsAction.java
    new file mode 100644
    index 0000000..382cf71
    - +  
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.actions.relation;
     3
     4import static org.openstreetmap.josm.tools.I18n.tr;
     5import static org.openstreetmap.josm.tools.I18n.trn;
     6
     7import java.awt.Component;
     8import java.awt.event.ActionEvent;
     9import java.awt.event.ActionListener;
     10import java.awt.event.KeyEvent;
     11import java.awt.Rectangle;
     12import java.util.Collection;
     13import java.util.List;
     14
     15import javax.swing.AbstractAction;
     16import javax.swing.JMenuItem;
     17import javax.swing.JPopupMenu;
     18import javax.swing.KeyStroke;
     19import javax.swing.plaf.basic.BasicArrowButton;
     20
     21import org.openstreetmap.josm.Main;
     22import org.openstreetmap.josm.data.osm.Relation;
     23import org.openstreetmap.josm.gui.layer.Layer;
     24import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     25import org.openstreetmap.josm.gui.layer.OsmDataLayer.CommandQueueListener;
     26import org.openstreetmap.josm.gui.DefaultNameFormatter;
     27import org.openstreetmap.josm.gui.MapView;
     28import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
     29import org.openstreetmap.josm.gui.SideButton;
     30import org.openstreetmap.josm.tools.Shortcut;
     31
     32/**
     33 * Action for accessing recent relations.
     34 */
     35public class RecentRelationsAction implements ActionListener, CommandQueueListener, LayerChangeListener{
     36
     37    private SideButton editButton;
     38    private BasicArrowButton arrow;
     39    private Shortcut shortcut;
     40
     41    /**
     42     * Constructs a new <code>RecentRelationsAction</code>.
     43     */
     44    public RecentRelationsAction(SideButton editButton) {
     45        this.editButton = editButton;
     46        arrow = editButton.createArrow(this);
     47        arrow.setToolTipText(tr("List of recent relations"));
     48        Main.main.undoRedo.addCommandQueueListener(this);
     49        MapView.addLayerChangeListener(this);
     50        enableArrow();
     51        shortcut = Shortcut.registerShortcut(
     52            "relationeditor:editrecentrelation",
     53            tr("Relation Editor: {0}", tr("Open recent relation")),
     54            KeyEvent.VK_ESCAPE,
     55            Shortcut.SHIFT
     56        );
     57        Main.registerActionShortcut(new AbstractAction() {
     58            @Override
     59            public void actionPerformed(ActionEvent e) {
     60                EditRelationAction.launchEditor(getLastRelation());
     61            }
     62        }, shortcut);
     63    }
     64
     65    public void enableArrow() {
     66        arrow.setEnabled(getLastRelation() != null);
     67    }
     68
     69    public static Relation getLastRelation() {
     70        List<Relation> recentRelations = getRecentRelationsOnActiveLayer();
     71        if (recentRelations == null || recentRelations.isEmpty()) return null;
     72        for (Relation relation: recentRelations) {
     73            if (!isRelationListable(relation)) continue;
     74            return relation;
     75        }
     76        return null;
     77    }
     78
     79    public static boolean isRelationListable(Relation relation) {
     80        return relation != null &&
     81            !relation.isDeleted() &&
     82            Main.main.getCurrentDataSet().containsRelation(relation);
     83    }
     84
     85    @Override
     86    public void actionPerformed(ActionEvent e) {
     87        RecentRelationsPopupMenu.launch(editButton, shortcut.getKeyStroke());
     88    }
     89
     90    @Override
     91    public void commandChanged(int queueSize, int redoSize) {
     92        enableArrow();
     93    }
     94
     95    @Override
     96    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
     97        enableArrow();
     98    }
     99
     100    @Override
     101    public void layerAdded(Layer newLayer) {
     102        enableArrow();
     103    }
     104
     105    @Override
     106    public void layerRemoved(Layer oldLayer) {
     107        enableArrow();
     108    }
     109
     110    public static List<Relation> getRecentRelationsOnActiveLayer() {
     111        if (Main.map == null || Main.map.mapView == null) return null;
     112        Layer activeLayer = Main.map.mapView.getActiveLayer();
     113        if (!(activeLayer instanceof OsmDataLayer)) {
     114            return null;
     115        } else {
     116            return ((OsmDataLayer) activeLayer).getRecentRelations();
     117        }
     118    }
     119
     120    protected static class RecentRelationsPopupMenu extends JPopupMenu {
     121        public static void launch(Component parent, KeyStroke keystroke) {
     122            List<Relation> recentRelations = getRecentRelationsOnActiveLayer();
     123            JPopupMenu menu = new RecentRelationsPopupMenu(recentRelations, keystroke);
     124            Rectangle r = parent.getBounds();
     125            menu.show(parent, r.x, r.y + r.height);
     126        }
     127
     128        /**
     129         * Constructs a new {@code SearchPopupMenu}.
     130         */
     131        public RecentRelationsPopupMenu(List<Relation> recentRelations, KeyStroke keystroke) {
     132            boolean first = true;
     133            for (Relation relation: recentRelations) {
     134                if (!isRelationListable(relation)) continue;
     135                JMenuItem menuItem = new RecentRelationsMenuItem(relation);
     136                if (first) {
     137                    menuItem.setAccelerator(keystroke);
     138                    first = false;
     139                }
     140                add(menuItem);
     141            }
     142        }
     143    }
     144
     145    /**
     146     * A specialized {@link JMenuItem} for presenting one entry of the relation history
     147     */
     148    protected static class RecentRelationsMenuItem extends JMenuItem implements ActionListener {
     149        protected final transient Relation relation;
     150
     151        public RecentRelationsMenuItem(Relation relation) {
     152            super(relation.getDisplayName(DefaultNameFormatter.getInstance()));
     153            this.relation = relation;
     154            addActionListener(this);
     155        }
     156
     157        @Override
     158        public void actionPerformed(ActionEvent e) {
     159            EditRelationAction.launchEditor(relation);
     160        }
     161    }
     162}
  • src/org/openstreetmap/josm/gui/SideButton.java

    diff --git a/src/org/openstreetmap/josm/gui/SideButton.java b/src/org/openstreetmap/josm/gui/SideButton.java
    index 88539ba..b1705b0 100644
    a b public class SideButton extends JButton implements Destroyable {  
    8989        setMargin(new Insets(0, 0, 0, 0));
    9090    }
    9191
    92     public void createArrow(ActionListener listener) {
     92    public BasicArrowButton createArrow(ActionListener listener) {
    9393        setMargin(new Insets(0, 0, 0, 0));
    9494        BasicArrowButton arrowButton = new BasicArrowButton(SwingConstants.SOUTH, null, null, Color.BLACK, null);
    9595        arrowButton.setBorder(BorderFactory.createEmptyBorder());
    9696        add(arrowButton, BorderLayout.EAST);
    9797        arrowButton.addActionListener(listener);
     98        return arrowButton;
    9899    }
    99100
    100101    @Override
  • src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java

    diff --git a/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java b/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java
    index 53cb4da..c7c3439 100644
    a b import org.openstreetmap.josm.actions.relation.DownloadMembersAction;  
    4141import org.openstreetmap.josm.actions.relation.DownloadSelectedIncompleteMembersAction;
    4242import org.openstreetmap.josm.actions.relation.DuplicateRelationAction;
    4343import org.openstreetmap.josm.actions.relation.EditRelationAction;
     44import org.openstreetmap.josm.actions.relation.RecentRelationsAction;
    4445import org.openstreetmap.josm.actions.relation.SelectMembersAction;
    4546import org.openstreetmap.josm.actions.relation.SelectRelationAction;
    4647import org.openstreetmap.josm.actions.search.SearchCompiler;
    public class RelationListDialog extends ToggleDialog  
    122123
    123124    private final transient HighlightHelper highlightHelper = new HighlightHelper();
    124125    private final boolean highlightEnabled = Main.pref.getBoolean("draw.target-highlight", true);
     126    private RecentRelationsAction recentRelationsAction;
    125127
    126128    /**
    127129     * Constructs <code>RelationListDialog</code>
    public class RelationListDialog extends ToggleDialog  
    168170        JPanel pane = new JPanel(new BorderLayout());
    169171        pane.add(filter, BorderLayout.NORTH);
    170172        pane.add(new JScrollPane(displaylist), BorderLayout.CENTER);
     173
     174        SideButton editButton = new SideButton(editAction, false);
     175        recentRelationsAction = new RecentRelationsAction(editButton);
     176
    171177        createLayout(pane, false, Arrays.asList(new SideButton[]{
    172178                new SideButton(newAction, false),
    173                 new SideButton(editAction, false),
     179                editButton,
    174180                new SideButton(duplicateAction, false),
    175181                new SideButton(deleteRelationsAction, false),
    176182                new SideButton(selectRelationAction, false)
    public class RelationListDialog extends ToggleDialog  
    192198        updateActionsRelationLists();
    193199    }
    194200
     201    public void enableRecentRelations() {
     202        recentRelationsAction.enableArrow();
     203    }
     204
    195205    // inform all actions about list of relations they need
    196206    private void updateActionsRelationLists() {
    197207        List<Relation> sel = model.getSelectedRelations();
  • src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditor.java

    diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditor.java b/src/org/openstreetmap/josm/gui/dialogs/relation/RelationEditor.java
    index 8c04d22..5514ba3 100644
    a b public abstract class RelationEditor extends ExtendedDialog implements RelationA  
    6666        CheckParameterUtil.ensureParameterNotNull(layer, "layer");
    6767        this.layer = layer;
    6868        setRelation(relation);
     69        layer.removeRecentRelation(relation);
    6970    }
    7071
    7172    /**
    public abstract class RelationEditor extends ExtendedDialog implements RelationA  
    189190    public final void removePropertyChangeListener(PropertyChangeListener listener) {
    190191        this.support.removePropertyChangeListener(listener);
    191192    }
     193
     194    @Override
     195    public void dispose() {
     196        layer.setRecentRelation(relation);
     197        super.dispose();
     198    }
    192199}
  • src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java

    diff --git a/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java b/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
    index 7a22bdc..ef28d98 100644
    a b import java.util.Collection;  
    2424import java.util.Collections;
    2525import java.util.HashMap;
    2626import java.util.HashSet;
     27import java.util.LinkedHashMap;
     28import java.util.LinkedList;
    2729import java.util.List;
    2830import java.util.Map;
    2931import java.util.Set;
    import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;  
    7476import org.openstreetmap.josm.data.osm.visitor.paint.MapRendererFactory;
    7577import org.openstreetmap.josm.data.osm.visitor.paint.Rendering;
    7678import org.openstreetmap.josm.data.osm.visitor.paint.relations.MultipolygonCache;
     79import org.openstreetmap.josm.data.preferences.IntegerProperty;
    7780import org.openstreetmap.josm.data.projection.Projection;
    7881import org.openstreetmap.josm.data.validation.TestError;
    7982import org.openstreetmap.josm.gui.ExtendedDialog;
    public class OsmDataLayer extends AbstractModifiableLayer implements Listener, S  
    121124     */
    122125    public final List<TestError> validationErrors = new ArrayList<>();
    123126
     127    public static final int DEFAULT_RECENT_RELATIONS_NUMBER = 20;
     128    public static final IntegerProperty PROPERTY_RECENT_RELATIONS_NUMBER = new IntegerProperty("properties.last-closed-relations-size",
     129            DEFAULT_RECENT_RELATIONS_NUMBER);
     130
     131    /** List of recent relations */
     132    private final Map<Relation, Void> recentRelations = new LinkedHashMap<Relation, Void>(PROPERTY_RECENT_RELATIONS_NUMBER.get()+1, 1.1f, true) {
     133        @Override
     134        protected boolean removeEldestEntry(Map.Entry<Relation, Void> eldest) {
     135            return size() > PROPERTY_RECENT_RELATIONS_NUMBER.get();
     136        }
     137    };
     138
     139    /**
     140     * Returns list of recently closed relations or null if none.
     141     */
     142    public ArrayList<Relation> getRecentRelations() {
     143        ArrayList<Relation> list = new ArrayList<Relation>(recentRelations.keySet());
     144        Collections.reverse(list);
     145        return list;
     146    }
     147
     148    public void setRecentRelation(Relation relation) {
     149        recentRelations.put(relation, null);
     150        Main.map.relationListDialog.enableRecentRelations();
     151    }
     152
     153    public void removeRecentRelation(Relation relation) {
     154        recentRelations.remove(relation);
     155        Main.map.relationListDialog.enableRecentRelations();
     156    }
     157
    124158    protected void setRequiresSaveToFile(boolean newValue) {
    125159        boolean oldValue = requiresSaveToFile;
    126160        requiresSaveToFile = newValue;