JAL-2484 added improvement to enable clearing cache items and configuring maximum...
[jalview.git] / src / jalview / io / cache / JvCacheableInputBox.java
index 55254c5..3eb193e 100644 (file)
@@ -1,5 +1,11 @@
 package jalview.io.cache;
 
+import jalview.util.MessageManager;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.LinkedHashSet;
@@ -7,7 +13,15 @@ import java.util.List;
 import java.util.Set;
 
 import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JTextField;
 import javax.swing.SwingUtilities;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.PlainDocument;
 
 public class JvCacheableInputBox<E> extends JComboBox<String>
 {
@@ -18,6 +32,20 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
 
   private AppCache appCache;
 
+  JPanel pnlDefaultCache = new JPanel();
+
+  JLabel lblDefaultCacheSize = new JLabel();
+
+  JTextField txtDefaultCacheSize = new JTextField();
+
+  JPopupMenu popup = new JPopupMenu();
+
+  JMenuItem menuItemClearCache = new JMenuItem();
+
+  final static int INPUT_LIMIT = 2;
+
+  final static String SPACE = "    ";
+
   public JvCacheableInputBox(String cacheKey)
   {
     super();
@@ -25,12 +53,61 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
     setEditable(true);
     setPrototypeDisplayValue("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
     appCache = AppCache.getInstance();
+    initCachePopupMenu();
     appCache.initCache(cacheKey);
     updateCache();
   }
 
 
   /**
+   * Initialise this cache's pop-up menu
+   */
+  private void initCachePopupMenu()
+  {
+    add(popup);
+    setComponentPopupMenu(popup);
+    pnlDefaultCache.setBackground(Color.WHITE);
+    txtDefaultCacheSize.setPreferredSize(new Dimension(45, 20));
+    lblDefaultCacheSize.setText(SPACE
+            + MessageManager.getString("label.default_cache_size"));
+    // Force input to accept only Integer entries up to length - INPUT_LIMIT
+    txtDefaultCacheSize.setDocument(new PlainDocument()
+    {
+      private static final long serialVersionUID = 1L;
+
+      @Override
+      public void insertString(int offs, String str, AttributeSet a)
+              throws BadLocationException
+      {
+        if (getLength() + str.length() <= INPUT_LIMIT && isInteger(str))
+        {
+          super.insertString(offs, str, a);
+        }
+      }
+    });
+    txtDefaultCacheSize.setText(appCache.getCacheLmit(cacheKey));
+    pnlDefaultCache.add(lblDefaultCacheSize);
+    pnlDefaultCache.add(txtDefaultCacheSize);
+    popup.insert(pnlDefaultCache, 0);
+
+    menuItemClearCache.setText(MessageManager
+            .getString("action.clear_cached_items"));
+    menuItemClearCache.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        System.out.println(">>>>> Clear cache items");
+        setSelectedItem("");
+        appCache.deleteCacheItems(cacheKey);
+        updateCache();
+      }
+    });
+
+    popup.add(menuItemClearCache);
+  }
+
+  /**
    * Answers true if input text is an integer
    * 
    * @param text
@@ -58,6 +135,8 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
       @Override
       public void run()
       {
+        int cacheLimit = appCache.updateCacheLimit(cacheKey,
+                txtDefaultCacheSize.getText());
         String userInput = getUserInput();
         if (userInput != null && !userInput.isEmpty())
         {
@@ -84,12 +163,34 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
         {
           addItem("");
         }
+
         if (reversedCacheItems != null && !reversedCacheItems.isEmpty())
         {
+          LinkedHashSet<String> foundCache = appCache
+                  .getAllCachedItemsFor(cacheKey);
+          boolean prune = reversedCacheItems.size() > cacheLimit;
+          int count = 1;
+          boolean limitExceeded = false;
           for (String cacheItem : reversedCacheItems)
           {
-            addItem(cacheItem);
+            limitExceeded = (count++ > cacheLimit);
+            if (prune)
+            {
+              if (limitExceeded)
+              {
+                foundCache.remove(cacheItem);
+              }
+              else
+              {
+                addItem(cacheItem);
+              }
+            }
+            else
+            {
+              addItem(cacheItem);
+            }
           }
+          appCache.putCache(cacheKey, foundCache);
         }
         setSelectedItem(lastSearch.isEmpty() ? "" : lastSearch);
       }
@@ -97,6 +198,21 @@ public class JvCacheableInputBox<E> extends JComboBox<String>
   }
 
 
+  /**
+   * This method should be called to persist the in-memory cache when this
+   * components parent frame is closed / exited
+   */
+  public void persistCache()
+  {
+    appCache.persistCache(cacheKey);
+    appCache.updateCacheLimit(cacheKey, txtDefaultCacheSize.getText());
+  }
+
+  /**
+   * Method to obtain input text from the cache box
+   * 
+   * @return
+   */
   public String getUserInput()
   {
     return getEditor().getItem() == null ? "" : getEditor().getItem()