source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/DeleteFromRelationConfirmationDialog.java@ 8836

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

fix Checkstyle issues

  • Property svn:eol-style set to native
File size: 12.1 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6import static org.openstreetmap.josm.tools.I18n.trn;
7
8import java.awt.BorderLayout;
9import java.awt.Dimension;
10import java.awt.FlowLayout;
11import java.awt.event.ActionEvent;
12import java.awt.event.WindowAdapter;
13import java.awt.event.WindowEvent;
14import java.util.ArrayList;
15import java.util.Collection;
16import java.util.Collections;
17import java.util.Comparator;
18import java.util.HashSet;
19import java.util.List;
20import java.util.Set;
21
22import javax.swing.AbstractAction;
23import javax.swing.JDialog;
24import javax.swing.JOptionPane;
25import javax.swing.JPanel;
26import javax.swing.JScrollPane;
27import javax.swing.JTable;
28import javax.swing.event.TableModelEvent;
29import javax.swing.event.TableModelListener;
30import javax.swing.table.DefaultTableColumnModel;
31import javax.swing.table.DefaultTableModel;
32import javax.swing.table.TableColumn;
33
34import org.openstreetmap.josm.Main;
35import org.openstreetmap.josm.data.osm.NameFormatter;
36import org.openstreetmap.josm.data.osm.OsmPrimitive;
37import org.openstreetmap.josm.data.osm.RelationToChildReference;
38import org.openstreetmap.josm.gui.DefaultNameFormatter;
39import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
40import org.openstreetmap.josm.gui.SideButton;
41import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
42import org.openstreetmap.josm.gui.help.HelpUtil;
43import org.openstreetmap.josm.gui.widgets.HtmlPanel;
44import org.openstreetmap.josm.tools.ImageProvider;
45import org.openstreetmap.josm.tools.WindowGeometry;
46
47/**
48 * This dialog is used to get a user confirmation that a collection of primitives can be removed
49 * from their parent relations.
50 * @since 2308
51 */
52public class DeleteFromRelationConfirmationDialog extends JDialog implements TableModelListener {
53 /** the unique instance of this dialog */
54 private static DeleteFromRelationConfirmationDialog instance;
55
56 /**
57 * Replies the unique instance of this dialog
58 *
59 * @return The unique instance of this dialog
60 */
61 public static synchronized DeleteFromRelationConfirmationDialog getInstance() {
62 if (instance == null) {
63 instance = new DeleteFromRelationConfirmationDialog();
64 }
65 return instance;
66 }
67
68 /** the data model */
69 private RelationMemberTableModel model;
70 private HtmlPanel htmlPanel;
71 private boolean canceled;
72 private SideButton btnOK;
73
74 protected JPanel buildRelationMemberTablePanel() {
75 JTable table = new JTable(model, new RelationMemberTableColumnModel());
76 JPanel pnl = new JPanel();
77 pnl.setLayout(new BorderLayout());
78 pnl.add(new JScrollPane(table));
79 return pnl;
80 }
81
82 protected JPanel buildButtonPanel() {
83 JPanel pnl = new JPanel();
84 pnl.setLayout(new FlowLayout());
85 pnl.add(btnOK = new SideButton(new OKAction()));
86 btnOK.setFocusable(true);
87 pnl.add(new SideButton(new CancelAction()));
88 pnl.add(new SideButton(new ContextSensitiveHelpAction(ht("/Action/Delete#DeleteFromRelations"))));
89 return pnl;
90 }
91
92 protected final void build() {
93 model = new RelationMemberTableModel();
94 model.addTableModelListener(this);
95 getContentPane().setLayout(new BorderLayout());
96 getContentPane().add(htmlPanel = new HtmlPanel(), BorderLayout.NORTH);
97 getContentPane().add(buildRelationMemberTablePanel(), BorderLayout.CENTER);
98 getContentPane().add(buildButtonPanel(), BorderLayout.SOUTH);
99
100 HelpUtil.setHelpContext(this.getRootPane(), ht("/Action/Delete#DeleteFromRelations"));
101
102 addWindowListener(new WindowEventHandler());
103 }
104
105 protected void updateMessage() {
106 int numObjectsToDelete = model.getNumObjectsToDelete();
107 int numParentRelations = model.getNumParentRelations();
108 String msg;
109 if (numObjectsToDelete == 1 && numParentRelations == 1) {
110 msg = tr("<html>Please confirm to remove <strong>1 object</strong> from <strong>1 relation</strong>.</html>");
111 } else if (numObjectsToDelete == 1 && numParentRelations > 1) {
112 msg = tr("<html>Please confirm to remove <strong>1 object</strong> from <strong>{0} relations</strong>.</html>",
113 numParentRelations);
114 } else if (numObjectsToDelete > 1 && numParentRelations == 1) {
115 msg = tr("<html>Please confirm to remove <strong>1 object</strong> from <strong>{0} relations</strong>.</html>",
116 numParentRelations);
117 } else {
118 msg = tr("<html>Please confirm to remove <strong>{0} objects</strong> from <strong>{1} relations</strong>.</html>",
119 numObjectsToDelete, numParentRelations);
120 }
121 htmlPanel.getEditorPane().setText(msg);
122 invalidate();
123 }
124
125 protected void updateTitle() {
126 int numObjectsToDelete = model.getNumObjectsToDelete();
127 if (numObjectsToDelete > 0) {
128 setTitle(trn("Deleting {0} object", "Deleting {0} objects", numObjectsToDelete, numObjectsToDelete));
129 } else {
130 setTitle(tr("Delete objects"));
131 }
132 }
133
134 /**
135 * Constructs a new {@code DeleteFromRelationConfirmationDialog}.
136 */
137 public DeleteFromRelationConfirmationDialog() {
138 super(JOptionPane.getFrameForComponent(Main.parent), "", ModalityType.DOCUMENT_MODAL);
139 build();
140 }
141
142 /**
143 * Replies the data model used in this dialog
144 *
145 * @return the data model
146 */
147 public RelationMemberTableModel getModel() {
148 return model;
149 }
150
151 /**
152 * Replies true if the dialog was canceled
153 *
154 * @return true if the dialog was canceled
155 */
156 public boolean isCanceled() {
157 return canceled;
158 }
159
160 protected void setCanceled(boolean canceled) {
161 this.canceled = canceled;
162 }
163
164 @Override
165 public void setVisible(boolean visible) {
166 if (visible) {
167 new WindowGeometry(
168 getClass().getName() + ".geometry",
169 WindowGeometry.centerInWindow(
170 Main.parent,
171 new Dimension(400, 200)
172 )
173 ).applySafe(this);
174 setCanceled(false);
175 } else if (isShowing()) { // Avoid IllegalComponentStateException like in #8775
176 new WindowGeometry(this).remember(getClass().getName() + ".geometry");
177 }
178 super.setVisible(visible);
179 }
180
181 @Override
182 public void tableChanged(TableModelEvent e) {
183 updateMessage();
184 updateTitle();
185 }
186
187 /**
188 * The table model which manages the list of relation-to-child references
189 *
190 */
191 public static class RelationMemberTableModel extends DefaultTableModel {
192 private transient List<RelationToChildReference> data;
193
194 /**
195 * Constructs a new {@code RelationMemberTableModel}.
196 */
197 public RelationMemberTableModel() {
198 data = new ArrayList<>();
199 }
200
201 @Override
202 public int getRowCount() {
203 if (data == null) return 0;
204 return data.size();
205 }
206
207 protected void sort() {
208 Collections.sort(
209 data,
210 new Comparator<RelationToChildReference>() {
211 private NameFormatter nf = DefaultNameFormatter.getInstance();
212 @Override
213 public int compare(RelationToChildReference o1, RelationToChildReference o2) {
214 int cmp = o1.getChild().getDisplayName(nf).compareTo(o2.getChild().getDisplayName(nf));
215 if (cmp != 0) return cmp;
216 cmp = o1.getParent().getDisplayName(nf).compareTo(o2.getParent().getDisplayName(nf));
217 if (cmp != 0) return cmp;
218 return Integer.compare(o1.getPosition(), o2.getPosition());
219 }
220 }
221 );
222 }
223
224 public void populate(Collection<RelationToChildReference> references) {
225 data.clear();
226 if (references != null) {
227 data.addAll(references);
228 }
229 sort();
230 fireTableDataChanged();
231 }
232
233 public Set<OsmPrimitive> getObjectsToDelete() {
234 Set<OsmPrimitive> ret = new HashSet<>();
235 for (RelationToChildReference ref: data) {
236 ret.add(ref.getChild());
237 }
238 return ret;
239 }
240
241 public int getNumObjectsToDelete() {
242 return getObjectsToDelete().size();
243 }
244
245 public Set<OsmPrimitive> getParentRelations() {
246 Set<OsmPrimitive> ret = new HashSet<>();
247 for (RelationToChildReference ref: data) {
248 ret.add(ref.getParent());
249 }
250 return ret;
251 }
252
253 public int getNumParentRelations() {
254 return getParentRelations().size();
255 }
256
257 @Override
258 public Object getValueAt(int rowIndex, int columnIndex) {
259 if (data == null) return null;
260 RelationToChildReference ref = data.get(rowIndex);
261 switch(columnIndex) {
262 case 0: return ref.getChild();
263 case 1: return ref.getParent();
264 case 2: return ref.getPosition()+1;
265 case 3: return ref.getRole();
266 default:
267 assert false : "Illegal column index";
268 }
269 return null;
270 }
271
272 @Override
273 public boolean isCellEditable(int row, int column) {
274 return false;
275 }
276 }
277
278 private static class RelationMemberTableColumnModel extends DefaultTableColumnModel{
279
280 protected final void createColumns() {
281 TableColumn col = null;
282
283 // column 0 - To Delete
284 col = new TableColumn(0);
285 col.setHeaderValue(tr("To delete"));
286 col.setResizable(true);
287 col.setWidth(100);
288 col.setPreferredWidth(100);
289 col.setCellRenderer(new OsmPrimitivRenderer());
290 addColumn(col);
291
292 // column 0 - From Relation
293 col = new TableColumn(1);
294 col.setHeaderValue(tr("From Relation"));
295 col.setResizable(true);
296 col.setWidth(100);
297 col.setPreferredWidth(100);
298 col.setCellRenderer(new OsmPrimitivRenderer());
299 addColumn(col);
300
301 // column 1 - Pos.
302 col = new TableColumn(2);
303 col.setHeaderValue(tr("Pos."));
304 col.setResizable(true);
305 col.setWidth(30);
306 col.setPreferredWidth(30);
307 addColumn(col);
308
309 // column 2 - Role
310 col = new TableColumn(3);
311 col.setHeaderValue(tr("Role"));
312 col.setResizable(true);
313 col.setWidth(50);
314 col.setPreferredWidth(50);
315 addColumn(col);
316 }
317
318 RelationMemberTableColumnModel() {
319 createColumns();
320 }
321 }
322
323 class OKAction extends AbstractAction {
324 OKAction() {
325 putValue(NAME, tr("OK"));
326 putValue(SMALL_ICON, ImageProvider.get("ok"));
327 putValue(SHORT_DESCRIPTION, tr("Click to close the dialog and remove the object from the relations"));
328 }
329
330 @Override
331 public void actionPerformed(ActionEvent e) {
332 setCanceled(false);
333 setVisible(false);
334 }
335 }
336
337 class CancelAction extends AbstractAction {
338 CancelAction() {
339 putValue(NAME, tr("Cancel"));
340 putValue(SMALL_ICON, ImageProvider.get("cancel"));
341 putValue(SHORT_DESCRIPTION, tr("Click to close the dialog and to abort deleting the objects"));
342 }
343
344 @Override
345 public void actionPerformed(ActionEvent e) {
346 setCanceled(true);
347 setVisible(false);
348 }
349 }
350
351 class WindowEventHandler extends WindowAdapter {
352
353 @Override
354 public void windowClosing(WindowEvent e) {
355 setCanceled(true);
356 }
357
358 @Override
359 public void windowOpened(WindowEvent e) {
360 btnOK.requestFocusInWindow();
361 }
362 }
363}
Note: See TracBrowser for help on using the repository browser.