better search box
This commit is contained in:
@@ -78,10 +78,10 @@ class MuWireSettings {
|
||||
totalUploadSlots = Integer.valueOf(props.getProperty("totalUploadSlots","-1"))
|
||||
uploadSlotsPerUser = Integer.valueOf(props.getProperty("uploadSlotsPerUser","-1"))
|
||||
|
||||
watchedDirectories = readEncodedSet(props, "watchedDirectories")
|
||||
watchedKeywords = readEncodedSet(props, "watchedKeywords")
|
||||
watchedRegexes = readEncodedSet(props, "watchedRegexes")
|
||||
negativeFileTree = readEncodedSet(props, "negativeFileTree")
|
||||
watchedDirectories = DataUtil.readEncodedSet(props, "watchedDirectories")
|
||||
watchedKeywords = DataUtil.readEncodedSet(props, "watchedKeywords")
|
||||
watchedRegexes = DataUtil.readEncodedSet(props, "watchedRegexes")
|
||||
negativeFileTree = DataUtil.readEncodedSet(props, "negativeFileTree")
|
||||
|
||||
trustSubscriptions = new HashSet<>()
|
||||
if (props.containsKey("trustSubscriptions")) {
|
||||
@@ -125,10 +125,10 @@ class MuWireSettings {
|
||||
props.setProperty("totalUploadSlots", String.valueOf(totalUploadSlots))
|
||||
props.setProperty("uploadSlotsPerUser", String.valueOf(uploadSlotsPerUser))
|
||||
|
||||
writeEncodedSet(watchedDirectories, "watchedDirectories", props)
|
||||
writeEncodedSet(watchedKeywords, "watchedKeywords", props)
|
||||
writeEncodedSet(watchedRegexes, "watchedRegexes", props)
|
||||
writeEncodedSet(negativeFileTree, "negativeFileTree", props)
|
||||
DataUtil.writeEncodedSet(watchedDirectories, "watchedDirectories", props)
|
||||
DataUtil.writeEncodedSet(watchedKeywords, "watchedKeywords", props)
|
||||
DataUtil.writeEncodedSet(watchedRegexes, "watchedRegexes", props)
|
||||
DataUtil.writeEncodedSet(negativeFileTree, "negativeFileTree", props)
|
||||
|
||||
if (!trustSubscriptions.isEmpty()) {
|
||||
String encoded = trustSubscriptions.stream().
|
||||
@@ -139,24 +139,6 @@ class MuWireSettings {
|
||||
|
||||
props.store(out, "This file is UTF-8")
|
||||
}
|
||||
|
||||
private static Set<String> readEncodedSet(Properties props, String property) {
|
||||
Set<String> rv = new ConcurrentHashSet<>()
|
||||
if (props.containsKey(property)) {
|
||||
String[] encoded = props.getProperty(property).split(",")
|
||||
encoded.each { rv << DataUtil.readi18nString(Base64.decode(it)) }
|
||||
}
|
||||
rv
|
||||
}
|
||||
|
||||
private static void writeEncodedSet(Set<String> set, String property, Properties props) {
|
||||
if (set.isEmpty())
|
||||
return
|
||||
String encoded = set.stream().
|
||||
map({Base64.encode(DataUtil.encodei18nString(it))}).
|
||||
collect(Collectors.joining(","))
|
||||
props.setProperty(property, encoded)
|
||||
}
|
||||
|
||||
boolean isLeaf() {
|
||||
isLeaf
|
||||
|
@@ -11,10 +11,14 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.muwire.core.Constants;
|
||||
|
||||
import net.i2p.data.Base64;
|
||||
import net.i2p.util.ConcurrentHashSet;
|
||||
|
||||
public class DataUtil {
|
||||
|
||||
@@ -165,4 +169,22 @@ public class DataUtil {
|
||||
} catch(Exception ex) { }
|
||||
cb = null;
|
||||
}
|
||||
|
||||
public static Set<String> readEncodedSet(Properties props, String property) {
|
||||
Set<String> rv = new ConcurrentHashSet<>();
|
||||
if (props.containsKey(property)) {
|
||||
String [] encoded = props.getProperty(property).split(",");
|
||||
for(String s : encoded)
|
||||
rv.add(readi18nString(Base64.decode(s)));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static void writeEncodedSet(Set<String> set, String property, Properties props) {
|
||||
if (set.isEmpty())
|
||||
return;
|
||||
String encoded = set.stream().map(s -> Base64.encode(encodei18nString(s)))
|
||||
.collect(Collectors.joining(","));
|
||||
props.setProperty(property, encoded);
|
||||
}
|
||||
}
|
||||
|
@@ -11,6 +11,7 @@ import net.i2p.crypto.DSAEngine
|
||||
import net.i2p.data.Base64
|
||||
import net.i2p.data.Signature
|
||||
|
||||
import java.awt.event.ActionEvent
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
import javax.annotation.Nonnull
|
||||
@@ -51,11 +52,16 @@ class MainFrameController {
|
||||
private volatile Core core
|
||||
|
||||
@ControllerAction
|
||||
void search() {
|
||||
void search(ActionEvent evt) {
|
||||
if (evt.getActionCommand() == null)
|
||||
return
|
||||
def cardsPanel = builder.getVariable("cards-panel")
|
||||
cardsPanel.getLayout().show(cardsPanel, "search window")
|
||||
|
||||
def search = builder.getVariable("search-field").text
|
||||
def searchField = builder.getVariable("search-field")
|
||||
def search = searchField.getSelectedItem()
|
||||
searchField.model.addElement(search)
|
||||
|
||||
search = search.trim()
|
||||
if (search.length() == 0)
|
||||
return
|
||||
|
@@ -11,6 +11,7 @@ import net.i2p.data.DataHelper
|
||||
import javax.swing.BorderFactory
|
||||
import javax.swing.Box
|
||||
import javax.swing.BoxLayout
|
||||
import javax.swing.JComboBox
|
||||
import javax.swing.JFileChooser
|
||||
import javax.swing.JFrame
|
||||
import javax.swing.JLabel
|
||||
@@ -24,6 +25,8 @@ import javax.swing.SwingConstants
|
||||
import javax.swing.SwingUtilities
|
||||
import javax.swing.TransferHandler
|
||||
import javax.swing.border.Border
|
||||
import javax.swing.event.DocumentEvent
|
||||
import javax.swing.event.DocumentListener
|
||||
import javax.swing.event.TreeExpansionEvent
|
||||
import javax.swing.event.TreeExpansionListener
|
||||
import javax.swing.table.DefaultTableCellRenderer
|
||||
@@ -135,7 +138,11 @@ class MainFrameView {
|
||||
panel(constraints: BorderLayout.CENTER) {
|
||||
borderLayout()
|
||||
label(" Enter search here:", constraints: BorderLayout.WEST) // TODO: fix this
|
||||
textField(id: "search-field", constraints: BorderLayout.CENTER, action : searchAction)
|
||||
|
||||
def searchFieldModel = new SearchFieldModel(settings, new File(application.context.get("muwire-home")))
|
||||
JComboBox myComboBox = new SearchField(searchFieldModel)
|
||||
myComboBox.setAction(searchAction)
|
||||
widget(id: "search-field", constraints: BorderLayout.CENTER, myComboBox)
|
||||
|
||||
}
|
||||
panel( constraints: BorderLayout.EAST) {
|
||||
@@ -484,6 +491,10 @@ class MainFrameView {
|
||||
}
|
||||
}})
|
||||
|
||||
// search field
|
||||
def searchField = builder.getVariable("search-field")
|
||||
|
||||
// downloads table
|
||||
def downloadsTable = builder.getVariable("downloads-table")
|
||||
def selectionModel = downloadsTable.getSelectionModel()
|
||||
selectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION)
|
||||
|
14
gui/src/main/groovy/com/muwire/gui/SearchField.groovy
Normal file
14
gui/src/main/groovy/com/muwire/gui/SearchField.groovy
Normal file
@@ -0,0 +1,14 @@
|
||||
package com.muwire.gui
|
||||
|
||||
import java.awt.event.KeyEvent
|
||||
|
||||
import javax.swing.JComboBox
|
||||
|
||||
class SearchField extends JComboBox {
|
||||
SearchField(SearchFieldModel model) {
|
||||
super()
|
||||
setEditable(true)
|
||||
setModel(model)
|
||||
setEditor(new SearchFieldEditor(model, this))
|
||||
}
|
||||
}
|
47
gui/src/main/groovy/com/muwire/gui/SearchFieldEditor.groovy
Normal file
47
gui/src/main/groovy/com/muwire/gui/SearchFieldEditor.groovy
Normal file
@@ -0,0 +1,47 @@
|
||||
package com.muwire.gui
|
||||
|
||||
import javax.swing.JTextField
|
||||
import javax.swing.SwingUtilities
|
||||
import javax.swing.event.DocumentEvent
|
||||
import javax.swing.event.DocumentListener
|
||||
import javax.swing.plaf.basic.BasicComboBoxEditor
|
||||
|
||||
class SearchFieldEditor extends BasicComboBoxEditor {
|
||||
|
||||
private final SearchFieldModel model
|
||||
private final SearchField field
|
||||
|
||||
SearchFieldEditor(SearchFieldModel model, SearchField field) {
|
||||
super()
|
||||
this.model = model
|
||||
this.field = field
|
||||
def action = field.getAction()
|
||||
field.setAction(null)
|
||||
editor.setAction(action)
|
||||
editor.getDocument().addDocumentListener(new DocumentListener() {
|
||||
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
SwingUtilities.invokeLater({
|
||||
field.hidePopup()
|
||||
if (model.onKeyStroke(editor.text))
|
||||
field.showPopup()
|
||||
})
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
SwingUtilities.invokeLater({
|
||||
field.hidePopup()
|
||||
if (model.onKeyStroke(editor.text))
|
||||
field.showPopup()
|
||||
})
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
96
gui/src/main/groovy/com/muwire/gui/SearchFieldModel.groovy
Normal file
96
gui/src/main/groovy/com/muwire/gui/SearchFieldModel.groovy
Normal file
@@ -0,0 +1,96 @@
|
||||
package com.muwire.gui
|
||||
|
||||
import javax.swing.AbstractListModel
|
||||
import javax.swing.MutableComboBoxModel
|
||||
|
||||
class SearchFieldModel extends AbstractListModel implements MutableComboBoxModel {
|
||||
private final UISettings uiSettings
|
||||
private final File settingsFile
|
||||
private final List<String> objects = new ArrayList<>()
|
||||
private String selectedObject
|
||||
|
||||
SearchFieldModel(UISettings uiSettings, File home) {
|
||||
super()
|
||||
this.uiSettings = uiSettings
|
||||
this.settingsFile = new File(home, "gui.properties")
|
||||
uiSettings.searchHistory.each { objects.add(it) }
|
||||
fireIntervalAdded(this, 0, objects.size() - 1)
|
||||
}
|
||||
|
||||
public void addElement(Object string) {
|
||||
if (!uiSettings.searchHistory.add(string))
|
||||
return
|
||||
settingsFile.withOutputStream { uiSettings.write(it) }
|
||||
objects.add(string);
|
||||
fireIntervalAdded(this,objects.size()-1, objects.size()-1);
|
||||
if ( objects.size() == 1 && selectedObject == null && string != null ) {
|
||||
setSelectedItem( string );
|
||||
}
|
||||
}
|
||||
|
||||
boolean onKeyStroke(String selected) {
|
||||
selectedObject = selected
|
||||
if (selected == null || selected.length() == 0) {
|
||||
objects.clear()
|
||||
uiSettings.searchHistory.each { objects.add(it) }
|
||||
return true
|
||||
}
|
||||
|
||||
objects.clear()
|
||||
|
||||
Set<String> matching = new HashSet<>(uiSettings.searchHistory)
|
||||
matching.retainAll { it.contains(selected) }
|
||||
|
||||
matching.each {
|
||||
objects.add(it)
|
||||
}
|
||||
Collections.sort(objects)
|
||||
if (!objects.isEmpty()) {
|
||||
fireIntervalAdded(this, 0, objects.size() - 1)
|
||||
return true
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectedItem(Object anObject) {
|
||||
if ((selectedObject != null && !selectedObject.equals( anObject )) ||
|
||||
selectedObject == null && anObject != null) {
|
||||
selectedObject = anObject;
|
||||
fireContentsChanged(this, -1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSelectedItem() {
|
||||
selectedObject
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
objects.size()
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElementAt(int index) {
|
||||
if ( index >= 0 && index < objects.size() )
|
||||
return objects.get(index);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeElement(Object obj) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertElementAt(Object item, int index) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeElementAt(int index) {
|
||||
|
||||
}
|
||||
}
|
@@ -1,5 +1,7 @@
|
||||
package com.muwire.gui
|
||||
|
||||
import com.muwire.core.util.DataUtil
|
||||
|
||||
class UISettings {
|
||||
|
||||
String lnf
|
||||
@@ -14,6 +16,7 @@ class UISettings {
|
||||
boolean closeWarning
|
||||
boolean exitOnClose
|
||||
boolean clearUploads
|
||||
Set<String> searchHistory
|
||||
|
||||
UISettings(Properties props) {
|
||||
lnf = props.getProperty("lnf", "system")
|
||||
@@ -28,6 +31,8 @@ class UISettings {
|
||||
closeWarning = Boolean.parseBoolean(props.getProperty("closeWarning","true"))
|
||||
exitOnClose = Boolean.parseBoolean(props.getProperty("exitOnClose","false"))
|
||||
clearUploads = Boolean.parseBoolean(props.getProperty("clearUploads","false"))
|
||||
|
||||
searchHistory = DataUtil.readEncodedSet(props, "searchHistory")
|
||||
}
|
||||
|
||||
void write(OutputStream out) throws IOException {
|
||||
@@ -46,6 +51,7 @@ class UISettings {
|
||||
if (font != null)
|
||||
props.setProperty("font", font)
|
||||
|
||||
DataUtil.writeEncodedSet(searchHistory, "searchHistory", props)
|
||||
|
||||
props.store(out, "UI Properties")
|
||||
}
|
||||
|
Reference in New Issue
Block a user