source: josm/trunk/src/org/openstreetmap/josm/gui/actionsupport/DeleteFromRelationConfirmationDialog.java@ 6340

Last change on this file since 6340 was 6316, checked in by Don-vip, 11 years ago

Sonar/FindBugs - Loose coupling

  • 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.actionsupport;
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 static private DeleteFromRelationConfirmationDialog instance;
55
56 /**
57 * Replies the unique instance of this dialog
58 *
59 * @return The unique instance of this dialog
60 */
61 static public 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 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>", numParentRelations);
113 } else if (numObjectsToDelete > 1 && numParentRelations == 1) {
114 msg = tr("<html>Please confirm to remove <strong>1 object</strong> from <strong>{0} relations</strong>.</html>", numParentRelations);
115 } else {
116 msg = tr("<html>Please confirm to remove <strong>{0} objects</strong> from <strong>{1} relations</strong>.</html>", numObjectsToDelete,numParentRelations);
117 }
118 htmlPanel.getEditorPane().setText(msg);
119 invalidate();
120 }
121
122 protected void updateTitle() {
123 int numObjectsToDelete = model.getNumObjectsToDelete();
124 if (numObjectsToDelete > 0) {
125 setTitle(trn("Deleting {0} object", "Deleting {0} objects", numObjectsToDelete, numObjectsToDelete));
126 } else {
127 setTitle(tr("Delete objects"));
128 }
129 }
130
131 /**
132 * Constructs a new {@code DeleteFromRelationConfirmationDialog}.
133 */
134 public DeleteFromRelationConfirmationDialog() {
135 super(JOptionPane.getFrameForComponent(Main.parent), "", ModalityType.DOCUMENT_MODAL);
136 build();
137 }
138
139 /**
140 * Replies the data model used in this dialog
141 *
142 * @return the data model
143 */
144 public RelationMemberTableModel getModel() {
145 return model;
146 }
147
148 /**
149 * Replies true if the dialog was canceled
150 *
151 * @return true if the dialog was canceled
152 */
153 public boolean isCanceled() {
154 return canceled;
155 }
156
157 protected void setCanceled(boolean canceled) {
158 this.canceled = canceled;
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(400,200)
169 )
170 ).applySafe(this);
171 setCanceled(false);
172 } else if (isShowing()) { // Avoid IllegalComponentStateException like in #8775
173 new WindowGeometry(this).remember(getClass().getName() + ".geometry");
174 }
175 super.setVisible(visible);
176 }
177
178 @Override
179 public void tableChanged(TableModelEvent e) {
180 updateMessage();
181 updateTitle();
182 }
183
184 /**
185 * The table model which manages the list of relation-to-child references
186 *
187 */
188 public static class RelationMemberTableModel extends DefaultTableModel {
189 private List<RelationToChildReference> data;
190
191 /**
192 * Constructs a new {@code RelationMemberTableModel}.
193 */
194 public RelationMemberTableModel() {
195 data = new ArrayList<RelationToChildReference>();
196 }
197
198 @Override
199 public int getRowCount() {
200 if (data == null) return 0;
201 return data.size();
202 }
203
204 protected void sort() {
205 Collections.sort(
206 data,
207 new Comparator<RelationToChildReference>() {
208 private NameFormatter nf = DefaultNameFormatter.getInstance();
209 @Override
210 public int compare(RelationToChildReference o1, RelationToChildReference o2) {
211 int cmp = o1.getChild().getDisplayName(nf).compareTo(o2.getChild().getDisplayName(nf));
212 if (cmp != 0) return cmp;
213 cmp = o1.getParent().getDisplayName(nf).compareTo(o2.getParent().getDisplayName(nf));
214 if (cmp != 0) return cmp;
215 return Integer.valueOf(o1.getPosition()).compareTo(o2.getPosition());
216 }
217 }
218 );
219 }
220
221 public void populate(Collection<RelationToChildReference> references) {
222 data.clear();
223 if (references != null) {
224 data.addAll(references);
225 }
226 sort();
227 fireTableDataChanged();
228 }
229
230 public Set<OsmPrimitive> getObjectsToDelete() {
231 HashSet<OsmPrimitive> ret = new HashSet<OsmPrimitive>();
232 for (RelationToChildReference ref: data) {
233 ret.add(ref.getChild());
234 }
235 return ret;
236 }
237
238 public int getNumObjectsToDelete() {
239 return getObjectsToDelete().size();
240 }
241
242 public Set<OsmPrimitive> getParentRelations() {
243 HashSet<OsmPrimitive> ret = new HashSet<OsmPrimitive>();
244 for (RelationToChildReference ref: data) {
245 ret.add(ref.getParent());
246 }
247 return ret;
248 }
249
250 public int getNumParentRelations() {
251 return getParentRelations().size();
252 }
253
254 @Override
255 public Object getValueAt(int rowIndex, int columnIndex) {
256 if (data == null) return null;
257 RelationToChildReference ref = data.get(rowIndex);
258 switch(columnIndex) {
259 case 0: return ref.getChild();
260 case 1: return ref.getParent();
261 case 2: return ref.getPosition()+1;
262 case 3: return ref.getRole();
263 default:
264 assert false: "Illegal column index";
265 }
266 return null;
267 }
268
269 @Override
270 public boolean isCellEditable(int row, int column) {
271 return false;
272 }
273 }
274
275 private static class RelationMemberTableColumnModel extends DefaultTableColumnModel{
276
277 protected void createColumns() {
278 TableColumn col = null;
279
280 // column 0 - To Delete
281 col = new TableColumn(0);
282 col.setHeaderValue(tr("To delete"));
283 col.setResizable(true);
284 col.setWidth(100);
285 col.setPreferredWidth(100);
286 col.setCellRenderer(new OsmPrimitivRenderer());
287 addColumn(col);
288
289 // column 0 - From Relation
290 col = new TableColumn(1);
291 col.setHeaderValue(tr("From Relation"));
292 col.setResizable(true);
293 col.setWidth(100);
294 col.setPreferredWidth(100);
295 col.setCellRenderer(new OsmPrimitivRenderer());
296 addColumn(col);
297
298 // column 1 - Pos.
299 col = new TableColumn(2);
300 col.setHeaderValue(tr("Pos."));
301 col.setResizable(true);
302 col.setWidth(30);
303 col.setPreferredWidth(30);
304 addColumn(col);
305
306 // column 2 - Role
307 col = new TableColumn(3);
308 col.setHeaderValue(tr("Role"));
309 col.setResizable(true);
310 col.setWidth(50);
311 col.setPreferredWidth(50);
312 addColumn(col);
313 }
314
315 public RelationMemberTableColumnModel() {
316 createColumns();
317 }
318 }
319
320 class OKAction extends AbstractAction {
321 public OKAction() {
322 putValue(NAME, tr("OK"));
323 putValue(SMALL_ICON, ImageProvider.get("ok"));
324 putValue(SHORT_DESCRIPTION, tr("Click to close the dialog and remove the object from the relations"));
325 }
326
327 @Override
328 public void actionPerformed(ActionEvent e) {
329 setCanceled(false);
330 setVisible(false);
331 }
332 }
333
334 class CancelAction extends AbstractAction {
335 public CancelAction() {
336 putValue(NAME, tr("Cancel"));
337 putValue(SMALL_ICON, ImageProvider.get("cancel"));
338 putValue(SHORT_DESCRIPTION, tr("Click to close the dialog and to abort deleting the objects"));
339 }
340
341 @Override
342 public void actionPerformed(ActionEvent e) {
343 setCanceled(true);
344 setVisible(false);
345 }
346 }
347
348 class WindowEventHandler extends WindowAdapter {
349
350 @Override
351 public void windowClosing(WindowEvent e) {
352 setCanceled(true);
353 }
354
355 @Override
356 public void windowOpened(WindowEvent e) {
357 btnOK.requestFocusInWindow();
358 }
359 }
360}
Note: See TracBrowser for help on using the repository browser.