source: subversion/applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/AddRemoveMemberAction.java

Last change on this file was 34551, checked in by donvip, 8 months ago

update to JOSM 14153

File size: 6.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package relcontext.actions;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.event.ActionEvent;
7import java.awt.event.KeyEvent;
8import java.util.ArrayList;
9import java.util.Collection;
10
11import org.openstreetmap.josm.actions.JosmAction;
12import org.openstreetmap.josm.command.ChangeCommand;
13import org.openstreetmap.josm.command.Command;
14import org.openstreetmap.josm.data.UndoRedoHandler;
15import org.openstreetmap.josm.data.osm.DataSet;
16import org.openstreetmap.josm.data.osm.Node;
17import org.openstreetmap.josm.data.osm.OsmPrimitive;
18import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
19import org.openstreetmap.josm.data.osm.Relation;
20import org.openstreetmap.josm.data.osm.RelationMember;
21import org.openstreetmap.josm.data.osm.Way;
22import org.openstreetmap.josm.gui.util.GuiHelper;
23import org.openstreetmap.josm.tools.ImageProvider;
24import org.openstreetmap.josm.tools.Shortcut;
25
26import relcontext.ChosenRelation;
27import relcontext.ChosenRelationListener;
28
29/**
30 * An action to add or remove (or both) member(s) from the chosen relation.
31 * In time should be able to determine correct position for new members.
32 * Also, there should be some support for entering a role for new members.
33 *
34 * @author Zverik
35 */
36public class AddRemoveMemberAction extends JosmAction implements ChosenRelationListener {
37    private ChosenRelation rel;
38    private SortAndFixAction sortAndFix;
39
40    public AddRemoveMemberAction(ChosenRelation rel, SortAndFixAction sortAndFix) {
41        super(null, "relcontext/addremove", tr("Add/remove members from the chosen relation"),
42                Shortcut.registerShortcut("reltoolbox:addremove", tr("Relation Toolbox: {0}", tr("Add/remove members from the chosen relation")),
43                        KeyEvent.VK_EQUALS, Shortcut.DIRECT), false);
44        this.rel = rel;
45        this.sortAndFix = sortAndFix;
46        rel.addChosenRelationListener(this);
47        updateEnabledState();
48    }
49
50    @Override
51    public void actionPerformed(ActionEvent e) {
52        if (rel.get() == null)
53            return;
54
55        Relation r = new Relation(rel.get());
56
57        Collection<OsmPrimitive> toAdd = new ArrayList<>(getLayerManager().getEditDataSet().getSelected());
58        toAdd.remove(rel.get());
59        toAdd.removeAll(r.getMemberPrimitives());
60
61        // 0. check if relation is broken (temporary)
62        boolean isBroken = !toAdd.isEmpty() && sortAndFix.needsFixing(r);
63
64        // 1. remove all present members
65        r.removeMembersFor(getLayerManager().getEditDataSet().getSelected());
66
67        // 2. add all new members
68        for (OsmPrimitive p : toAdd) {
69            int pos = -1; //p instanceof Way ? findAdjacentMember(p, r) : -1;
70            if (pos < 0) {
71                r.addMember(new RelationMember("", p));
72            } else {
73                r.addMember(pos, new RelationMember("", p));
74            }
75        }
76
77        // 3. check for roles again (temporary)
78        Command roleFix = !isBroken && sortAndFix.needsFixing(r) ? sortAndFix.fixRelation(r) : null;
79        if (roleFix != null) {
80            roleFix.executeCommand();
81        }
82
83        if (!r.getMemberPrimitives().equals(rel.get().getMemberPrimitives())) {
84            UndoRedoHandler.getInstance().add(new ChangeCommand(rel.get(), r));
85        }
86    }
87
88    /**
89     * Finds two relation members between which to place given way. Incomplete.
90     * @see org.openstreetmap.josm.gui.dialogs.relation.MemberTableModel#determineDirection
91     */
92    protected int findAdjacentMember(Way w, Relation r) {
93        Node firstNode = w.firstNode();
94        Node lastNode = w.lastNode();
95
96        if (firstNode != null && !firstNode.equals(lastNode)) {
97            for (int i = 0; i < r.getMembersCount(); i++) {
98                if (r.getMember(i).getType().equals(OsmPrimitiveType.WAY)) {
99                    Way rw = (Way) r.getMember(i).getMember();
100                    Node firstNodeR = rw.firstNode();
101                    Node lastNodeR = rw.lastNode();
102                    if (firstNode.equals(firstNodeR) || firstNode.equals(lastNodeR) || lastNode.equals(firstNodeR) || lastNode.equals(lastNodeR))
103                        return i + 1;
104                }
105            }
106        }
107        return -1;
108    }
109
110    @Override
111    public void chosenRelationChanged(Relation oldRelation, Relation newRelation) {
112        updateEnabledState();
113    }
114
115    @Override
116    protected void updateEnabledState() {
117        updateEnabledState(getLayerManager().getEditDataSet() == null ? null : getLayerManager().getEditDataSet().getSelected());
118    }
119
120    @Override
121    protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
122        updateIcon();
123        if (rel == null || rel.get() == null || selection == null || selection.isEmpty()) {
124            setEnabled(false);
125            return;
126        }
127        if (selection.size() == 1 && selection.contains(rel.get())) {
128            setEnabled(false);
129            return;
130        }
131        setEnabled(true);
132    }
133
134    protected void updateIcon() {
135        // todo: change icon based on selection
136        final int state; // 0=unknown, 1=add, 2=remove, 3=both
137        DataSet ds = getLayerManager().getEditDataSet();
138        if (ds == null || ds.getSelected() == null
139                || ds.getSelected().isEmpty() || rel == null || rel.get() == null) {
140            state = 0;
141        } else {
142            Collection<OsmPrimitive> toAdd = new ArrayList<>(ds.getSelected());
143            toAdd.remove(rel.get());
144            int selectedSize = toAdd.size();
145            if (selectedSize == 0) {
146                state = 0;
147            } else {
148                toAdd.removeAll(rel.get().getMemberPrimitives());
149                if (toAdd.isEmpty()) {
150                    state = 2;
151                } else if (toAdd.size() < selectedSize) {
152                    state = 3;
153                } else {
154                    state = 1;
155                }
156            }
157        }
158        GuiHelper.runInEDT(new Runnable() {
159            @Override
160            public void run() {
161                if (state == 0) {
162                    putValue(LARGE_ICON_KEY, ImageProvider.get("relcontext", "addremove"));
163                } else {
164                    String iconName = state == 1 ? "add" : state == 2 ? "remove" : "addremove";
165                    putValue(NAME, null);
166                    putValue(LARGE_ICON_KEY, ImageProvider.get("relcontext", iconName));
167                }
168            }
169        });
170    }
171}
Note: See TracBrowser for help on using the repository browser.