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

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

see #12994 - Old style SideButton usage errors

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