source: josm/trunk/src/org/openstreetmap/josm/gui/widgets/ComboBoxHistory.java@ 18131

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

fix #21215 - fix StackOverflowError in ComboBoxHistory (patch by taylor.smock)

  • Property svn:eol-style set to native
File size: 3.3 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.widgets;
3
4import java.util.ArrayList;
5import java.util.Iterator;
6import java.util.List;
7import java.util.NoSuchElementException;
8
9import javax.swing.DefaultComboBoxModel;
10
11import org.openstreetmap.josm.data.tagging.ac.AutoCompletionItem;
12
13/**
14 * A data model for {@link HistoryComboBox}
15 */
16class ComboBoxHistory extends DefaultComboBoxModel<AutoCompletionItem> implements Iterable<AutoCompletionItem> {
17
18 private final int maxSize;
19
20 /**
21 * Constructs a {@code ComboBoxHistory} keeping track of {@code maxSize} items
22 * @param size the history size
23 */
24 ComboBoxHistory(int size) {
25 maxSize = size;
26 }
27
28 /**
29 * Adds or moves an element to the top of the history
30 * @param s the element to add
31 */
32 public void addElement(String s) {
33 addElement(new AutoCompletionItem(s));
34 }
35
36 /**
37 * Adds or moves an element to the top of the history
38 * @param o the element to add
39 */
40 @Override
41 public void addElement(AutoCompletionItem o) {
42 String newEntry = o.getValue();
43
44 boolean alreadyAdded = false;
45 // if history contains this object already, delete it,
46 // so that it looks like a move to the top
47 for (int i = 0; i < getSize(); i++) {
48 String oldEntry = getElementAt(i).getValue();
49 if (oldEntry.equals(newEntry)) {
50 if (i == 0) {
51 alreadyAdded = true;
52 break;
53 } else {
54 removeElementAt(i);
55 }
56 }
57 }
58
59 if (!alreadyAdded) {
60 // insert element at the top
61 insertElementAt(o, 0);
62 }
63
64 // remove an element, if the history gets too large
65 if (getSize() > maxSize) {
66 removeElementAt(getSize()-1);
67 }
68
69 // set selected item to the one just added
70 setSelectedItem(o);
71 }
72
73 @Override
74 public Iterator<AutoCompletionItem> iterator() {
75 return new Iterator<AutoCompletionItem>() {
76
77 private int position = -1;
78
79 @Override
80 public void remove() {
81 removeElementAt(position);
82 }
83
84 @Override
85 public boolean hasNext() {
86 return position < getSize()-1 && getSize() > 0;
87 }
88
89 @Override
90 public AutoCompletionItem next() {
91 if (!hasNext())
92 throw new NoSuchElementException();
93 position++;
94 return getElementAt(position);
95 }
96 };
97 }
98
99 /**
100 * {@link javax.swing.DefaultComboBoxModel#removeAllElements() Removes all items}
101 * and {@link ComboBoxHistory#addElement(String) adds} the given items.
102 * @param items the items to set
103 */
104 public void setItemsAsString(List<String> items) {
105 removeAllElements();
106 for (int i = items.size()-1; i >= 0; i--) {
107 addElement(items.get(i));
108 }
109 }
110
111 /**
112 * Returns the {@link AutoCompletionItem} items as strings
113 * @return a list of strings
114 */
115 public List<String> asStringList() {
116 List<String> list = new ArrayList<>(maxSize);
117 for (AutoCompletionItem item : this) {
118 list.add(item.getValue());
119 }
120 return list;
121 }
122}
Note: See TracBrowser for help on using the repository browser.