source: josm/trunk/src/org/openstreetmap/josm/gui/download/BookmarkList.java@ 12620

Last change on this file since 12620 was 12620, checked in by Don-vip, 7 years ago

see #15182 - deprecate all Main logging methods and introduce suitable replacements in Logging for most of them

  • Property svn:eol-style set to native
File size: 14.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.download;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Component;
7import java.awt.GraphicsEnvironment;
8import java.util.ArrayList;
9import java.util.Arrays;
10import java.util.Collection;
11import java.util.Collections;
12import java.util.Comparator;
13import java.util.LinkedList;
14import java.util.List;
15import java.util.Locale;
16import java.util.Objects;
17
18import javax.swing.DefaultListModel;
19import javax.swing.ImageIcon;
20import javax.swing.JLabel;
21import javax.swing.JList;
22import javax.swing.ListCellRenderer;
23import javax.swing.UIManager;
24
25import org.openstreetmap.josm.Main;
26import org.openstreetmap.josm.actions.downloadtasks.ChangesetQueryTask;
27import org.openstreetmap.josm.data.Bounds;
28import org.openstreetmap.josm.data.coor.LatLon;
29import org.openstreetmap.josm.data.osm.Changeset;
30import org.openstreetmap.josm.data.osm.UserInfo;
31import org.openstreetmap.josm.data.preferences.IntegerProperty;
32import org.openstreetmap.josm.data.projection.Projection;
33import org.openstreetmap.josm.data.projection.Projections;
34import org.openstreetmap.josm.gui.JosmUserIdentityManager;
35import org.openstreetmap.josm.gui.MapViewState;
36import org.openstreetmap.josm.gui.dialogs.changeset.ChangesetCacheManager;
37import org.openstreetmap.josm.gui.mappaint.mapcss.Selector;
38import org.openstreetmap.josm.gui.util.GuiHelper;
39import org.openstreetmap.josm.io.ChangesetQuery;
40import org.openstreetmap.josm.tools.ImageProvider;
41import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
42import org.openstreetmap.josm.tools.Logging;
43
44/**
45 * List class that read and save its content from the bookmark file.
46 * @since 6340
47 */
48public class BookmarkList extends JList<BookmarkList.Bookmark> {
49
50 /**
51 * The maximum number of changeset bookmarks to maintain in list.
52 * @since 12495
53 */
54 public static final IntegerProperty MAX_CHANGESET_BOOKMARKS = new IntegerProperty("bookmarks.changesets.max-entries", 15);
55
56 /**
57 * Class holding one bookmarkentry.
58 */
59 public static class Bookmark implements Comparable<Bookmark> {
60 private String name;
61 private Bounds area;
62 private ImageIcon icon;
63
64 /**
65 * Constructs a new {@code Bookmark} with the given contents.
66 * @param list Bookmark contents as a list of 5 elements.
67 * First item is the name, then come bounds arguments (minlat, minlon, maxlat, maxlon)
68 * @throws NumberFormatException if the bounds arguments are not numbers
69 * @throws IllegalArgumentException if list contain less than 5 elements
70 */
71 public Bookmark(Collection<String> list) {
72 List<String> array = new ArrayList<>(list);
73 if (array.size() < 5)
74 throw new IllegalArgumentException(tr("Wrong number of arguments for bookmark"));
75 icon = ImageProvider.get("dialogs", "bookmark");
76 name = array.get(0);
77 area = new Bounds(Double.parseDouble(array.get(1)), Double.parseDouble(array.get(2)),
78 Double.parseDouble(array.get(3)), Double.parseDouble(array.get(4)));
79 }
80
81 /**
82 * Constructs a new empty {@code Bookmark}.
83 */
84 public Bookmark() {
85 this(null, null);
86 }
87
88 /**
89 * Constructs a new unamed {@code Bookmark} for the given area.
90 * @param area The bookmark area
91 */
92 public Bookmark(Bounds area) {
93 this(null, area);
94 }
95
96 /**
97 * Constructs a new {@code Bookmark} for the given name and area.
98 * @param name The bookmark name
99 * @param area The bookmark area
100 * @since 12495
101 */
102 protected Bookmark(String name, Bounds area) {
103 this.icon = ImageProvider.get("dialogs", "bookmark");
104 this.name = name;
105 this.area = area;
106 }
107
108 @Override
109 public String toString() {
110 return name;
111 }
112
113 @Override
114 public int compareTo(Bookmark b) {
115 return name.toLowerCase(Locale.ENGLISH).compareTo(b.name.toLowerCase(Locale.ENGLISH));
116 }
117
118 @Override
119 public int hashCode() {
120 return Objects.hash(name, area);
121 }
122
123 @Override
124 public boolean equals(Object obj) {
125 if (this == obj) return true;
126 if (obj == null || getClass() != obj.getClass()) return false;
127 Bookmark bookmark = (Bookmark) obj;
128 return Objects.equals(name, bookmark.name) &&
129 Objects.equals(area, bookmark.area);
130 }
131
132 /**
133 * Returns the bookmark area
134 * @return The bookmark area
135 */
136 public Bounds getArea() {
137 return area;
138 }
139
140 /**
141 * Returns the bookmark name
142 * @return The bookmark name
143 */
144 public String getName() {
145 return name;
146 }
147
148 /**
149 * Sets the bookmark name
150 * @param name The bookmark name
151 */
152 public void setName(String name) {
153 this.name = name;
154 }
155
156 /**
157 * Sets the bookmark area
158 * @param area The bookmark area
159 */
160 public void setArea(Bounds area) {
161 this.area = area;
162 }
163
164 /**
165 * Returns the bookmark icon.
166 * @return the bookmark icon
167 * @since 12495
168 */
169 public ImageIcon getIcon() {
170 return icon;
171 }
172
173 /**
174 * Sets the bookmark icon.
175 * @param icon the bookmark icon
176 * @since 12495
177 */
178 public void setIcon(ImageIcon icon) {
179 this.icon = icon;
180 }
181 }
182
183 /**
184 * A specific optional bookmark for the "home location" configured on osm.org website.
185 * @since 12495
186 */
187 public static class HomeLocationBookmark extends Bookmark {
188 /**
189 * Constructs a new {@code HomeLocationBookmark}.
190 */
191 public HomeLocationBookmark() {
192 setName(tr("Home location"));
193 setIcon(ImageProvider.get("help", "home", ImageSizes.SMALLICON));
194 UserInfo info = JosmUserIdentityManager.getInstance().getUserInfo();
195 if (info == null) {
196 throw new IllegalStateException("User not identified");
197 }
198 LatLon home = info.getHome();
199 if (home == null) {
200 throw new IllegalStateException("User home location not set");
201 }
202 int zoom = info.getHomeZoom();
203 if (zoom <= 3) {
204 // 3 is the default zoom level in OSM database, but the real zoom level was not correct
205 // for a long time, see https://github.com/openstreetmap/openstreetmap-website/issues/1592
206 zoom = 15;
207 }
208 Projection mercator = Projections.getProjectionByCode("EPSG:3857");
209 setArea(MapViewState.createDefaultState(430, 400) // Size of map on osm.org user profile settings
210 .usingProjection(mercator)
211 .usingScale(Selector.GeneralSelector.level2scale(zoom) / 100)
212 .usingCenter(mercator.latlon2eastNorth(home))
213 .getViewArea()
214 .getLatLonBoundsBox());
215 }
216 }
217
218 /**
219 * A specific optional bookmark for the boundaries of recent changesets.
220 * @since 12495
221 */
222 public static class ChangesetBookmark extends Bookmark {
223 /**
224 * Constructs a new {@code ChangesetBookmark}.
225 * @param cs changeset from which the boundaries are read. Its id, name and comment are used to name the bookmark
226 */
227 public ChangesetBookmark(Changeset cs) {
228 setName(String.format("%d - %tF - %s", cs.getId(), cs.getCreatedAt(), cs.getComment()));
229 setIcon(ImageProvider.get("data", "changeset", ImageSizes.SMALLICON));
230 setArea(cs.getBounds());
231 }
232 }
233
234 /**
235 * Creates a bookmark list as well as the Buttons add and remove.
236 */
237 public BookmarkList() {
238 setModel(new DefaultListModel<Bookmark>());
239 load();
240 setVisibleRowCount(7);
241 setCellRenderer(new BookmarkCellRenderer());
242 }
243
244 /**
245 * Loads the home location bookmark from OSM API,
246 * the manual bookmarks from preferences file,
247 * the changeset bookmarks from changeset cache.
248 */
249 public final void load() {
250 final DefaultListModel<Bookmark> model = (DefaultListModel<Bookmark>) getModel();
251 model.removeAllElements();
252 JosmUserIdentityManager im = JosmUserIdentityManager.getInstance();
253 // Add home location bookmark first, if user fully identified
254 if (im.isFullyIdentified()) {
255 try {
256 model.addElement(new HomeLocationBookmark());
257 } catch (IllegalStateException e) {
258 Logging.info(e.getMessage());
259 Logging.trace(e);
260 }
261 }
262 // Then add manual bookmarks previously saved in local preferences
263 Collection<Collection<String>> args = Main.pref.getArray("bookmarks", null);
264 if (args != null) {
265 List<Bookmark> bookmarks = new LinkedList<>();
266 for (Collection<String> entry : args) {
267 try {
268 bookmarks.add(new Bookmark(entry));
269 } catch (IllegalArgumentException e) {
270 Logging.log(Logging.LEVEL_ERROR, tr("Error reading bookmark entry: %s", e.getMessage()), e);
271 }
272 }
273 Collections.sort(bookmarks);
274 for (Bookmark b : bookmarks) {
275 model.addElement(b);
276 }
277 }
278 // Finally add recent changeset bookmarks, if user name is known
279 final int n = MAX_CHANGESET_BOOKMARKS.get();
280 if (n > 0 && !im.isAnonymous()) {
281 final UserInfo userInfo = im.getUserInfo();
282 if (userInfo != null) {
283 final ChangesetCacheManager ccm = ChangesetCacheManager.getInstance();
284 final int userId = userInfo.getId();
285 int found = 0;
286 for (int i = 0; i < ccm.getModel().getRowCount() && found < n; i++) {
287 Changeset cs = ccm.getModel().getValueAt(i, 0);
288 if (cs.getUser().getId() == userId && cs.getBounds() != null) {
289 model.addElement(new ChangesetBookmark(cs));
290 found++;
291 }
292 }
293 }
294 }
295 }
296
297 /**
298 * Saves all manual bookmarks to the preferences file.
299 */
300 public final void save() {
301 List<Collection<String>> coll = new LinkedList<>();
302 for (Object o : ((DefaultListModel<Bookmark>) getModel()).toArray()) {
303 if (o instanceof HomeLocationBookmark || o instanceof ChangesetBookmark) {
304 continue;
305 }
306 String[] array = new String[5];
307 Bookmark b = (Bookmark) o;
308 array[0] = b.getName();
309 Bounds area = b.getArea();
310 array[1] = String.valueOf(area.getMinLat());
311 array[2] = String.valueOf(area.getMinLon());
312 array[3] = String.valueOf(area.getMaxLat());
313 array[4] = String.valueOf(area.getMaxLon());
314 coll.add(Arrays.asList(array));
315 }
316 Main.pref.putArray("bookmarks", coll);
317 }
318
319 /**
320 * Refreshes the changeset bookmarks.
321 * @since 12495
322 */
323 public void refreshChangesetBookmarks() {
324 final int n = MAX_CHANGESET_BOOKMARKS.get();
325 if (n > 0) {
326 final DefaultListModel<Bookmark> model = (DefaultListModel<Bookmark>) getModel();
327 for (int i = model.getSize() - 1; i >= 0; i--) {
328 if (model.get(i) instanceof ChangesetBookmark) {
329 model.remove(i);
330 }
331 }
332 ChangesetQuery query = ChangesetQuery.forCurrentUser();
333 if (!GraphicsEnvironment.isHeadless()) {
334 final ChangesetQueryTask task = new ChangesetQueryTask(this, query);
335 ChangesetCacheManager.getInstance().runDownloadTask(task);
336 Main.worker.submit(() -> {
337 if (task.isCanceled() || task.isFailed())
338 return;
339 GuiHelper.runInEDT(() -> task.getDownloadedData().stream()
340 .filter(cs -> cs.getBounds() != null)
341 .sorted(Comparator.reverseOrder())
342 .limit(n)
343 .forEachOrdered(cs -> model.addElement(new ChangesetBookmark(cs))));
344 });
345 }
346 }
347 }
348
349 static class BookmarkCellRenderer extends JLabel implements ListCellRenderer<BookmarkList.Bookmark> {
350
351 /**
352 * Constructs a new {@code BookmarkCellRenderer}.
353 */
354 BookmarkCellRenderer() {
355 setOpaque(true);
356 }
357
358 protected void renderColor(boolean selected) {
359 if (selected) {
360 setBackground(UIManager.getColor("List.selectionBackground"));
361 setForeground(UIManager.getColor("List.selectionForeground"));
362 } else {
363 setBackground(UIManager.getColor("List.background"));
364 setForeground(UIManager.getColor("List.foreground"));
365 }
366 }
367
368 protected String buildToolTipText(Bookmark b) {
369 Bounds area = b.getArea();
370 StringBuilder sb = new StringBuilder(128);
371 if (area != null) {
372 sb.append("<html>min[latitude,longitude]=<strong>[")
373 .append(area.getMinLat()).append(',').append(area.getMinLon()).append("]</strong>"+
374 "<br>max[latitude,longitude]=<strong>[")
375 .append(area.getMaxLat()).append(',').append(area.getMaxLon()).append("]</strong>"+
376 "</html>");
377 }
378 return sb.toString();
379 }
380
381 @Override
382 public Component getListCellRendererComponent(JList<? extends Bookmark> list, Bookmark value, int index, boolean isSelected,
383 boolean cellHasFocus) {
384 renderColor(isSelected);
385 setIcon(value.getIcon());
386 setText(value.getName());
387 setToolTipText(buildToolTipText(value));
388 return this;
389 }
390 }
391}
Note: See TracBrowser for help on using the repository browser.