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

Last change on this file since 26290 was 26290, checked in by zverik, 13 years ago

implemented most TODO requests, fixed some bugs

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