source: osm/applications/editors/josm/plugins/reltoolbox/src/relcontext/RelContextDialog.java@ 30738

Last change on this file since 30738 was 30738, checked in by donvip, 11 years ago

[josm_plugins] fix java 7 warnings / global usage of try-with-resource

File size: 31.0 KB
Line 
1package relcontext;
2
3import static org.openstreetmap.josm.tools.I18n.tr;
4
5import java.awt.BorderLayout;
6import java.awt.Color;
7import java.awt.Component;
8import java.awt.Dialog.ModalityType;
9import java.awt.Dimension;
10import java.awt.GridBagLayout;
11import java.awt.Point;
12import java.awt.event.ActionEvent;
13import java.awt.event.ActionListener;
14import java.awt.event.ItemEvent;
15import java.awt.event.ItemListener;
16import java.awt.event.KeyEvent;
17import java.awt.event.MouseAdapter;
18import java.awt.event.MouseEvent;
19import java.awt.event.MouseListener;
20import java.beans.PropertyChangeEvent;
21import java.beans.PropertyChangeListener;
22import java.io.BufferedReader;
23import java.io.InputStream;
24import java.io.InputStreamReader;
25import java.util.ArrayList;
26import java.util.Collection;
27import java.util.Collections;
28import java.util.HashMap;
29import java.util.List;
30import java.util.Map;
31import java.util.Set;
32import java.util.StringTokenizer;
33import java.util.TreeSet;
34
35import javax.swing.AbstractListModel;
36import javax.swing.Action;
37import javax.swing.Box;
38import javax.swing.ComboBoxModel;
39import javax.swing.JButton;
40import javax.swing.JCheckBoxMenuItem;
41import javax.swing.JComboBox;
42import javax.swing.JComponent;
43import javax.swing.JDialog;
44import javax.swing.JLabel;
45import javax.swing.JOptionPane;
46import javax.swing.JPanel;
47import javax.swing.JPopupMenu;
48import javax.swing.JScrollPane;
49import javax.swing.JTable;
50import javax.swing.ListSelectionModel;
51import javax.swing.SwingUtilities;
52import javax.swing.event.ListSelectionEvent;
53import javax.swing.event.ListSelectionListener;
54import javax.swing.table.DefaultTableCellRenderer;
55import javax.swing.table.DefaultTableModel;
56import javax.swing.table.TableColumnModel;
57
58import org.openstreetmap.josm.Main;
59import org.openstreetmap.josm.actions.JosmAction;
60import org.openstreetmap.josm.command.ChangeRelationMemberRoleCommand;
61import org.openstreetmap.josm.command.Command;
62import org.openstreetmap.josm.command.SequenceCommand;
63import org.openstreetmap.josm.data.SelectionChangedListener;
64import org.openstreetmap.josm.data.osm.OsmPrimitive;
65import org.openstreetmap.josm.data.osm.Relation;
66import org.openstreetmap.josm.data.osm.RelationMember;
67import org.openstreetmap.josm.data.osm.event.DatasetEventManager;
68import org.openstreetmap.josm.data.osm.event.DatasetEventManager.FireMode;
69import org.openstreetmap.josm.data.osm.event.SelectionEventManager;
70import org.openstreetmap.josm.gui.DefaultNameFormatter;
71import org.openstreetmap.josm.gui.MapView;
72import org.openstreetmap.josm.gui.MapView.EditLayerChangeListener;
73import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
74import org.openstreetmap.josm.gui.dialogs.ToggleDialog;
75import org.openstreetmap.josm.gui.layer.OsmDataLayer;
76import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingComboBox;
77import org.openstreetmap.josm.tools.GBC;
78import org.openstreetmap.josm.tools.Shortcut;
79
80import relcontext.actions.AddRemoveMemberAction;
81import relcontext.actions.ClearChosenRelationAction;
82import relcontext.actions.CreateMultipolygonAction;
83import relcontext.actions.CreateRelationAction;
84import relcontext.actions.DeleteChosenRelationAction;
85import relcontext.actions.DownloadChosenRelationAction;
86import relcontext.actions.DownloadParentsAction;
87import relcontext.actions.DuplicateChosenRelationAction;
88import relcontext.actions.EditChosenRelationAction;
89import relcontext.actions.FindRelationAction;
90import relcontext.actions.ReconstructPolygonAction;
91import relcontext.actions.RelationHelpAction;
92import relcontext.actions.SelectInRelationPanelAction;
93import relcontext.actions.SelectMembersAction;
94import relcontext.actions.SelectRelationAction;
95import relcontext.actions.SortAndFixAction;
96
97/**
98 * The new, advanced relation editing panel.
99 *
100 * @author Zverik
101 */
102public class RelContextDialog extends ToggleDialog implements EditLayerChangeListener, ChosenRelationListener, SelectionChangedListener {
103
104 public final static String PREF_PREFIX = "reltoolbox";
105
106 private final DefaultTableModel relationsData;
107 private ChosenRelation chosenRelation;
108 private JPanel chosenRelationPanel;
109 private ChosenRelationPopupMenu popupMenu;
110 private MultipolygonSettingsPopup multiPopupMenu;
111 private RoleComboBoxModel roleBoxModel;
112 private SortAndFixAction sortAndFixAction;
113 // actions saved for unregistering on dialog destroying
114 private final EnterRoleAction enterRoleAction;
115 private final FindRelationAction findRelationAction;
116 private final CreateMultipolygonAction createMultipolygonAction;
117 private final CreateRelationAction createRelationAction;
118 private final AddRemoveMemberAction addRemoveMemberAction;
119
120 public RelContextDialog() {
121 super(tr("Relation Toolbox"), PREF_PREFIX, tr("Open relation/multipolygon editor panel"), null, 150, true);
122
123 chosenRelation = new ChosenRelation();
124 chosenRelation.addChosenRelationListener(this);
125 MapView.addEditLayerChangeListener(chosenRelation);
126
127 popupMenu = new ChosenRelationPopupMenu(chosenRelation);
128 multiPopupMenu = new MultipolygonSettingsPopup();
129
130 JPanel rcPanel = new JPanel(new BorderLayout());
131
132 relationsData = new RelationTableModel();
133 relationsData.setColumnIdentifiers(new String[] {tr("Member Of"), tr("Role")});
134 final JTable relationsTable = new JTable(relationsData);
135 configureRelationsTable(relationsTable);
136 rcPanel.add(new JScrollPane(relationsTable, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER), BorderLayout.CENTER);
137
138 final MouseListener relationMouseAdapter = new ChosenRelationMouseAdapter();
139 final JComboBox<String> roleBox = new JComboBox<>();
140 roleBoxModel = new RoleComboBoxModel(roleBox);
141 roleBox.setModel(roleBoxModel);
142 roleBox.addMouseListener(relationMouseAdapter);
143 roleBox.addItemListener(new ItemListener() {
144 @Override
145 public void itemStateChanged( ItemEvent e ) {
146 if( e.getStateChange() == ItemEvent.DESELECTED ) return;
147 String memberRole = roleBoxModel.getSelectedMembersRole();
148 String selectedRole = roleBoxModel.isAnotherRoleSelected() ? askForRoleName() : roleBoxModel.getSelectedRole();
149 if( memberRole != null && selectedRole != null && !memberRole.equals(selectedRole) ) {
150 applyRoleToSelection(selectedRole.trim());
151 }
152 }
153 });
154 roleBox.setVisible(false);
155 enterRoleAction = new EnterRoleAction(); // just for the shortcut
156 sortAndFixAction = new SortAndFixAction(chosenRelation);
157
158 // [±][X] relation U [AZ][Down][Edit]
159 chosenRelationPanel = new JPanel(new GridBagLayout());
160 addRemoveMemberAction = new AddRemoveMemberAction(chosenRelation, sortAndFixAction);
161 chosenRelationPanel.add(new JButton(addRemoveMemberAction), GBC.std());
162 chosenRelationPanel.add(sizeButton(new JButton(new ClearChosenRelationAction(chosenRelation)), 32, 0), GBC.std());
163 final ChosenRelationComponent chosenRelationComponent = new ChosenRelationComponent(chosenRelation);
164 chosenRelationComponent.addMouseListener(relationMouseAdapter);
165 chosenRelationPanel.add(chosenRelationComponent, GBC.std().fill().insets(5, 0, 5, 0));
166 chosenRelationPanel.add(roleBox, GBC.std().fill().insets(5, 0, 5, 0));
167 final JButton sortAndFixButton = (JButton) sizeButton(new JButton(sortAndFixAction), 32, 0);
168 chosenRelationPanel.add(sortAndFixButton, GBC.std().fill(GBC.VERTICAL));
169 final Action downloadChosenRelationAction = new DownloadChosenRelationAction(chosenRelation);
170 final JButton downloadButton = (JButton) sizeButton(new JButton(downloadChosenRelationAction), 32, 0);
171 chosenRelationPanel.add(downloadButton, GBC.std().fill(GBC.VERTICAL));
172 chosenRelationPanel.add(new JButton(new EditChosenRelationAction(chosenRelation)), GBC.eol().fill(GBC.VERTICAL));
173
174 rcPanel.add(chosenRelationPanel, BorderLayout.NORTH);
175
176 roleBox.addPropertyChangeListener("enabled", new PropertyChangeListener() {
177 @Override
178 public void propertyChange( PropertyChangeEvent evt ) {
179 boolean showRoleBox = roleBox.isEnabled();
180 roleBox.setVisible(showRoleBox);
181 chosenRelationComponent.setVisible(!showRoleBox);
182 }
183 });
184
185 sortAndFixAction.addPropertyChangeListener(new PropertyChangeListener() {
186 @Override
187 public void propertyChange( PropertyChangeEvent evt ) {
188 sortAndFixButton.setVisible(sortAndFixAction.isEnabled());
189 }
190 });
191 sortAndFixButton.setVisible(false);
192
193 downloadChosenRelationAction.addPropertyChangeListener(new PropertyChangeListener() {
194 @Override
195 public void propertyChange( PropertyChangeEvent evt ) {
196 downloadButton.setVisible(downloadChosenRelationAction.isEnabled());
197 }
198 });
199 downloadButton.setVisible(false);
200 if( Main.pref.getBoolean(PREF_PREFIX + ".hidetopline", false) )
201 chosenRelationPanel.setVisible(false);
202
203 // [+][Multi] [X]Adm [X]Tags [X]1
204 JPanel bottomLine = new JPanel(new GridBagLayout());
205 createRelationAction = new CreateRelationAction(chosenRelation);
206 bottomLine.add(new JButton(createRelationAction), GBC.std());
207 createMultipolygonAction = new CreateMultipolygonAction(chosenRelation);
208 final JButton multipolygonButton = new JButton(createMultipolygonAction);
209 bottomLine.add(multipolygonButton, GBC.std());
210// bottomLine.add(sizeButton(new JButton(new MultipolygonSettingsAction()), 16, 0), GBC.std().fill(GBC.VERTICAL));
211 bottomLine.add(Box.createHorizontalGlue(), GBC.std().fill());
212 findRelationAction = new FindRelationAction(chosenRelation);
213 bottomLine.add(new JButton(findRelationAction), GBC.eol());
214 rcPanel.add(sizeButton(bottomLine, 0, 24), BorderLayout.SOUTH);
215
216 multipolygonButton.addMouseListener(new MouseAdapter() {
217 @Override
218 public void mousePressed( MouseEvent e ) {
219 checkPopup(e);
220 }
221
222 @Override
223 public void mouseReleased( MouseEvent e ) {
224 checkPopup(e);
225 }
226
227 private void checkPopup( MouseEvent e ) {
228 if( e.isPopupTrigger() )
229 multiPopupMenu.show(e.getComponent(), e.getX(), e.getY());
230 }
231 });
232
233 createLayout(rcPanel, false, null);
234 }
235
236 private static final Color CHOSEN_RELATION_COLOR = new Color(255, 255, 128);
237
238 private void configureRelationsTable( final JTable relationsTable ) {
239 relationsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
240 relationsTable.setTableHeader(null);
241 relationsTable.addMouseListener(new MouseAdapter() {
242 @Override
243 public void mouseClicked( MouseEvent e ) {
244 Point p = e.getPoint();
245 int row = relationsTable.rowAtPoint(p);
246 if( SwingUtilities.isLeftMouseButton(e) && row >= 0 ) {
247 Relation relation = (Relation)relationsData.getValueAt(row, 0);
248 if( e.getClickCount() > 1 ) {
249 Main.main.getEditLayer().data.setSelected(relation);
250 }
251 }
252 }
253
254 @Override
255 public void mousePressed( MouseEvent e ) {
256 checkPopup(e);
257 }
258
259 @Override
260 public void mouseReleased( MouseEvent e ) {
261 checkPopup(e);
262 }
263
264 public void checkPopup( MouseEvent e ) {
265 if( e.isPopupTrigger() ) {
266 Point p = e.getPoint();
267 int row = relationsTable.rowAtPoint(p);
268 if (row > -1) {
269 Relation relation = (Relation)relationsData.getValueAt(row, 0);
270 JPopupMenu menu = chosenRelation.isSame(relation) ? popupMenu
271 : new ChosenRelationPopupMenu(new StaticChosenRelation(relation));
272 menu.show(relationsTable, p.x, p.y-5);
273 }
274 }
275 }
276 });
277
278 TableColumnModel columns = relationsTable.getColumnModel();
279 columns.getColumn(0).setCellRenderer(new OsmPrimitivRenderer() {
280 @Override
281 protected String getComponentToolTipText( OsmPrimitive value ) {
282 return null;
283 }
284
285 @Override
286 public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column ) {
287 Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
288 if( !isSelected && value instanceof Relation && chosenRelation.isSame(value) )
289 c.setBackground(CHOSEN_RELATION_COLOR);
290 else
291 c.setBackground(table.getBackground());
292 return c;
293 }
294
295 });
296 columns.getColumn(1).setCellRenderer(new DefaultTableCellRenderer() {
297 @Override
298 public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column ) {
299 Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
300 if( !isSelected && chosenRelation.isSame(table.getValueAt(row, 0)) )
301 c.setBackground(CHOSEN_RELATION_COLOR);
302 else
303 c.setBackground(table.getBackground());
304 return c;
305 }
306 });
307 columns.getColumn(1).setPreferredWidth(40);
308 columns.getColumn(0).setPreferredWidth(220);
309 relationsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
310 @Override
311 public void valueChanged( ListSelectionEvent e ) {
312 int selectedRow = relationsTable.getSelectedRow();
313 if( selectedRow >= 0 ) {
314 chosenRelation.set((Relation)relationsData.getValueAt(selectedRow, 0));
315 relationsTable.clearSelection();
316 }
317 }
318 });
319 }
320
321 private JComponent sizeButton( JComponent b, int width, int height ) {
322 Dimension pref = b.getPreferredSize();
323 b.setPreferredSize(new Dimension(width <= 0 ? pref.width : width, height <= 0 ? pref.height : height));
324 return b;
325 }
326
327 @Override
328 public void hideNotify() {
329 SelectionEventManager.getInstance().removeSelectionListener(this);
330 MapView.removeEditLayerChangeListener(this);
331 DatasetEventManager.getInstance().removeDatasetListener(chosenRelation);
332 chosenRelation.clear();
333 }
334
335 @Override
336 public void showNotify() {
337 SelectionEventManager.getInstance().addSelectionListener(this, FireMode.IN_EDT_CONSOLIDATED);
338 MapView.addEditLayerChangeListener(this);
339 DatasetEventManager.getInstance().addDatasetListener(chosenRelation, FireMode.IN_EDT);
340 }
341
342 public ChosenRelation getChosenRelation() {
343 return chosenRelation;
344 }
345
346 @Override
347 public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
348 if( chosenRelationPanel != null && Main.pref.getBoolean(PREF_PREFIX + ".hidetopline", false) )
349 chosenRelationPanel.setVisible(newRelation != null);
350 if( Main.main.getCurrentDataSet() != null )
351 selectionChanged(Main.main.getCurrentDataSet().getSelected());
352 roleBoxModel.update();
353 // ?
354 }
355
356 @Override
357 public void selectionChanged( Collection<? extends OsmPrimitive> newSelection ) {
358 if( !isVisible() || relationsData == null )
359 return;
360 roleBoxModel.update();
361 // repopulate relations table
362 relationsData.setRowCount(0);
363 sortAndFixAction.chosenRelationChanged(chosenRelation.get(), chosenRelation.get());
364 if( newSelection == null )
365 return;
366
367 Set<Relation> relations = new TreeSet<>(
368 DefaultNameFormatter.getInstance().getRelationComparator());
369 for( OsmPrimitive element : newSelection ) {
370 for( OsmPrimitive ref : element.getReferrers() ) {
371 if( ref instanceof Relation && !ref.isIncomplete() && !ref.isDeleted() ) {
372 relations.add((Relation) ref);
373 }
374 }
375 }
376
377 for( Relation rel : relations ) {
378 String role = null;
379 for( RelationMember m : rel.getMembers() ) {
380 for( OsmPrimitive element : newSelection ) {
381 if( m.getMember().equals(element) ) {
382 if( role == null )
383 role = m.getRole();
384 else if( !role.equals(m.getRole()) ) {
385 role = tr("<different>");
386 break;
387 }
388 }
389 }
390 }
391 relationsData.addRow(new Object[] {rel, role == null ? "" : role});
392 }
393 for( OsmPrimitive element : newSelection )
394 if( element instanceof Relation && !chosenRelation.isSame(element) )
395 relationsData.addRow(new Object[] {element, ""});
396 }
397
398 private void updateSelection() {
399 if (Main.main.getCurrentDataSet() == null) {
400 selectionChanged(Collections.<OsmPrimitive>emptyList());
401 } else {
402 selectionChanged(Main.main.getCurrentDataSet().getSelected());
403 }
404 }
405
406 @Override
407 public void editLayerChanged( OsmDataLayer oldLayer, OsmDataLayer newLayer ) {
408 updateSelection();
409 }
410
411 @Override
412 public void destroy() {
413 enterRoleAction.destroy();
414 findRelationAction.destroy();
415 createMultipolygonAction.destroy();
416 createRelationAction.destroy();
417 addRemoveMemberAction.destroy();
418 super.destroy();
419 }
420
421 private static final String POSSIBLE_ROLES_FILE = "relcontext/possible_roles.txt";
422 private static final Map<String, List<String>> possibleRoles = loadRoles();
423
424 private static Map<String, List<String>> loadRoles() {
425 Map<String, List<String>> result = new HashMap<>();
426 ClassLoader classLoader = RelContextDialog.class.getClassLoader();
427 try (
428 InputStream possibleRolesStream = classLoader.getResourceAsStream(POSSIBLE_ROLES_FILE);
429 BufferedReader r = new BufferedReader(new InputStreamReader(possibleRolesStream));
430 ) {
431 while( r.ready() ) {
432 String line = r.readLine();
433 StringTokenizer t = new StringTokenizer(line, " ,;:\"");
434 if( t.hasMoreTokens() ) {
435 String type = t.nextToken();
436 List<String> roles = new ArrayList<>();
437 while( t.hasMoreTokens() )
438 roles.add(t.nextToken());
439 result.put(type, roles);
440 }
441 }
442 } catch( Exception e ) {
443 Main.error("[RelToolbox] Error reading possible roles file.");
444 Main.error(e);
445 }
446 return result;
447 }
448
449 private String askForRoleName() {
450 JPanel panel = new JPanel(new GridBagLayout());
451
452 List<String> items = new ArrayList<>();
453 for( String role : roleBoxModel.getRoles() ) {
454 if( role.length() > 1 )
455 items.add(role);
456 }
457 final AutoCompletingComboBox role = new AutoCompletingComboBox();
458 role.setPossibleItems(items);
459 role.setEditable(true);
460
461 panel.add(new JLabel(tr("Role")), GBC.std());
462 panel.add(Box.createHorizontalStrut(10), GBC.std());
463 panel.add(role, GBC.eol().fill(GBC.HORIZONTAL));
464
465 final JOptionPane optionPane = new JOptionPane(panel, JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION) {
466 @Override
467 public void selectInitialValue() {
468 role.requestFocusInWindow();
469 role.getEditor().selectAll();
470 }
471 };
472 final JDialog dlg = optionPane.createDialog(Main.parent, tr("Specify role"));
473 dlg.setModalityType(ModalityType.DOCUMENT_MODAL);
474
475 role.getEditor().addActionListener(new ActionListener() {
476 @Override
477 public void actionPerformed( ActionEvent e ) {
478 dlg.setVisible(false);
479 optionPane.setValue(JOptionPane.OK_OPTION);
480 }
481 });
482
483 dlg.setVisible(true);
484
485 Object answer = optionPane.getValue();
486 if( answer == null || answer == JOptionPane.UNINITIALIZED_VALUE
487 || (answer instanceof Integer && (Integer)answer != JOptionPane.OK_OPTION) ) {
488 return null;
489 }
490
491 return role.getEditor().getItem().toString().trim();
492 }
493
494 private class ChosenRelationMouseAdapter extends MouseAdapter {
495 @Override
496 public void mouseClicked( MouseEvent e ) {
497 if( e.isControlDown() || !(e.getComponent() instanceof JComboBox ) ) // do not use left click handler on combo box
498 if( SwingUtilities.isLeftMouseButton(e) && chosenRelation.get() != null && Main.main.getEditLayer() != null ) {
499 Main.main.getEditLayer().data.setSelected(chosenRelation.get());
500 }
501 }
502
503 @Override
504 public void mousePressed( MouseEvent e ) {
505 checkPopup(e);
506 }
507
508 @Override
509 public void mouseReleased( MouseEvent e ) {
510 checkPopup(e);
511 }
512
513 private void checkPopup( MouseEvent e ) {
514 if( e.isPopupTrigger() && chosenRelation.get() != null ) {
515 popupMenu.show(e.getComponent(), e.getX(), e.getY() - 5);
516 }
517 }
518 }
519
520 private class ChosenRelationPopupMenu extends JPopupMenu {
521 public ChosenRelationPopupMenu( ChosenRelation chosenRelation ) {
522 add(new SelectMembersAction(chosenRelation));
523 add(new SelectRelationAction(chosenRelation));
524 add(new DuplicateChosenRelationAction(chosenRelation));
525 add(new DeleteChosenRelationAction(chosenRelation));
526 add(new DownloadParentsAction(chosenRelation));
527 add(new ReconstructPolygonAction(chosenRelation));
528 addSeparator();
529 add(new SelectInRelationPanelAction(chosenRelation));
530 add(new RelationHelpAction(chosenRelation));
531 }
532 }
533
534 protected void applyRoleToSelection( String role ) {
535 if( chosenRelation != null && chosenRelation.get() != null && Main.main.getCurrentDataSet() != null && !Main.main.getCurrentDataSet().selectionEmpty() ) {
536 Collection<OsmPrimitive> selected = Main.main.getCurrentDataSet().getSelected();
537 Relation r = chosenRelation.get();
538 List<Command> commands = new ArrayList<>();
539 for( int i = 0; i < r.getMembersCount(); i++ ) {
540 RelationMember m = r.getMember(i);
541 if( selected.contains(m.getMember()) ) {
542 if( !role.equals(m.getRole()) ) {
543// r.setMember(i, new RelationMember(role, m.getMember()));
544 commands.add(new ChangeRelationMemberRoleCommand(r, i, role));
545 }
546 }
547 }
548 if( !commands.isEmpty() ) {
549// Main.main.undoRedo.add(new ChangeCommand(chosenRelation.get(), r));
550 Main.main.undoRedo.add(new SequenceCommand(tr("Change relation member roles to {0}", role), commands));
551 }
552 }
553 }
554
555 private static class RelationTableModel extends DefaultTableModel {
556 @Override
557 public boolean isCellEditable(int row, int column) {
558 return false;
559 }
560
561 @Override
562 public Class<?> getColumnClass(int columnIndex) {
563 return columnIndex == 0 ? Relation.class : String.class;
564 }
565 }
566/*
567 private class MultipolygonSettingsAction extends AbstractAction {
568 public MultipolygonSettingsAction() {
569 super();
570 putValue(SMALL_ICON, ImageProvider.get("svpRight"));
571 putValue(SHORT_DESCRIPTION, tr("Change multipolygon creation settings"));
572 }
573
574 public void actionPerformed( ActionEvent e ) {
575 Component c = e.getSource() instanceof Component ? (Component)e.getSource() : Main.parent;
576 multiPopupMenu.show(c, 0, 0);
577 }
578 }*/
579
580 private class MultipolygonSettingsPopup extends JPopupMenu implements ActionListener {
581 public MultipolygonSettingsPopup() {
582 super();
583 addMenuItem("boundary", tr("Create administrative boundary relations"));
584 addMenuItem("boundaryways", tr("Add tags boundary and admin_level to boundary relation ways"));
585 addMenuItem("tags", tr("Move area tags from contour to relation"));
586 addMenuItem("alltags", tr("When moving tags, consider even non-repeating ones"));
587 addMenuItem("allowsplit", tr("Always split ways of neighbouring multipolygons"));
588 }
589
590 protected final JCheckBoxMenuItem addMenuItem( String property, String title ) {
591 String fullProperty = PREF_PREFIX + ".multipolygon." + property;
592 JCheckBoxMenuItem item = new JCheckBoxMenuItem(tr(title));
593 item.setSelected(Main.pref.getBoolean(fullProperty, CreateMultipolygonAction.getDefaultPropertyValue(property)));
594 item.setActionCommand(fullProperty);
595 item.addActionListener(this);
596 add(item);
597 return item;
598 }
599
600 @Override
601 public void actionPerformed( ActionEvent e ) {
602 String property = e.getActionCommand();
603 if( property != null && property.length() > 0 && e.getSource() instanceof JCheckBoxMenuItem ) {
604 boolean value = ((JCheckBoxMenuItem)e.getSource()).isSelected();
605 Main.pref.put(property, value);
606 show(getInvoker(), getX(), getY());
607 }
608 }
609 }
610
611 private class EnterRoleAction extends JosmAction implements ChosenRelationListener {
612
613 public EnterRoleAction() {
614 super(tr("Change role"), (String)null, tr("Enter role for selected members"),
615 Shortcut.registerShortcut("reltoolbox:changerole", tr("Relation Toolbox: {0}", tr("Enter role for selected members")),
616 KeyEvent.VK_R, Shortcut.ALT_CTRL), false, "relcontext/enterrole", true);
617 chosenRelation.addChosenRelationListener(this);
618 updateEnabledState();
619 }
620
621 @Override
622 public void actionPerformed( ActionEvent e ) {
623 if( roleBoxModel.membersRole != null ) {
624 String role = askForRoleName();
625 if( role != null )
626 applyRoleToSelection(role);
627 }
628 }
629
630 @Override
631 public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
632 setEnabled(newRelation != null);
633 }
634 }
635
636 private class RoleComboBoxModel extends AbstractListModel<String> implements ComboBoxModel<String> {
637 private List<String> roles = new ArrayList<>();
638 private int selectedIndex = -1;
639 private JComboBox<String> combobox;
640 private String membersRole;
641 private final String EMPTY_ROLE = tr("<empty>");
642 private final String ANOTHER_ROLE = tr("another...");
643
644 public RoleComboBoxModel( JComboBox<String> combobox ) {
645 super();
646 this.combobox = combobox;
647 update();
648 }
649
650 public void update() {
651 membersRole = getSelectedMembersRoleIntl();
652 if( membersRole == null ) {
653 if( combobox.isEnabled() )
654 combobox.setEnabled(false);
655 return;
656 }
657 if( !combobox.isEnabled() )
658 combobox.setEnabled(true);
659
660 List<String> items = new ArrayList<>();
661 if( chosenRelation != null && chosenRelation.get() != null ) {
662 if( chosenRelation.isMultipolygon() ) {
663 items.add("outer");
664 items.add("inner");
665 }
666 if( chosenRelation.get().get("type") != null ) {
667 List<String> values = possibleRoles.get(chosenRelation.get().get("type"));
668 if( values != null )
669 items.addAll(values);
670 }
671 for( RelationMember m : chosenRelation.get().getMembers() )
672 if( m.getRole().length() > 0 && !items.contains(m.getRole()) )
673 items.add(m.getRole());
674 }
675 items.add(EMPTY_ROLE);
676 if( !items.contains(membersRole) )
677 items.add(0, membersRole);
678 items.add(ANOTHER_ROLE);
679 roles = Collections.unmodifiableList(items);
680
681 if( membersRole != null )
682 setSelectedItem(membersRole);
683 else
684 fireContentsChanged(this, -1, -1);
685 combobox.repaint();
686 }
687
688 public String getSelectedMembersRole() {
689 return membersRole == EMPTY_ROLE ? "" : membersRole;
690 }
691
692 public boolean isAnotherRoleSelected() {
693 return getSelectedRole() != null && getSelectedRole().equals(ANOTHER_ROLE);
694 }
695
696 private String getSelectedMembersRoleIntl() {
697 String role = null;
698 if( chosenRelation != null && chosenRelation.get() != null && Main.main.getCurrentDataSet() != null && !Main.main.getCurrentDataSet().selectionEmpty() ) {
699 Collection<OsmPrimitive> selected = Main.main.getCurrentDataSet().getSelected();
700 for( RelationMember m : chosenRelation.get().getMembers() ) {
701 if( selected.contains(m.getMember()) ) {
702 if( role == null )
703 role = m.getRole();
704 else if( m.getRole() != null && !role.equals(m.getRole()) ) {
705 role = tr("<different>");
706 break;
707 }
708 }
709 }
710 }
711 return role == null ? null : role.length() == 0 ? EMPTY_ROLE : role;
712 }
713
714 public List<String> getRoles() {
715 return roles;
716 }
717
718 @Override
719 public int getSize() {
720 return roles.size();
721 }
722
723 @Override
724 public String getElementAt( int index ) {
725 return getRole(index);
726 }
727
728 public String getRole( int index ) {
729 return roles.get(index);
730 }
731
732 @Override
733 public void setSelectedItem( Object anItem ) {
734 int newIndex = anItem == null ? -1 : roles.indexOf(anItem);
735 if( newIndex != selectedIndex ) {
736 selectedIndex = newIndex;
737 fireContentsChanged(this, -1, -1);
738 }
739 }
740
741 @Override
742 public Object getSelectedItem() {
743 return selectedIndex < 0 || selectedIndex >= getSize() ? null : getRole(selectedIndex);
744 }
745
746 public String getSelectedRole() {
747 String role = selectedIndex < 0 || selectedIndex >= getSize() ? null : getRole(selectedIndex);
748 return role != null && role.equals(EMPTY_ROLE) ? "" : role;
749 }
750 }
751}
Note: See TracBrowser for help on using the repository browser.