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

Last change on this file since 27901 was 27901, checked in by stoecker, 13 years ago

fix warning

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