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

Last change on this file since 26257 was 26125, checked in by zverik, 15 years ago

fixed displaying relations of similar names

File size: 29.0 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 shorcut
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 add(rcPanel, BorderLayout.CENTER);
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 DeleteChosenRelationAction(chosenRelation));
456 add(new DownloadParentsAction(chosenRelation));
457 addSeparator();
458 add(new SelectInRelationPanelAction(chosenRelation));
459 add(new RelationHelpAction(chosenRelation));
460 }
461 }
462
463 protected void applyRoleToSelection( String role ) {
464 if( chosenRelation != null && chosenRelation.get() != null && Main.main.getCurrentDataSet() != null && !Main.main.getCurrentDataSet().selectionEmpty() ) {
465 Collection<OsmPrimitive> selected = Main.main.getCurrentDataSet().getSelected();
466 Relation r = chosenRelation.get();
467 List<Command> commands = new ArrayList<Command>();
468 for( int i = 0; i < r.getMembersCount(); i++ ) {
469 RelationMember m = r.getMember(i);
470 if( selected.contains(m.getMember()) ) {
471 if( !role.equals(m.getRole()) ) {
472// r.setMember(i, new RelationMember(role, m.getMember()));
473 commands.add(new ChangeRelationMemberRoleCommand(r, i, role));
474 }
475 }
476 }
477 if( !commands.isEmpty() ) {
478// Main.main.undoRedo.add(new ChangeCommand(chosenRelation.get(), r));
479 Main.main.undoRedo.add(new SequenceCommand(tr("Change relation member roles to {0}", role), commands));
480 }
481 }
482 }
483
484 private static class RelationTableModel extends DefaultTableModel {
485 @Override
486 public boolean isCellEditable(int row, int column) {
487 return false;
488 }
489
490 @Override
491 public Class<?> getColumnClass(int columnIndex) {
492 return columnIndex == 0 ? Relation.class : String.class;
493 }
494 }
495
496 private class MultipolygonSettingsAction extends AbstractAction {
497 public MultipolygonSettingsAction() {
498 super();
499 putValue(SMALL_ICON, ImageProvider.get("svpRight"));
500 putValue(SHORT_DESCRIPTION, tr("Change multipolygon creation settings"));
501 }
502
503 public void actionPerformed( ActionEvent e ) {
504 Component c = e.getSource() instanceof Component ? (Component)e.getSource() : Main.parent;
505 Point p = getMousePosition();
506 multiPopupMenu.show(c, 0, 0);
507 }
508 }
509
510 private class MultipolygonSettingsPopup extends JPopupMenu implements ActionListener {
511 public MultipolygonSettingsPopup() {
512 super();
513 addMenuItem("boundary", tr("Create administrative boundary relations"));
514 addMenuItem("boundaryways", tr("Add tags boundary and admin_level to boundary relation ways"));
515 addMenuItem("tags", tr("Move area tags from contour to relation"));
516 }
517
518 protected final JCheckBoxMenuItem addMenuItem( String property, String title ) {
519 String fullProperty = PREF_PREFIX + ".multipolygon." + property;
520 JCheckBoxMenuItem item = new JCheckBoxMenuItem(tr(title));
521 item.setSelected(Main.pref.getBoolean(fullProperty, CreateMultipolygonAction.getDefaultPropertyValue(property)));
522 item.setActionCommand(fullProperty);
523 item.addActionListener(this);
524 add(item);
525 return item;
526 }
527
528 public void actionPerformed( ActionEvent e ) {
529 String property = e.getActionCommand();
530 if( property != null && property.length() > 0 && e.getSource() instanceof JCheckBoxMenuItem ) {
531 boolean value = ((JCheckBoxMenuItem)e.getSource()).isSelected();
532 Main.pref.put(property, value);
533 show(getInvoker(), getX(), getY());
534 }
535 }
536 }
537
538 private class EnterRoleAction extends JosmAction implements ChosenRelationListener {
539
540 public EnterRoleAction() {
541 super("…", null, tr("Enter role for selected members"),
542 Shortcut.registerShortcut("reltoolbox:changerole", tr("Relation Toolbox: {0}", tr("Enter role for selected members")),
543 KeyEvent.VK_R, Shortcut.GROUP_EDIT, Shortcut.SHIFT_DEFAULT), true);
544 chosenRelation.addChosenRelationListener(this);
545 updateEnabledState();
546 }
547
548 public void actionPerformed( ActionEvent e ) {
549 if( roleBoxModel.membersRole != null ) {
550 String role = askForRoleName();
551 if( role != null )
552 applyRoleToSelection(role);
553 }
554 }
555
556 public void chosenRelationChanged( Relation oldRelation, Relation newRelation ) {
557 setEnabled(newRelation != null);
558 }
559 }
560
561 private class RoleComboBoxModel extends AbstractListModel implements ComboBoxModel {
562 private List<String> roles = new ArrayList<String>();
563 private int selectedIndex = -1;
564 private JComboBox combobox;
565 private String membersRole;
566 private final String EMPTY_ROLE = tr("<empty>");
567 private final String ANOTHER_ROLE = tr("another...");
568
569 public RoleComboBoxModel( JComboBox combobox ) {
570 super();
571 this.combobox = combobox;
572 update();
573 }
574
575 public void update() {
576 membersRole = getSelectedMembersRoleIntl();
577 if( membersRole == null ) {
578 if( combobox.isEnabled() )
579 combobox.setEnabled(false);
580 return;
581 }
582 if( !combobox.isEnabled() )
583 combobox.setEnabled(true);
584
585 List<String> items = new ArrayList<String>();
586 if( chosenRelation != null && chosenRelation.get() != null ) {
587 if( chosenRelation.isMultipolygon() ) {
588 items.add("outer");
589 items.add("inner");
590 }
591 if( chosenRelation.get().get("type") != null ) {
592 List<String> values = possibleRoles.get(chosenRelation.get().get("type"));
593 if( values != null )
594 items.addAll(values);
595 }
596 for( RelationMember m : chosenRelation.get().getMembers() )
597 if( m.getRole().length() > 0 && !items.contains(m.getRole()) )
598 items.add(m.getRole());
599 }
600 items.add(EMPTY_ROLE);
601 if( !items.contains(membersRole) )
602 items.add(0, membersRole);
603 items.add(ANOTHER_ROLE);
604 roles = Collections.unmodifiableList(items);
605
606 if( membersRole != null )
607 setSelectedItem(membersRole);
608 else
609 fireContentsChanged(this, -1, -1);
610 combobox.repaint();
611 }
612
613 public String getSelectedMembersRole() {
614 return membersRole == EMPTY_ROLE ? "" : membersRole;
615 }
616
617 public boolean isAnotherRoleSelected() {
618 return getSelectedRole() != null && getSelectedRole().equals(ANOTHER_ROLE);
619 }
620
621 private String getSelectedMembersRoleIntl() {
622 String role = null;
623 if( chosenRelation != null && chosenRelation.get() != null && Main.main.getCurrentDataSet() != null && !Main.main.getCurrentDataSet().selectionEmpty() ) {
624 Collection<OsmPrimitive> selected = Main.main.getCurrentDataSet().getSelected();
625 for( RelationMember m : chosenRelation.get().getMembers() ) {
626 if( selected.contains(m.getMember()) ) {
627 if( role == null )
628 role = m.getRole();
629 else if( m.getRole() != null && !role.equals(m.getRole()) ) {
630 role = tr("<different>");
631 break;
632 }
633 }
634 }
635 }
636 return role == null ? null : role.length() == 0 ? EMPTY_ROLE : role;
637 }
638
639 public List<String> getRoles() {
640 return roles;
641 }
642
643 public int getSize() {
644 return roles.size();
645 }
646
647 public Object getElementAt( int index ) {
648 return getRole(index);
649 }
650
651 public String getRole( int index ) {
652 return roles.get(index);
653 }
654
655 public void setSelectedItem( Object anItem ) {
656 int newIndex = anItem == null ? -1 : roles.indexOf(anItem);
657 if( newIndex != selectedIndex ) {
658 selectedIndex = newIndex;
659 fireContentsChanged(this, -1, -1);
660 }
661 }
662
663 public Object getSelectedItem() {
664 return selectedIndex < 0 || selectedIndex >= getSize() ? null : getRole(selectedIndex);
665 }
666
667 public String getSelectedRole() {
668 String role = selectedIndex < 0 || selectedIndex >= getSize() ? null : getRole(selectedIndex);
669 return role != null && role.equals(EMPTY_ROLE) ? "" : role;
670 }
671 }
672}
Note: See TracBrowser for help on using the repository browser.