001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.dialogs.changeset.query; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.BorderLayout; 007import java.awt.GridBagConstraints; 008import java.awt.GridBagLayout; 009import java.awt.Insets; 010import java.awt.event.ItemEvent; 011import java.awt.event.ItemListener; 012import java.util.Arrays; 013import java.util.EnumMap; 014import java.util.Map; 015 016import javax.swing.BorderFactory; 017import javax.swing.ButtonGroup; 018import javax.swing.JCheckBox; 019import javax.swing.JPanel; 020import javax.swing.JRadioButton; 021 022import org.openstreetmap.josm.data.Bounds; 023import org.openstreetmap.josm.data.UserIdentityManager; 024import org.openstreetmap.josm.gui.MainApplication; 025import org.openstreetmap.josm.gui.MapView; 026import org.openstreetmap.josm.gui.widgets.HtmlPanel; 027import org.openstreetmap.josm.io.ChangesetQuery; 028import org.openstreetmap.josm.spi.preferences.Config; 029import org.openstreetmap.josm.tools.GBC; 030import org.openstreetmap.josm.tools.Logging; 031 032/** 033 * This panel presents a list of basic queries for changesets. 034 * @since 2689 035 */ 036public class BasicChangesetQueryPanel extends JPanel { 037 038 /** 039 * Enumeration of basic, predefined queries 040 */ 041 private enum BasicQuery { 042 MOST_RECENT_CHANGESETS, 043 MY_OPEN_CHANGESETS, 044 CHANGESETS_IN_MAP_VIEW; 045 } 046 047 private transient Map<BasicQuery, JRadioButton> rbQueries; 048 private JCheckBox cbMyChangesetsOnly; 049 050 protected JPanel buildQueriesPanel() { 051 JPanel pnl = new JPanel(new GridBagLayout()); 052 053 ButtonGroup bgQueries = new ButtonGroup(); 054 rbQueries = new EnumMap<>(BasicQuery.class); 055 SelectQueryHandler selectedQueryHandler = new SelectQueryHandler(); 056 for (BasicQuery q: BasicQuery.values()) { 057 JRadioButton rb = new JRadioButton(); 058 rb.addItemListener(selectedQueryHandler); 059 rbQueries.put(q, rb); 060 bgQueries.add(rb); 061 } 062 063 GridBagConstraints gc = GBC.eop().fill(GridBagConstraints.HORIZONTAL); 064 // -- most recent changes 065 pnl.add(rbQueries.get(BasicQuery.MOST_RECENT_CHANGESETS), gc); 066 067 // -- most recent changes 068 pnl.add(rbQueries.get(BasicQuery.MY_OPEN_CHANGESETS), gc); 069 070 // -- changesets in map view 071 pnl.add(rbQueries.get(BasicQuery.CHANGESETS_IN_MAP_VIEW), gc); 072 073 // -- checkbox my changesets only 074 gc.gridwidth = 2; 075 gc.insets = new Insets(5, 0, 3, 3); 076 cbMyChangesetsOnly = new JCheckBox(tr("Download my changesets only")); 077 pnl.add(cbMyChangesetsOnly, gc); 078 cbMyChangesetsOnly.setToolTipText( 079 tr("<html>Select to restrict the query to your changesets only.<br>Unselect to include all changesets in the query.</html>")); 080 081 // grab remaining space 082 pnl.add(new JPanel(), GBC.eol().insets(5, 0, 3, 3).fill()); 083 084 return pnl; 085 } 086 087 protected JPanel buildInfoPanel() { 088 HtmlPanel pnlInfos = new HtmlPanel(); 089 pnlInfos.setText(tr("<html>Please select one the following <strong>standard queries</strong>." 090 + "Select <strong>Download my changesets only</strong>" 091 + " if you only want to download changesets created by yourself.<br>" 092 + "Note that JOSM will download max. 100 changesets.</html>") 093 ); 094 return pnlInfos; 095 } 096 097 protected final void build() { 098 setLayout(new BorderLayout(0, 5)); 099 setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 100 add(buildInfoPanel(), BorderLayout.NORTH); 101 add(buildQueriesPanel(), BorderLayout.CENTER); 102 } 103 104 /** 105 * Constructs a new {@code BasicChangesetQueryPanel}. 106 */ 107 public BasicChangesetQueryPanel() { 108 build(); 109 } 110 111 /** 112 * Initializes the panel. 113 */ 114 public void init() { 115 JRadioButton lbl = rbQueries.get(BasicQuery.MOST_RECENT_CHANGESETS); 116 lbl.setText(tr("<html>Download the latest changesets</html>")); 117 118 // query for open changesets only possible if we have a current user which is at least 119 // partially identified 120 lbl = rbQueries.get(BasicQuery.MY_OPEN_CHANGESETS); 121 if (UserIdentityManager.getInstance().isAnonymous()) { 122 rbQueries.get(BasicQuery.MY_OPEN_CHANGESETS).setEnabled(false); 123 lbl.setText(tr("<html>Download my open changesets<br><em>Disabled. " + 124 "Please enter your OSM user name in the preferences first.</em></html>")); 125 } else { 126 rbQueries.get(BasicQuery.MY_OPEN_CHANGESETS).setEnabled(true); 127 lbl.setText(tr("<html>Download my open changesets</html>")); 128 } 129 130 // query for changesets in the current map view only if there *is* a current map view 131 lbl = rbQueries.get(BasicQuery.CHANGESETS_IN_MAP_VIEW); 132 if (!MainApplication.isDisplayingMapView()) { 133 rbQueries.get(BasicQuery.CHANGESETS_IN_MAP_VIEW).setEnabled(false); 134 lbl.setText(tr("<html>Download changesets in the current map view.<br><em>Disabled. " + 135 "There is currently no map view active.</em></html>")); 136 } else { 137 rbQueries.get(BasicQuery.CHANGESETS_IN_MAP_VIEW).setEnabled(true); 138 lbl.setText(tr("<html>Download changesets in the current map view</html>")); 139 } 140 141 restoreFromPreferences(); 142 } 143 144 /** 145 * Remember settings in preferences. 146 */ 147 public void rememberInPreferences() { 148 BasicQuery q = getSelectedQuery(); 149 if (q == null) { 150 Config.getPref().put("changeset-query.basic.query", null); 151 } else { 152 Config.getPref().put("changeset-query.basic.query", q.toString()); 153 } 154 Config.getPref().putBoolean("changeset-query.basic.my-changesets-only", cbMyChangesetsOnly.isSelected()); 155 } 156 157 /** 158 * Restore settings from preferences. 159 */ 160 public void restoreFromPreferences() { 161 BasicQuery q; 162 String value = Config.getPref().get("changeset-query.basic.query", null); 163 if (value == null) { 164 q = BasicQuery.MOST_RECENT_CHANGESETS; 165 } else { 166 try { 167 q = BasicQuery.valueOf(BasicQuery.class, value); 168 } catch (IllegalArgumentException e) { 169 Logging.log(Logging.LEVEL_WARN, tr("Unexpected value for preference ''{0}'', got ''{1}''. Resetting to default query.", 170 "changeset-query.basic.query", value), e); 171 q = BasicQuery.MOST_RECENT_CHANGESETS; 172 } 173 } 174 rbQueries.get(q).setSelected(true); 175 boolean mineOnly = Config.getPref().getBoolean("changeset-query.basic.my-changesets-only", false); 176 mineOnly = mineOnly || q == BasicQuery.MY_OPEN_CHANGESETS; 177 cbMyChangesetsOnly.setSelected(mineOnly); 178 } 179 180 protected BasicQuery getSelectedQuery() { 181 return Arrays.stream(BasicQuery.values()) 182 .filter(q -> rbQueries.get(q).isSelected()) 183 .findFirst().orElse(null); 184 } 185 186 /** 187 * Builds the changeset query. 188 * @return the changeset query 189 */ 190 public ChangesetQuery buildChangesetQuery() { 191 BasicQuery q = getSelectedQuery(); 192 ChangesetQuery query = new ChangesetQuery(); 193 UserIdentityManager im = UserIdentityManager.getInstance(); 194 if (q == null) 195 return query; 196 switch(q) { 197 case MOST_RECENT_CHANGESETS: 198 break; 199 case MY_OPEN_CHANGESETS: 200 query = query.beingOpen(true); 201 break; 202 case CHANGESETS_IN_MAP_VIEW: 203 MapView mapView = MainApplication.getMap().mapView; 204 Bounds b = mapView.getLatLonBounds(mapView.getBounds()); 205 query = query.inBbox(b); 206 break; 207 } 208 209 if (cbMyChangesetsOnly.isSelected()) { 210 if (im.isPartiallyIdentified()) { 211 query = query.forUser(im.getUserName()); 212 } else if (im.isFullyIdentified()) { 213 query = query.forUser(im.getUserId()).beingOpen(true); 214 } else 215 // anonymous -- can happen with a fresh config. 216 throw new IllegalStateException(tr("Cannot create changeset query for open changesets of anonymous user")); 217 } 218 219 return query; 220 } 221 222 /** 223 * Responds to changes in the selected query 224 */ 225 class SelectQueryHandler implements ItemListener { 226 @Override 227 public void itemStateChanged(ItemEvent e) { 228 BasicQuery q = getSelectedQuery(); 229 if (q == null) return; 230 if (q == BasicQuery.MY_OPEN_CHANGESETS) { 231 cbMyChangesetsOnly.setSelected(true); 232 cbMyChangesetsOnly.setEnabled(false); 233 } else { 234 if (!cbMyChangesetsOnly.isEnabled()) { 235 cbMyChangesetsOnly.setEnabled(true); 236 } 237 } 238 } 239 } 240}