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

Last change on this file since 32075 was 30841, checked in by bastik, 10 years ago

applied #josm10682 - Added features to sorting route relation of public_transport version 2 scheme (patch by freeExec)

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