hiscore panel: autocomplete recent search history
Co-authored-by: Daniel <serpa88@hotmail.ca>
This commit is contained in:
@@ -121,6 +121,7 @@ public class HiscorePanel extends PluginPanel
|
|||||||
private Client client;
|
private Client client;
|
||||||
|
|
||||||
private final HiscoreConfig config;
|
private final HiscoreConfig config;
|
||||||
|
private final NameAutocompleter nameAutocompleter;
|
||||||
|
|
||||||
private final IconTextField searchBar;
|
private final IconTextField searchBar;
|
||||||
|
|
||||||
@@ -141,10 +142,11 @@ public class HiscorePanel extends PluginPanel
|
|||||||
private boolean loading = false;
|
private boolean loading = false;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public HiscorePanel(HiscoreConfig config)
|
public HiscorePanel(HiscoreConfig config, NameAutocompleter nameAutocompleter)
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
this.nameAutocompleter = nameAutocompleter;
|
||||||
|
|
||||||
// The layout seems to be ignoring the top margin and only gives it
|
// The layout seems to be ignoring the top margin and only gives it
|
||||||
// a 2-3 pixel margin, so I set the value to 18 to compensate
|
// a 2-3 pixel margin, so I set the value to 18 to compensate
|
||||||
@@ -295,6 +297,13 @@ public class HiscorePanel extends PluginPanel
|
|||||||
|
|
||||||
add(bossPanel, c);
|
add(bossPanel, c);
|
||||||
c.gridy++;
|
c.gridy++;
|
||||||
|
|
||||||
|
addInputKeyListener(nameAutocompleter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void shutdown()
|
||||||
|
{
|
||||||
|
removeInputKeyListener(nameAutocompleter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -418,6 +427,8 @@ public class HiscorePanel extends PluginPanel
|
|||||||
searchBar.setEditable(true);
|
searchBar.setEditable(true);
|
||||||
loading = false;
|
loading = false;
|
||||||
|
|
||||||
|
nameAutocompleter.addToSearchHistory(result.getPlayer().toLowerCase());
|
||||||
|
|
||||||
for (Map.Entry<HiscoreSkill, JLabel> entry : skillLabels.entrySet())
|
for (Map.Entry<HiscoreSkill, JLabel> entry : skillLabels.entrySet())
|
||||||
{
|
{
|
||||||
HiscoreSkill skill = entry.getKey();
|
HiscoreSkill skill = entry.getKey();
|
||||||
|
|||||||
@@ -41,12 +41,12 @@ import net.runelite.api.Client;
|
|||||||
import net.runelite.api.MenuAction;
|
import net.runelite.api.MenuAction;
|
||||||
import net.runelite.api.MenuEntry;
|
import net.runelite.api.MenuEntry;
|
||||||
import net.runelite.api.events.ChatMessage;
|
import net.runelite.api.events.ChatMessage;
|
||||||
import net.runelite.client.events.ConfigChanged;
|
|
||||||
import net.runelite.api.events.MenuEntryAdded;
|
import net.runelite.api.events.MenuEntryAdded;
|
||||||
import net.runelite.api.events.PlayerMenuOptionClicked;
|
import net.runelite.api.events.PlayerMenuOptionClicked;
|
||||||
import net.runelite.api.widgets.WidgetInfo;
|
import net.runelite.api.widgets.WidgetInfo;
|
||||||
import net.runelite.client.config.ConfigManager;
|
import net.runelite.client.config.ConfigManager;
|
||||||
import net.runelite.client.eventbus.Subscribe;
|
import net.runelite.client.eventbus.Subscribe;
|
||||||
|
import net.runelite.client.events.ConfigChanged;
|
||||||
import net.runelite.client.menus.MenuManager;
|
import net.runelite.client.menus.MenuManager;
|
||||||
import net.runelite.client.plugins.Plugin;
|
import net.runelite.client.plugins.Plugin;
|
||||||
import net.runelite.client.plugins.PluginDescriptor;
|
import net.runelite.client.plugins.PluginDescriptor;
|
||||||
@@ -88,9 +88,6 @@ public class HiscorePlugin extends Plugin
|
|||||||
private NavigationButton navButton;
|
private NavigationButton navButton;
|
||||||
private HiscorePanel hiscorePanel;
|
private HiscorePanel hiscorePanel;
|
||||||
|
|
||||||
@Inject
|
|
||||||
private NameAutocompleter autocompleter;
|
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
HiscoreConfig provideConfig(ConfigManager configManager)
|
HiscoreConfig provideConfig(ConfigManager configManager)
|
||||||
{
|
{
|
||||||
@@ -117,16 +114,12 @@ public class HiscorePlugin extends Plugin
|
|||||||
{
|
{
|
||||||
menuManager.get().addPlayerMenuItem(LOOKUP);
|
menuManager.get().addPlayerMenuItem(LOOKUP);
|
||||||
}
|
}
|
||||||
if (config.autocomplete())
|
|
||||||
{
|
|
||||||
hiscorePanel.addInputKeyListener(autocompleter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void shutDown() throws Exception
|
protected void shutDown() throws Exception
|
||||||
{
|
{
|
||||||
hiscorePanel.removeInputKeyListener(autocompleter);
|
hiscorePanel.shutdown();
|
||||||
clientToolbar.removeNavigation(navButton);
|
clientToolbar.removeNavigation(navButton);
|
||||||
|
|
||||||
if (client != null)
|
if (client != null)
|
||||||
@@ -149,18 +142,6 @@ public class HiscorePlugin extends Plugin
|
|||||||
menuManager.get().addPlayerMenuItem(LOOKUP);
|
menuManager.get().addPlayerMenuItem(LOOKUP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.getKey().equals("autocomplete"))
|
|
||||||
{
|
|
||||||
if (config.autocomplete())
|
|
||||||
{
|
|
||||||
hiscorePanel.addInputKeyListener(autocompleter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hiscorePanel.removeInputKeyListener(autocompleter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.hiscore;
|
package net.runelite.client.plugins.hiscore;
|
||||||
|
|
||||||
|
import com.google.common.collect.EvictingQueue;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
import java.awt.event.KeyListener;
|
import java.awt.event.KeyListener;
|
||||||
@@ -32,10 +33,12 @@ import java.util.Objects;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import javax.inject.Singleton;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.text.BadLocationException;
|
import javax.swing.text.BadLocationException;
|
||||||
import javax.swing.text.Document;
|
import javax.swing.text.Document;
|
||||||
import javax.swing.text.JTextComponent;
|
import javax.swing.text.JTextComponent;
|
||||||
|
import lombok.NonNull;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.runelite.api.ClanMemberManager;
|
import net.runelite.api.ClanMemberManager;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
@@ -45,6 +48,7 @@ import net.runelite.api.NameableContainer;
|
|||||||
import net.runelite.api.Player;
|
import net.runelite.api.Player;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@Singleton
|
||||||
class NameAutocompleter implements KeyListener
|
class NameAutocompleter implements KeyListener
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@@ -57,7 +61,12 @@ class NameAutocompleter implements KeyListener
|
|||||||
*/
|
*/
|
||||||
private static final Pattern INVALID_CHARS = Pattern.compile("[^a-zA-Z0-9_ -]");
|
private static final Pattern INVALID_CHARS = Pattern.compile("[^a-zA-Z0-9_ -]");
|
||||||
|
|
||||||
|
private static final int MAX_SEARCH_HISTORY = 25;
|
||||||
|
|
||||||
private final Client client;
|
private final Client client;
|
||||||
|
private final HiscoreConfig hiscoreConfig;
|
||||||
|
|
||||||
|
private final EvictingQueue<String> searchHistory = EvictingQueue.create(MAX_SEARCH_HISTORY);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name currently being autocompleted.
|
* The name currently being autocompleted.
|
||||||
@@ -70,9 +79,10 @@ class NameAutocompleter implements KeyListener
|
|||||||
private Pattern autocompleteNamePattern;
|
private Pattern autocompleteNamePattern;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private NameAutocompleter(@Nullable Client client)
|
private NameAutocompleter(@Nullable Client client, HiscoreConfig hiscoreConfig)
|
||||||
{
|
{
|
||||||
this.client = client;
|
this.client = client;
|
||||||
|
this.hiscoreConfig = hiscoreConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -90,6 +100,11 @@ class NameAutocompleter implements KeyListener
|
|||||||
@Override
|
@Override
|
||||||
public void keyTyped(KeyEvent e)
|
public void keyTyped(KeyEvent e)
|
||||||
{
|
{
|
||||||
|
if (!hiscoreConfig.autocomplete())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final JTextComponent input = (JTextComponent)e.getSource();
|
final JTextComponent input = (JTextComponent)e.getSource();
|
||||||
final String inputText = input.getText();
|
final String inputText = input.getText();
|
||||||
|
|
||||||
@@ -189,17 +204,22 @@ class NameAutocompleter implements KeyListener
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
autocompleteName = Optional.empty();
|
// Search all previous successful queries
|
||||||
|
autocompleteName = searchHistory.stream()
|
||||||
|
.filter(n -> pattern.matcher(n).matches())
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
// TODO: Search lookup history
|
// Search friends if previous searches weren't matched
|
||||||
|
if (!autocompleteName.isPresent())
|
||||||
NameableContainer<Friend> friendContainer = client.getFriendContainer();
|
|
||||||
if (friendContainer != null)
|
|
||||||
{
|
{
|
||||||
autocompleteName = Arrays.stream(friendContainer.getMembers())
|
NameableContainer<Friend> friendContainer = client.getFriendContainer();
|
||||||
.map(Nameable::getName)
|
if (friendContainer != null)
|
||||||
.filter(n -> pattern.matcher(n).matches())
|
{
|
||||||
.findFirst();
|
autocompleteName = Arrays.stream(friendContainer.getMembers())
|
||||||
|
.map(Nameable::getName)
|
||||||
|
.filter(n -> pattern.matcher(n).matches())
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search clan if a friend wasn't found
|
// Search clan if a friend wasn't found
|
||||||
@@ -241,6 +261,14 @@ class NameAutocompleter implements KeyListener
|
|||||||
return autocompleteName.isPresent();
|
return autocompleteName.isPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addToSearchHistory(@NonNull String name)
|
||||||
|
{
|
||||||
|
if (!searchHistory.contains(name))
|
||||||
|
{
|
||||||
|
searchHistory.offer(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isExpectedNext(JTextComponent input, String nextChar)
|
private boolean isExpectedNext(JTextComponent input, String nextChar)
|
||||||
{
|
{
|
||||||
String expected;
|
String expected;
|
||||||
|
|||||||
@@ -27,15 +27,14 @@ package net.runelite.client.plugins.hiscore;
|
|||||||
import static net.runelite.client.plugins.hiscore.HiscorePanel.formatLevel;
|
import static net.runelite.client.plugins.hiscore.HiscorePanel.formatLevel;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
public class HiscorePanelTest
|
public class HiscorePanelTest
|
||||||
{
|
{
|
||||||
@Test
|
@Test
|
||||||
public void testConstructor()
|
public void testConstructor()
|
||||||
{
|
{
|
||||||
new HiscorePanel(new HiscoreConfig()
|
new HiscorePanel(mock(HiscoreConfig.class), mock(NameAutocompleter.class));
|
||||||
{
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user