| package com.intellij.util.ui; |
| |
| import com.intellij.ide.util.PropertiesComponent; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.util.ArrayUtil; |
| import com.intellij.util.containers.HashMap; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.xml.sax.InputSource; |
| |
| import javax.swing.*; |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import java.io.StringReader; |
| import java.util.Arrays; |
| import java.util.Comparator; |
| import java.util.List; |
| |
| /** |
| * @author Konstantin Bulenkov |
| */ |
| @SuppressWarnings({"UnusedDeclaration"}) |
| public class ComboBoxWithHistory extends JComboBox { |
| private final String myHistoryId; |
| private Project myProject; |
| private final HashMap<Object, Long> myWeights = new HashMap<Object, Long>(); |
| private boolean myAutoSave = true; |
| |
| public ComboBoxWithHistory(@Nullable Project project, String historyId, Object[] items) { |
| super(); |
| myHistoryId = historyId; |
| myProject = project; |
| setModelFrom(items); |
| } |
| |
| public ComboBoxWithHistory(@NotNull String historyId, Object[] items) { |
| this(null, historyId, items); |
| } |
| |
| public ComboBoxWithHistory(String historyId) { |
| this(null, historyId, ArrayUtil.EMPTY_OBJECT_ARRAY); |
| } |
| |
| public void setModelFrom(Object... items) { |
| setModel(new MyModel(items)); |
| } |
| |
| public boolean isAutoSave() { |
| return myAutoSave; |
| } |
| |
| public void setAutoSave(boolean autoSave) { |
| myAutoSave = autoSave; |
| } |
| |
| public void save() { |
| final StringBuilder buf = new StringBuilder("<map>"); |
| for (Object key : myWeights.keySet()) { |
| if (key != null) { |
| final Long value = myWeights.get(key); |
| if (value != null) { |
| buf.append("<element>") |
| .append("<key>").append(key).append("</key>") |
| .append("<value>").append(value).append("</value>") |
| .append("</element>"); |
| } |
| } |
| } |
| |
| final String xml = buf.append("</map>").toString(); |
| |
| if (myProject == null) { |
| PropertiesComponent.getInstance().setValue(myHistoryId, xml); |
| } else { |
| PropertiesComponent.getInstance(myProject).setValue(myHistoryId, xml); |
| } |
| } |
| |
| public void load() { |
| final String xml = myProject == null ? PropertiesComponent.getInstance().getValue(myHistoryId) |
| : PropertiesComponent.getInstance(myProject).getValue(myHistoryId); |
| myWeights.clear(); |
| |
| if (xml == null) return; |
| |
| try { |
| final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); |
| final DocumentBuilder db = dbf.newDocumentBuilder(); |
| final InputSource is = new InputSource(); |
| is.setCharacterStream(new StringReader(xml)); |
| |
| Document doc = db.parse(is); |
| NodeList nodes = doc.getElementsByTagName("map"); |
| if (nodes.getLength() == 1) { |
| final NodeList map = nodes.item(0).getChildNodes(); |
| for (int i = 0; i < map.getLength(); i++) { |
| final Node item = map.item(i); |
| final NodeList list = item.getChildNodes(); |
| final Element key = (Element)list.item(0); |
| final Element value = (Element)list.item(1); |
| myWeights.put(key.getTextContent(), Long.valueOf(value.getTextContent())); |
| } |
| } |
| } |
| catch (Exception e) {// |
| } |
| } |
| |
| public void setProject(Project project) { |
| myProject = project; |
| load(); |
| } |
| |
| private static Object[] sort(final Object[] items, HashMap<Object, Long> weights) { |
| Arrays.sort(items, new LastUsedComparator(weights, Arrays.asList(items))); |
| return items; |
| } |
| |
| |
| private class MyModel extends DefaultComboBoxModel { |
| private MyModel(Object[] items) { |
| super(sort(items, myWeights)); |
| } |
| |
| @Override |
| public void setSelectedItem(Object o) { |
| super.setSelectedItem(o); |
| if (o != null && isAutoSave()) { |
| myWeights.put(o.toString(), System.currentTimeMillis()); |
| save(); |
| } |
| } |
| } |
| |
| private static class LastUsedComparator implements Comparator<Object> { |
| private final HashMap<Object, Long> myWeights; |
| private final List<Object> myInitialPositions; |
| |
| private LastUsedComparator(HashMap<Object, Long> weights, List<Object> initialPositions) { |
| myWeights = weights; |
| myInitialPositions = initialPositions; |
| } |
| |
| @Override |
| public int compare(Object o1, Object o2) { |
| final Long w1 = myWeights.get(o1); |
| final Long w2 = myWeights.get(o2); |
| if (w1 != null || w2 != null) { |
| return w1 != null && w2 != null ? sign(w2 - w1) : w1 != null ? -1 : 1; |
| } |
| return myInitialPositions.indexOf(o1) - myInitialPositions.indexOf(o2); |
| } |
| |
| private static int sign(Long l) { |
| return l == 0 ? 0 : l < 0 ? -1 : 1; |
| } |
| } |
| } |