001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.dialogs.relation; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.BorderLayout; 007import java.awt.FlowLayout; 008import java.awt.event.ActionEvent; 009import java.awt.event.MouseAdapter; 010import java.awt.event.MouseEvent; 011 012import javax.swing.AbstractAction; 013import javax.swing.JButton; 014import javax.swing.JCheckBox; 015import javax.swing.JList; 016import javax.swing.JPanel; 017import javax.swing.JScrollPane; 018import javax.swing.ListSelectionModel; 019import javax.swing.event.ListDataEvent; 020import javax.swing.event.ListDataListener; 021import javax.swing.event.ListSelectionEvent; 022import javax.swing.event.ListSelectionListener; 023 024import org.openstreetmap.josm.Main; 025import org.openstreetmap.josm.data.osm.Relation; 026import org.openstreetmap.josm.gui.OsmPrimitivRenderer; 027import org.openstreetmap.josm.gui.layer.OsmDataLayer; 028import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor; 029import org.openstreetmap.josm.tools.ImageProvider; 030 031/** 032 * This is browser for a list of relations which refer to another relations. 033 * @since 1806 034 */ 035public class ReferringRelationsBrowser extends JPanel { 036 037 /** the list of relations */ 038 private JList<Relation> referrers; 039 private final ReferringRelationsBrowserModel model; 040 private final transient OsmDataLayer layer; 041 private final JCheckBox cbReadFull = new JCheckBox(tr("including immediate children of parent relations")); 042 private EditAction editAction; 043 044 /** 045 * Constructs a new {@code ReferringRelationsBrowser}. 046 * @param layer OSM data layer 047 * @param model referrinf relations browser model 048 */ 049 public ReferringRelationsBrowser(OsmDataLayer layer, ReferringRelationsBrowserModel model) { 050 this.model = model; 051 this.layer = layer; 052 build(); 053 } 054 055 /** 056 * build the GUI 057 */ 058 protected void build() { 059 setLayout(new BorderLayout()); 060 referrers = new JList<>(model); 061 referrers.setCellRenderer(new OsmPrimitivRenderer()); 062 add(new JScrollPane(referrers), BorderLayout.CENTER); 063 referrers.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 064 referrers.addMouseListener(new DblClickMouseAdapter()); 065 066 JPanel pnl = new JPanel(new FlowLayout(FlowLayout.LEFT)); 067 068 ReloadAction reloadAction = new ReloadAction(); 069 referrers.getModel().addListDataListener(reloadAction); 070 pnl.add(new JButton(reloadAction)); 071 pnl.add(cbReadFull); 072 073 editAction = new EditAction(); 074 referrers.getSelectionModel().addListSelectionListener(editAction); 075 pnl.add(new JButton(editAction)); 076 add(pnl, BorderLayout.SOUTH); 077 } 078 079 public void init() { 080 model.populate(getLayer().data); 081 } 082 083 protected OsmDataLayer getLayer() { 084 return layer; 085 } 086 087 /** 088 * Action for loading the parent relations of a relation 089 * 090 */ 091 class ReloadAction extends AbstractAction implements ListDataListener { 092 ReloadAction() { 093 putValue(SHORT_DESCRIPTION, tr("Load parent relations")); 094 new ImageProvider("dialogs", "refresh").getResource().attachImageIcon(this); 095 putValue(NAME, tr("Reload")); 096 refreshEnabled(); 097 } 098 099 protected void refreshEnabled() { 100 setEnabled(model.canReload()); 101 } 102 103 @Override 104 public void actionPerformed(ActionEvent e) { 105 boolean full = cbReadFull.isSelected(); 106 final ParentRelationLoadingTask task = new ParentRelationLoadingTask( 107 model.getRelation(), 108 getLayer(), 109 full, 110 new PleaseWaitProgressMonitor(tr("Loading parent relations")) 111 ); 112 task.setContinuation( 113 new Runnable() { 114 @Override 115 public void run() { 116 if (task.isCanceled() || task.hasError()) 117 return; 118 model.populate(task.getParents()); 119 } 120 } 121 ); 122 Main.worker.submit(task); 123 } 124 125 @Override 126 public void contentsChanged(ListDataEvent e) { 127 refreshEnabled(); 128 } 129 130 @Override 131 public void intervalAdded(ListDataEvent e) { 132 refreshEnabled(); 133 } 134 135 @Override 136 public void intervalRemoved(ListDataEvent e) { 137 refreshEnabled(); 138 } 139 } 140 141 /** 142 * Action for editing the currently selected relation 143 * 144 */ 145 class EditAction extends AbstractAction implements ListSelectionListener { 146 EditAction() { 147 putValue(SHORT_DESCRIPTION, tr("Edit the currently selected relation")); 148 new ImageProvider("dialogs", "edit").getResource().attachImageIcon(this); 149 putValue(NAME, tr("Edit")); 150 refreshEnabled(); 151 } 152 153 protected void refreshEnabled() { 154 setEnabled(referrers.getSelectionModel().getMinSelectionIndex() >= 0); 155 } 156 157 @Override 158 public void actionPerformed(ActionEvent e) { 159 run(); 160 } 161 162 public void run() { 163 int idx = referrers.getSelectedIndex(); 164 if (idx < 0) 165 return; 166 Relation r = model.getElementAt(idx); 167 if (r == null) 168 return; 169 RelationEditor editor = RelationEditor.getEditor(getLayer(), r, null); 170 editor.setVisible(true); 171 } 172 173 @Override 174 public void valueChanged(ListSelectionEvent e) { 175 refreshEnabled(); 176 } 177 } 178 179 class DblClickMouseAdapter extends MouseAdapter { 180 @Override 181 public void mouseClicked(MouseEvent e) { 182 if (e.getClickCount() == 2) { 183 editAction.run(); 184 } 185 } 186 } 187}