Ticket #5097: 5097v1.patch

File 5097v1.patch, 14.0 KB (added by simon04, 12 years ago)
  • new file src/org/openstreetmap/josm/actions/RepeatAction.java

    diff --git a/src/org/openstreetmap/josm/actions/RepeatAction.java b/src/org/openstreetmap/josm/actions/RepeatAction.java
    new file mode 100644
    index 0000000..e4ddd74
    - +  
     1package org.openstreetmap.josm.actions;
     2
     3import org.openstreetmap.josm.Main;
     4import org.openstreetmap.josm.command.RepeatableCommand;
     5import org.openstreetmap.josm.data.SelectionChangedListener;
     6import org.openstreetmap.josm.data.osm.DataSet;
     7import org.openstreetmap.josm.data.osm.OsmPrimitive;
     8import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     9import org.openstreetmap.josm.tools.Shortcut;
     10
     11import java.awt.event.ActionEvent;
     12import java.awt.event.KeyEvent;
     13import java.util.Collection;
     14
     15import static org.openstreetmap.josm.tools.I18n.tr;
     16
     17public class RepeatAction extends JosmAction implements OsmDataLayer.CommandQueueListener, SelectionChangedListener {
     18
     19    public RepeatAction() {
     20        super(tr("Repeat"), null, tr("Repeat the last action."),
     21                Shortcut.registerShortcut("system:repeat", tr("Edit: {0}", tr("Repeat")), KeyEvent.VK_PERIOD, Shortcut.ALT_CTRL), true);
     22        setEnabled(false);
     23        DataSet.addSelectionListener(this);
     24    }
     25
     26    @Override
     27    public void actionPerformed(ActionEvent e) {
     28        if (Main.map != null) {
     29            Main.map.repaint();
     30            Main.main.undoRedo.add(getRepeatableCommand().repeatableFor(Main.main.getCurrentDataSet().getSelected()));
     31        }
     32    }
     33
     34    @Override
     35    protected void updateEnabledState() {
     36        setEnabled(getRepeatableCommand() != null
     37                && Main.main.getCurrentDataSet() != null
     38                && !Main.main.getCurrentDataSet().getSelected().isEmpty()
     39                && getRepeatableCommand().isRepeatableFor(Main.main.getCurrentDataSet().getSelected()));
     40        if (getRepeatableCommand() == null) {
     41            putValue(NAME, tr("Repeat"));
     42            setTooltip(tr("Repeat the last action."));
     43        } else {
     44            putValue(NAME, tr("Repeat ..."));
     45            setTooltip(tr("Repeat {0}", getRepeatableCommand().getDescriptionText()));
     46        }
     47    }
     48
     49    @Override
     50    public void commandChanged(int queueSize, int redoSize) {
     51        updateEnabledState();
     52    }
     53
     54    @Override
     55    public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
     56        updateEnabledState();
     57    }
     58
     59    protected RepeatableCommand getRepeatableCommand() {
     60        if (Main.main != null
     61                && !Main.main.undoRedo.commands.isEmpty()
     62                && Main.main.undoRedo.commands.getLast() instanceof RepeatableCommand) {
     63            return (RepeatableCommand) Main.main.undoRedo.commands.getLast();
     64        } else {
     65            return null;
     66        }
     67    }
     68}
     69
  • src/org/openstreetmap/josm/command/ChangePropertyCommand.java

    diff --git a/src/org/openstreetmap/josm/command/ChangePropertyCommand.java b/src/org/openstreetmap/josm/command/ChangePropertyCommand.java
    index 8a3ac10..a106d8f 100644
    a b import org.openstreetmap.josm.tools.ImageProvider;  
    2828 *
    2929 * @author imi
    3030 */
    31 public class ChangePropertyCommand extends Command {
     31public class ChangePropertyCommand extends RepeatableCommand {
    3232    /**
    3333     * All primitives that are affected with this command.
    3434     */
    public class ChangePropertyCommand extends Command {  
    213213        }
    214214        return children;
    215215    }
     216
     217    @Override
     218    public boolean isRepeatableFor(Collection<OsmPrimitive> primitives) {
     219        return true;
     220    }
     221
     222    @Override
     223    public RepeatableCommand repeatableFor(Collection<OsmPrimitive> primitives) {
     224        return new ChangePropertyCommand(primitives, tags);
     225    }
    216226}
  • new file src/org/openstreetmap/josm/command/RepeatableCommand.java

    diff --git a/src/org/openstreetmap/josm/command/RepeatableCommand.java b/src/org/openstreetmap/josm/command/RepeatableCommand.java
    new file mode 100644
    index 0000000..a6f1029
    - +  
     1package org.openstreetmap.josm.command;
     2
     3import org.openstreetmap.josm.data.osm.OsmPrimitive;
     4import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     5import org.openstreetmap.josm.tools.Predicate;
     6import org.openstreetmap.josm.tools.Utils;
     7
     8import java.util.Collection;
     9
     10public abstract class RepeatableCommand extends Command {
     11    public RepeatableCommand() {
     12    }
     13
     14    public RepeatableCommand(OsmDataLayer layer) throws IllegalArgumentException {
     15        super(layer);
     16    }
     17
     18    public abstract boolean isRepeatableFor(final Collection<OsmPrimitive> primitives);
     19
     20    public abstract RepeatableCommand repeatableFor(final Collection<OsmPrimitive> primitives);
     21
     22    public static Predicate<Command> getIsRepeatableForPredicate(final Collection<OsmPrimitive> primitives) {
     23        return new Predicate<Command>() {
     24            @Override
     25            public boolean evaluate(Command c) {
     26                return c instanceof RepeatableCommand && ((RepeatableCommand) c).isRepeatableFor(primitives);
     27            }
     28        };
     29    }
     30
     31    public static Utils.Function<RepeatableCommand, RepeatableCommand> getRepeatForFunction(final Collection<OsmPrimitive> primitives) {
     32        return new Utils.Function<RepeatableCommand, RepeatableCommand>() {
     33            @Override
     34            public RepeatableCommand apply(RepeatableCommand x) {
     35                return x.repeatableFor(primitives);
     36            }
     37        };
     38    }
     39}
  • src/org/openstreetmap/josm/command/SequenceCommand.java

    diff --git a/src/org/openstreetmap/josm/command/SequenceCommand.java b/src/org/openstreetmap/josm/command/SequenceCommand.java
    index f172f22..2ae6b2a 100644
    a b import static org.openstreetmap.josm.tools.I18n.tr;  
    66import java.util.Arrays;
    77import java.util.Collection;
    88import java.util.HashSet;
     9import java.util.List;
    910
    1011import javax.swing.Icon;
    1112
    1213import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1314import org.openstreetmap.josm.tools.ImageProvider;
     15import org.openstreetmap.josm.tools.Predicate;
     16import org.openstreetmap.josm.tools.Utils;
    1417
    1518/**
    1619 * A command consisting of a sequence of other commands. Executes the other commands
    import org.openstreetmap.josm.tools.ImageProvider;  
    1821 * @author imi
    1922 * @since 31
    2023 */
    21 public class SequenceCommand extends Command {
     24public class SequenceCommand extends RepeatableCommand {
    2225
    2326    /** The command sequence to be executed. */
    2427    private Command[] sequence;
    public class SequenceCommand extends Command {  
    3235     * @param name The description text
    3336     * @param sequenz The sequence that should be executed.
    3437     */
    35     public SequenceCommand(String name, Collection<Command> sequenz) {
     38    public SequenceCommand(String name, Collection<? extends Command> sequenz) {
    3639        super();
    3740        this.name = name;
    3841        this.sequence = sequenz.toArray(new Command[sequenz.size()]);
    public class SequenceCommand extends Command {  
    121124    protected final void setSequenceComplete(boolean sequenceComplete) {
    122125        this.sequenceComplete = sequenceComplete;
    123126    }
     127
     128    @Override
     129    public boolean isRepeatableFor(final Collection<OsmPrimitive> primitives) {
     130        return Utils.forAll(Arrays.asList(sequence), getIsRepeatableForPredicate(primitives));
     131    }
     132
     133    @SuppressWarnings("unchecked")
     134    @Override
     135    public RepeatableCommand repeatableFor(final Collection<OsmPrimitive> primitives) {
     136        final List commands = Arrays.asList(sequence);
     137        return new SequenceCommand(name, Utils.transform(commands, getRepeatForFunction(primitives)));
     138    }
    124139}
  • src/org/openstreetmap/josm/gui/MainMenu.java

    diff --git a/src/org/openstreetmap/josm/gui/MainMenu.java b/src/org/openstreetmap/josm/gui/MainMenu.java
    index a4d6653..886dcff 100644
    a b import javax.swing.event.MenuEvent;  
    2222import javax.swing.event.MenuListener;
    2323
    2424import org.openstreetmap.josm.Main;
    25 import org.openstreetmap.josm.actions.AboutAction;
    26 import org.openstreetmap.josm.actions.AddNodeAction;
    27 import org.openstreetmap.josm.actions.AlignInCircleAction;
    28 import org.openstreetmap.josm.actions.AlignInLineAction;
    29 import org.openstreetmap.josm.actions.AutoScaleAction;
    30 import org.openstreetmap.josm.actions.ChangesetManagerToggleAction;
    31 import org.openstreetmap.josm.actions.CloseChangesetAction;
    32 import org.openstreetmap.josm.actions.CombineWayAction;
    33 import org.openstreetmap.josm.actions.CopyAction;
    34 import org.openstreetmap.josm.actions.CopyCoordinatesAction;
    35 import org.openstreetmap.josm.actions.CreateCircleAction;
    36 import org.openstreetmap.josm.actions.CreateMultipolygonAction;
    37 import org.openstreetmap.josm.actions.DeleteAction;
    38 import org.openstreetmap.josm.actions.DialogsToggleAction;
    39 import org.openstreetmap.josm.actions.DistributeAction;
    40 import org.openstreetmap.josm.actions.DownloadAction;
    41 import org.openstreetmap.josm.actions.DownloadPrimitiveAction;
    42 import org.openstreetmap.josm.actions.DownloadReferrersAction;
    43 import org.openstreetmap.josm.actions.DuplicateAction;
    44 import org.openstreetmap.josm.actions.ExitAction;
    45 import org.openstreetmap.josm.actions.ExpertToggleAction;
    46 import org.openstreetmap.josm.actions.FollowLineAction;
    47 import org.openstreetmap.josm.actions.FullscreenToggleAction;
    48 import org.openstreetmap.josm.actions.GpxExportAction;
    49 import org.openstreetmap.josm.actions.HelpAction;
    50 import org.openstreetmap.josm.actions.HistoryInfoAction;
    51 import org.openstreetmap.josm.actions.HistoryInfoWebAction;
    52 import org.openstreetmap.josm.actions.InfoAction;
    53 import org.openstreetmap.josm.actions.InfoWebAction;
    54 import org.openstreetmap.josm.actions.JoinAreasAction;
    55 import org.openstreetmap.josm.actions.JoinNodeWayAction;
    56 import org.openstreetmap.josm.actions.JosmAction;
    57 import org.openstreetmap.josm.actions.JumpToAction;
    58 import org.openstreetmap.josm.actions.MergeLayerAction;
    59 import org.openstreetmap.josm.actions.MergeNodesAction;
    60 import org.openstreetmap.josm.actions.MergeSelectionAction;
    61 import org.openstreetmap.josm.actions.MirrorAction;
    62 import org.openstreetmap.josm.actions.MoveAction;
    63 import org.openstreetmap.josm.actions.MoveNodeAction;
    64 import org.openstreetmap.josm.actions.NewAction;
    65 import org.openstreetmap.josm.actions.OpenFileAction;
    66 import org.openstreetmap.josm.actions.OpenLocationAction;
    67 import org.openstreetmap.josm.actions.OrthogonalizeAction;
     25import org.openstreetmap.josm.actions.*;
    6826import org.openstreetmap.josm.actions.OrthogonalizeAction.Undo;
    69 import org.openstreetmap.josm.actions.PasteAction;
    70 import org.openstreetmap.josm.actions.PasteTagsAction;
    71 import org.openstreetmap.josm.actions.PreferenceToggleAction;
    72 import org.openstreetmap.josm.actions.PreferencesAction;
    73 import org.openstreetmap.josm.actions.PurgeAction;
    74 import org.openstreetmap.josm.actions.RedoAction;
    75 import org.openstreetmap.josm.actions.RestartAction;
    76 import org.openstreetmap.josm.actions.ReverseWayAction;
    77 import org.openstreetmap.josm.actions.SaveAction;
    78 import org.openstreetmap.josm.actions.SaveAsAction;
    79 import org.openstreetmap.josm.actions.SelectAllAction;
    80 import org.openstreetmap.josm.actions.SessionLoadAction;
    81 import org.openstreetmap.josm.actions.SessionSaveAsAction;
    82 import org.openstreetmap.josm.actions.ShowStatusReportAction;
    83 import org.openstreetmap.josm.actions.SimplifyWayAction;
    84 import org.openstreetmap.josm.actions.SplitWayAction;
    85 import org.openstreetmap.josm.actions.ToggleGPXLinesAction;
    86 import org.openstreetmap.josm.actions.UnGlueAction;
    87 import org.openstreetmap.josm.actions.UnJoinNodeWayAction;
    88 import org.openstreetmap.josm.actions.UndoAction;
    89 import org.openstreetmap.josm.actions.UnselectAllAction;
    90 import org.openstreetmap.josm.actions.UpdateDataAction;
    91 import org.openstreetmap.josm.actions.UpdateModifiedAction;
    92 import org.openstreetmap.josm.actions.UpdateSelectionAction;
    93 import org.openstreetmap.josm.actions.UploadAction;
    94 import org.openstreetmap.josm.actions.UploadSelectionAction;
    95 import org.openstreetmap.josm.actions.ViewportFollowToggleAction;
    96 import org.openstreetmap.josm.actions.WireframeToggleAction;
    97 import org.openstreetmap.josm.actions.ZoomInAction;
    98 import org.openstreetmap.josm.actions.ZoomOutAction;
    9927import org.openstreetmap.josm.actions.audio.AudioBackAction;
    10028import org.openstreetmap.josm.actions.audio.AudioFasterAction;
    10129import org.openstreetmap.josm.actions.audio.AudioFwdAction;
    public class MainMenu extends JMenuBar {  
    172100    public final UndoAction undo = new UndoAction();
    173101    /** Edit -> Redo */
    174102    public final RedoAction redo = new RedoAction();
     103    /** Edit -> Repeat */
     104    public final RepeatAction repeat = new RepeatAction();
    175105    /** Edit -> Copy */
    176106    public final CopyAction copy = new CopyAction();
    177107    /** Edit -> Copy Coordinates */
    public class MainMenu extends JMenuBar {  
    621551        Main.main.undoRedo.addCommandQueueListener(undo);
    622552        add(editMenu, redo);
    623553        Main.main.undoRedo.addCommandQueueListener(redo);
     554        add(editMenu, repeat);
     555        Main.main.undoRedo.addCommandQueueListener(repeat);
    624556        editMenu.addSeparator();
    625557        add(editMenu, copy);
    626558        add(editMenu, copyCoordinates, true);
  • src/org/openstreetmap/josm/tools/Utils.java

    diff --git a/src/org/openstreetmap/josm/tools/Utils.java b/src/org/openstreetmap/josm/tools/Utils.java
    index 48149d6..92ff0cc 100644
    a b public final class Utils {  
    100100        return null;
    101101    }
    102102
     103    public static <T> Predicate<T> not(final Predicate<T> predicate) {
     104        return new Predicate<T>() {
     105            @Override
     106            public boolean evaluate(T object) {
     107                return !predicate.evaluate(object);
     108            }
     109        };
     110    }
     111
     112    public static <T> boolean forAll(Iterable<? extends T> collection, Predicate<? super T> predicate) {
     113        return !exists(collection, not(predicate));
     114    }
     115
    103116    /**
    104117     * Filter a collection by (sub)class.
    105118     * This is an efficient read-only implementation.