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

Last change on this file since 27927 was 27927, checked in by akks, 13 years ago

reltoolbox, turnlanes: fix shortcut and toolbar warnings

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