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 if (task.isCanceled() || task.hasError()) 114 return; 115 model.populate(task.getParents()); 116 }); 117 Main.worker.submit(task); 118 } 119 120 @Override 121 public void contentsChanged(ListDataEvent e) { 122 refreshEnabled(); 123 } 124 125 @Override 126 public void intervalAdded(ListDataEvent e) { 127 refreshEnabled(); 128 } 129 130 @Override 131 public void intervalRemoved(ListDataEvent e) { 132 refreshEnabled(); 133 } 134 } 135 136 /** 137 * Action for editing the currently selected relation 138 * 139 */ 140 class EditAction extends AbstractAction implements ListSelectionListener { 141 EditAction() { 142 putValue(SHORT_DESCRIPTION, tr("Edit the currently selected relation")); 143 new ImageProvider("dialogs", "edit").getResource().attachImageIcon(this); 144 putValue(NAME, tr("Edit")); 145 refreshEnabled(); 146 } 147 148 protected void refreshEnabled() { 149 setEnabled(referrers.getSelectionModel().getMinSelectionIndex() >= 0); 150 } 151 152 @Override 153 public void actionPerformed(ActionEvent e) { 154 run(); 155 } 156 157 public void run() { 158 int idx = referrers.getSelectedIndex(); 159 if (idx < 0) 160 return; 161 Relation r = model.getElementAt(idx); 162 if (r == null) 163 return; 164 RelationEditor editor = RelationEditor.getEditor(getLayer(), r, null); 165 editor.setVisible(true); 166 } 167 168 @Override 169 public void valueChanged(ListSelectionEvent e) { 170 refreshEnabled(); 171 } 172 } 173 174 class DblClickMouseAdapter extends MouseAdapter { 175 @Override 176 public void mouseClicked(MouseEvent e) { 177 if (e.getClickCount() == 2) { 178 editAction.run(); 179 } 180 } 181 } 182}