001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.actions.relation;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.GridBagLayout;
007import java.awt.event.ActionEvent;
008
009import javax.swing.JOptionPane;
010import javax.swing.JPanel;
011
012import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
013import org.openstreetmap.josm.data.osm.IRelation;
014import org.openstreetmap.josm.data.osm.Relation;
015import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
016import org.openstreetmap.josm.gui.MainApplication;
017import org.openstreetmap.josm.gui.dialogs.relation.RelationEditor;
018import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
019import org.openstreetmap.josm.tools.ImageProvider;
020
021/**
022 * Creates a new relation with a copy of the current editor state
023 * @since 5799
024 */
025public class DuplicateRelationAction extends AbstractRelationAction {
026
027    /**
028     * Constructs a new {@code DuplicateRelationAction}.
029     */
030    public DuplicateRelationAction() {
031        putValue(SHORT_DESCRIPTION, tr("Create a copy of this relation and open it in another editor window"));
032        new ImageProvider("duplicate").getResource().attachImageIcon(this, true);
033        putValue(NAME, tr("Duplicate"));
034    }
035
036    /**
037     * Duplicates the given relation and launches the relation editor for the created copy.
038     * @param original The relation to duplicate
039     */
040    public static void duplicateRelationAndLaunchEditor(Relation original) {
041        if (!confirmRelationDuplicate(original)) {
042            return;
043        }
044        Relation copy = new Relation(original, true);
045        copy.setModified(true);
046        RelationEditor editor = RelationEditor.getEditor(
047                MainApplication.getLayerManager().getEditLayer(),
048                copy,
049                null /* no selected members */
050                );
051        editor.setVisible(true);
052    }
053
054    @Override
055    public void actionPerformed(ActionEvent e) {
056        if (!isEnabled() || relations.isEmpty())
057            return;
058        IRelation<?> r = relations.iterator().next();
059        if (r instanceof Relation) {
060            duplicateRelationAndLaunchEditor((Relation) r);
061        }
062    }
063
064    private static boolean isEditableRelation(IRelation<?> r) {
065        return r instanceof Relation && r.getDataSet() != null && !r.getDataSet().isLocked();
066    }
067
068    @Override
069    protected void updateEnabledState() {
070        // only one selected relation can be edited
071        setEnabled(relations.size() == 1
072                && isEditableRelation(relations.iterator().next()));
073    }
074
075    private static boolean confirmRelationDuplicate(Relation relation) {
076        JPanel msg = new JPanel(new GridBagLayout());
077        msg.add(new JMultilineLabel("<html>" + tr(
078                "You are about to duplicate {0} relation: {1}"
079                        + "<br/>"
080                        + "This step is rarely necessary. Do you really want to duplicate?",
081                1, DefaultNameFormatter.getInstance().formatAsHtmlUnorderedList(relation))
082                + "</html>"));
083        return ConditionalOptionPaneUtil.showConfirmationDialog(
084                "delete_relations",
085                MainApplication.getMainFrame(),
086                msg,
087                tr("Duplicate relation?"),
088                JOptionPane.YES_NO_OPTION,
089                JOptionPane.QUESTION_MESSAGE,
090                JOptionPane.YES_OPTION);
091    }
092}