/notebooks/visualization/src/org/jetbrains/plugins/notebooks/visualization/r/inlays/table/filters/gui/editor/HistoryListModel.java

https://github.com/JetBrains/intellij-community · Java · 195 lines · 137 code · 30 blank · 28 comment · 33 complexity · 09dabaacbee86109984d1236f1e4d2ba MD5 · raw file

  1. /*
  2. * Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
  3. */
  4. package org.jetbrains.plugins.notebooks.visualization.r.inlays.table.filters.gui.editor;
  5. import org.jetbrains.plugins.notebooks.visualization.r.inlays.table.filters.gui.CustomChoice;
  6. import javax.swing.*;
  7. import java.util.ArrayList;
  8. import java.util.Comparator;
  9. import java.util.List;
  10. /**
  11. * List model to handle the history in the popup menu.<br>
  12. * When the user specifies a Renderer, history elements are considered non-text;
  13. * this affects to the search algorithm to find the best matches {@link
  14. * PopupComponent#selectBestMatch(Object)}<br>
  15. * Otherwise, content is always pure strings (@link {@link CustomChoice} are not
  16. * inserted into the history)
  17. */
  18. class HistoryListModel extends AbstractListModel {
  19. private static final long serialVersionUID = -374115548677017807L;
  20. private final List<Object> history = new ArrayList<>();
  21. private List<Object> shownHistory = history;
  22. private Object lastAdded;
  23. private Comparator<String> stringComparator;
  24. private int maxHistory;
  25. /** Initializes the model to a specific history content */
  26. public void initialize(List<Object> history){
  27. this.lastAdded = null;
  28. this.shownHistory = history;
  29. this.history.clear();
  30. if (!history.isEmpty()){
  31. this.history.addAll(history.subList
  32. (0, Math.min(maxHistory, history.size())));
  33. }
  34. }
  35. /** Returns the items currently visible */
  36. public List<Object> getShownHistory(){
  37. return new ArrayList<>(shownHistory);
  38. }
  39. /**
  40. * Specifies how to handle the content. If there is a string comparator,
  41. * content is handled as strings and it is possible to look for best
  42. * matches; otherwise, it is treated as abstract objects, matching is done
  43. * by identity.
  44. */
  45. public void setStringContent(Comparator<String> stringComparator) {
  46. if (this.stringComparator != stringComparator) {
  47. this.stringComparator = stringComparator;
  48. clear();
  49. }
  50. }
  51. /** Clears any restrictions. {@link #restrict(Object)} */
  52. public int clearRestrictions() {
  53. shownHistory = history;
  54. return shownHistory.size();
  55. }
  56. /** Restricts the elements from the history -without removing it. */
  57. public boolean restrict(Object exclude) {
  58. int index = shownHistory.indexOf(exclude);
  59. if (index != -1) {
  60. if (shownHistory == history) {
  61. shownHistory = new ArrayList<>(history);
  62. }
  63. shownHistory.remove(index);
  64. fireIntervalAdded(this, index, index);
  65. return true;
  66. }
  67. return false;
  68. }
  69. @Override public Object getElementAt(int index) {
  70. return shownHistory.get(index);
  71. }
  72. /** Adds an element, Returning true if the number of elements changes. */
  73. public boolean add(Object st) {
  74. // never add the passed element (which is now selected on the
  75. // editor). We will add it when the next element is passed
  76. boolean ret = false;
  77. boolean removed = history.remove(st);
  78. if ((maxHistory > 0) && (lastAdded != null)
  79. && (lastAdded.toString().length() > 0)
  80. && !lastAdded.equals(st)) {
  81. history.add(0, lastAdded);
  82. int size = history.size();
  83. if (size > maxHistory) {
  84. history.remove(--size);
  85. removed = true;
  86. } else {
  87. ret = true;
  88. if (!removed) {
  89. fireIntervalAdded(this, 0, 0);
  90. }
  91. }
  92. }
  93. if (removed) {
  94. fireContentsChanged(this, 0, history.size());
  95. ret = true;
  96. }
  97. lastAdded = st;
  98. shownHistory = history;
  99. return ret;
  100. }
  101. public boolean isEmpty() {
  102. return shownHistory.isEmpty();
  103. }
  104. public void clear() {
  105. int size = history.size();
  106. if (size > 0) {
  107. history.clear();
  108. shownHistory = history;
  109. fireIntervalRemoved(this, 0, size);
  110. }
  111. lastAdded = null;
  112. }
  113. @Override public int getSize() {
  114. return shownHistory.size();
  115. }
  116. /** Sets the max history size. */
  117. public void setMaxHistory(int size) {
  118. maxHistory = size;
  119. int current = history.size();
  120. if (current > size) {
  121. history.subList(size, current).clear();
  122. shownHistory = history;
  123. fireContentsChanged(this, maxHistory, current);
  124. }
  125. }
  126. /** Returns the max history. */
  127. public int getMaxHistory() {
  128. return maxHistory;
  129. }
  130. /** Returns the history as a list. */
  131. public List getList() {
  132. return history;
  133. }
  134. /** @see PopupComponent#selectBestMatch(Object) */
  135. public ChoiceMatch getClosestMatch(Object hint) {
  136. ChoiceMatch ret = new ChoiceMatch();
  137. if ((stringComparator != null) && (hint instanceof String)) {
  138. String strStart = (String) hint;
  139. int strLen = strStart.length();
  140. int historyLen = shownHistory.size();
  141. while (historyLen-- > 0) {
  142. Object content = shownHistory.get(historyLen);
  143. String str = content.toString();
  144. int len = ChoiceMatch.getMatchingLength(strStart, str,
  145. stringComparator);
  146. if (((len > 0) && (len >= ret.len)) || (ret.len == 0)) {
  147. ret.content = content;
  148. ret.index = historyLen;
  149. ret.len = len;
  150. if ((len == strLen) && (str.length() == strLen)) {
  151. ret.exact = true;
  152. return ret;
  153. }
  154. }
  155. }
  156. } else {
  157. ret.index = shownHistory.indexOf(hint);
  158. if (ret.index != -1) {
  159. ret.exact = true;
  160. ret.content = hint;
  161. }
  162. }
  163. return ret;
  164. }
  165. }