source: josm/trunk/src/org/openstreetmap/josm/gui/io/UploadSelectionDialog.java@ 10035

Last change on this file since 10035 was 10035, checked in by Don-vip, 8 years ago

code refactoring to ease creation of unit tests by avoiding as much as possible HeadlessException

  • Property svn:eol-style set to native
File size: 10.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.io;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.BorderLayout;
7import java.awt.Dimension;
8import java.awt.FlowLayout;
9import java.awt.event.ActionEvent;
10import java.awt.event.WindowAdapter;
11import java.awt.event.WindowEvent;
12import java.util.ArrayList;
13import java.util.Collection;
14import java.util.Collections;
15import java.util.Comparator;
16import java.util.List;
17
18import javax.swing.AbstractAction;
19import javax.swing.AbstractListModel;
20import javax.swing.Action;
21import javax.swing.BorderFactory;
22import javax.swing.JComponent;
23import javax.swing.JDialog;
24import javax.swing.JLabel;
25import javax.swing.JList;
26import javax.swing.JPanel;
27import javax.swing.JScrollPane;
28import javax.swing.JSplitPane;
29import javax.swing.KeyStroke;
30import javax.swing.ListSelectionModel;
31import javax.swing.event.ListSelectionEvent;
32import javax.swing.event.ListSelectionListener;
33
34import org.openstreetmap.josm.Main;
35import org.openstreetmap.josm.data.osm.OsmPrimitive;
36import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
37import org.openstreetmap.josm.gui.DefaultNameFormatter;
38import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
39import org.openstreetmap.josm.gui.SideButton;
40import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
41import org.openstreetmap.josm.gui.help.HelpUtil;
42import org.openstreetmap.josm.gui.util.GuiHelper;
43import org.openstreetmap.josm.tools.ImageProvider;
44import org.openstreetmap.josm.tools.WindowGeometry;
45
46/**
47 * This dialog can be used to select individual object for uploading.
48 *
49 * @since 2250
50 */
51public class UploadSelectionDialog extends JDialog {
52
53 private OsmPrimitiveList lstSelectedPrimitives;
54 private OsmPrimitiveList lstDeletedPrimitives;
55 private JSplitPane spLists;
56 private boolean canceled;
57 private SideButton btnContinue;
58
59 /**
60 * Constructs a new {@code UploadSelectionDialog}.
61 */
62 public UploadSelectionDialog() {
63 super(GuiHelper.getFrameForComponent(Main.parent), ModalityType.DOCUMENT_MODAL);
64 build();
65 }
66
67 protected JPanel buildSelectedPrimitivesPanel() {
68 JPanel pnl = new JPanel(new BorderLayout());
69 JLabel lbl = new JLabel(
70 tr("<html>Mark modified objects <strong>from the current selection</strong> to be uploaded to the server.</html>"));
71 lbl.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
72 pnl.add(lbl, BorderLayout.NORTH);
73 pnl.add(new JScrollPane(lstSelectedPrimitives = new OsmPrimitiveList()), BorderLayout.CENTER);
74 lbl.setLabelFor(lstSelectedPrimitives);
75 return pnl;
76 }
77
78 protected JPanel buildDeletedPrimitivesPanel() {
79 JPanel pnl = new JPanel(new BorderLayout());
80 JLabel lbl = new JLabel(tr("<html>Mark <strong>locally deleted objects</strong> to be deleted on the server.</html>"));
81 lbl.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
82 pnl.add(lbl, BorderLayout.NORTH);
83 pnl.add(new JScrollPane(lstDeletedPrimitives = new OsmPrimitiveList()), BorderLayout.CENTER);
84 lbl.setLabelFor(lstDeletedPrimitives);
85 return pnl;
86 }
87
88 protected JPanel buildButtonPanel() {
89 JPanel pnl = new JPanel(new FlowLayout());
90 ContinueAction continueAction = new ContinueAction();
91 pnl.add(btnContinue = new SideButton(continueAction));
92 btnContinue.setFocusable(true);
93 lstDeletedPrimitives.getSelectionModel().addListSelectionListener(continueAction);
94 lstSelectedPrimitives.getSelectionModel().addListSelectionListener(continueAction);
95
96 pnl.add(new SideButton(new CancelAction()));
97 pnl.add(new SideButton(new ContextSensitiveHelpAction(HelpUtil.ht("/Dialog/UploadSelection"))));
98 return pnl;
99 }
100
101 protected void build() {
102 setLayout(new BorderLayout());
103 spLists = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
104 spLists.setTopComponent(buildSelectedPrimitivesPanel());
105 spLists.setBottomComponent(buildDeletedPrimitivesPanel());
106 add(spLists, BorderLayout.CENTER);
107 add(buildButtonPanel(), BorderLayout.SOUTH);
108 addWindowListener(
109 new WindowAdapter() {
110 @Override
111 public void windowOpened(WindowEvent e) {
112 spLists.setDividerLocation(0.5);
113 btnContinue.requestFocusInWindow();
114 }
115
116 @Override
117 public void windowClosing(WindowEvent e) {
118 setCanceled(true);
119 }
120 }
121 );
122 setTitle(tr("Select objects to upload"));
123 HelpUtil.setHelpContext(getRootPane(), HelpUtil.ht("/Dialog/UploadSelection"));
124 }
125
126 public void populate(Collection<OsmPrimitive> selected, Collection<OsmPrimitive> deleted) {
127 if (selected != null) {
128 lstSelectedPrimitives.getOsmPrimitiveListModel().setPrimitives(new ArrayList<>(selected));
129 if (!selected.isEmpty()) {
130 lstSelectedPrimitives.getSelectionModel().setSelectionInterval(0, selected.size()-1);
131 } else {
132 lstSelectedPrimitives.getSelectionModel().clearSelection();
133 }
134 } else {
135 lstSelectedPrimitives.getOsmPrimitiveListModel().setPrimitives(null);
136 lstSelectedPrimitives.getSelectionModel().clearSelection();
137 }
138
139 if (deleted != null) {
140 lstDeletedPrimitives.getOsmPrimitiveListModel().setPrimitives(new ArrayList<>(deleted));
141 } else {
142 lstDeletedPrimitives.getOsmPrimitiveListModel().setPrimitives(null);
143 }
144 }
145
146 public boolean isCanceled() {
147 return canceled;
148 }
149
150 protected void setCanceled(boolean canceled) {
151 this.canceled = canceled;
152 }
153
154 public List<OsmPrimitive> getSelectedPrimitives() {
155 List<OsmPrimitive> ret = new ArrayList<>();
156 ret.addAll(lstSelectedPrimitives.getOsmPrimitiveListModel().getPrimitives(lstSelectedPrimitives.getSelectedIndices()));
157 ret.addAll(lstDeletedPrimitives.getOsmPrimitiveListModel().getPrimitives(lstDeletedPrimitives.getSelectedIndices()));
158 return ret;
159 }
160
161 @Override
162 public void setVisible(boolean visible) {
163 if (visible) {
164 new WindowGeometry(
165 getClass().getName() + ".geometry",
166 WindowGeometry.centerInWindow(
167 Main.parent,
168 new Dimension(200, 400)
169 )
170 ).applySafe(this);
171 } else if (isShowing()) { // Avoid IllegalComponentStateException like in #8775
172 new WindowGeometry(this).remember(getClass().getName() + ".geometry");
173 }
174 super.setVisible(visible);
175 }
176
177 static class OsmPrimitiveList extends JList<OsmPrimitive> {
178 protected void init() {
179 setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
180 setCellRenderer(new OsmPrimitivRenderer());
181 }
182
183 OsmPrimitiveList() {
184 this(new OsmPrimitiveListModel());
185 }
186
187 OsmPrimitiveList(OsmPrimitiveListModel model) {
188 super(model);
189 init();
190 }
191
192 public OsmPrimitiveListModel getOsmPrimitiveListModel() {
193 return (OsmPrimitiveListModel) getModel();
194 }
195 }
196
197 static class OsmPrimitiveListModel extends AbstractListModel<OsmPrimitive> {
198 private transient List<OsmPrimitive> data;
199
200 protected void sort() {
201 if (data == null)
202 return;
203 Collections.sort(
204 data,
205 new Comparator<OsmPrimitive>() {
206 private DefaultNameFormatter formatter = DefaultNameFormatter.getInstance();
207 @Override
208 public int compare(OsmPrimitive o1, OsmPrimitive o2) {
209 int ret = OsmPrimitiveType.from(o1).compareTo(OsmPrimitiveType.from(o2));
210 if (ret != 0) return ret;
211 return o1.getDisplayName(formatter).compareTo(o1.getDisplayName(formatter));
212 }
213 }
214 );
215 }
216
217 public void setPrimitives(List<OsmPrimitive> data) {
218 this.data = data;
219 sort();
220 if (data != null) {
221 fireContentsChanged(this, 0, data.size());
222 } else {
223 fireContentsChanged(this, 0, 0);
224 }
225 }
226
227 @Override
228 public OsmPrimitive getElementAt(int index) {
229 if (data == null)
230 return null;
231 return data.get(index);
232 }
233
234 @Override
235 public int getSize() {
236 if (data == null)
237 return 0;
238 return data.size();
239 }
240
241 public List<OsmPrimitive> getPrimitives(int[] indices) {
242 if (indices == null || indices.length == 0)
243 return Collections.emptyList();
244 List<OsmPrimitive> ret = new ArrayList<>(indices.length);
245 for (int i: indices) {
246 if (i < 0) {
247 continue;
248 }
249 ret.add(data.get(i));
250 }
251 return ret;
252 }
253 }
254
255 class CancelAction extends AbstractAction {
256 CancelAction() {
257 putValue(Action.SHORT_DESCRIPTION, tr("Cancel uploading"));
258 putValue(Action.NAME, tr("Cancel"));
259 putValue(Action.SMALL_ICON, ImageProvider.get("", "cancel"));
260 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
261 .put(KeyStroke.getKeyStroke("ESCAPE"), "ESCAPE");
262 getRootPane().getActionMap().put("ESCAPE", this);
263 setEnabled(true);
264 }
265
266 @Override
267 public void actionPerformed(ActionEvent e) {
268 setCanceled(true);
269 setVisible(false);
270 }
271 }
272
273 class ContinueAction extends AbstractAction implements ListSelectionListener {
274 ContinueAction() {
275 putValue(Action.SHORT_DESCRIPTION, tr("Continue uploading"));
276 putValue(Action.NAME, tr("Continue"));
277 putValue(Action.SMALL_ICON, ImageProvider.get("", "upload"));
278 updateEnabledState();
279 }
280
281 @Override
282 public void actionPerformed(ActionEvent e) {
283 setCanceled(false);
284 setVisible(false);
285 }
286
287 protected void updateEnabledState() {
288 setEnabled(lstSelectedPrimitives.getSelectedIndex() >= 0
289 || lstDeletedPrimitives.getSelectedIndex() >= 0);
290 }
291
292 @Override
293 public void valueChanged(ListSelectionEvent e) {
294 updateEnabledState();
295 }
296 }
297}
Note: See TracBrowser for help on using the repository browser.