add filtering in browse host view

auto-update
Zlatin Balevsky 2021-09-07 10:45:29 +01:00
parent 0b2fd2017a
commit a0ce1655ce
No known key found for this signature in database
GPG Key ID: A72832072D525E41
3 changed files with 142 additions and 23 deletions

View File

@ -1,5 +1,6 @@
package com.muwire.gui
import com.muwire.core.SplitPattern
import griffon.core.artifact.GriffonController
import griffon.core.controller.ControllerAction
import griffon.inject.MVCMember
@ -9,7 +10,6 @@ import net.i2p.data.Base64
import javax.annotation.Nonnull
import com.muwire.core.Core
import com.muwire.core.EventBus
import com.muwire.core.download.UIDownloadEvent
import com.muwire.core.search.BrowseStatus
import com.muwire.core.search.BrowseStatusEvent
@ -17,8 +17,12 @@ import com.muwire.core.search.UIBrowseEvent
import com.muwire.core.search.UIResultBatchEvent
import com.muwire.core.search.UIResultEvent
import javax.swing.JTextField
@ArtifactProviderFor(GriffonController)
class BrowseController {
@MVCMember @Nonnull
FactoryBuilderSupport builder
@MVCMember @Nonnull
BrowseModel model
@MVCMember @Nonnull
@ -44,6 +48,8 @@ class BrowseController {
return
runInsideUIAsync {
model.status = e.status
model.filterEnabled = (e.status == BrowseStatus.FINISHED || e.status == BrowseStatus.FAILED) &&
model.resultCount > 0
if (e.status == BrowseStatus.FETCHING)
model.totalResults = e.totalResults
}
@ -54,23 +60,35 @@ class BrowseController {
if (e.uuid != model.uuid)
return
model.chatActionEnabled = e.results[0].chat
model.results.addAll(e.results.toList())
List<UIResultEvent> results = e.results.toList()
model.results.addAll(results)
synchronized (model.allResults) {
model.allResults.addAll(results)
}
model.resultCount = model.results.size()
int [] selectedRows = view.resultsTable.getSelectedRows()
if (view.lastSortEvent != null) {
for (int i = 0; i < selectedRows.length; i ++)
selectedRows[i] = view.resultsTable.rowSorter.convertRowIndexToModel(selectedRows[i])
view.refreshResults()
}
view.resultsTable.model.fireTableDataChanged()
if (view.lastSortEvent != null) {
for (int i = 0; i < selectedRows.length; i ++)
selectedRows[i] = view.resultsTable.rowSorter.convertRowIndexToView(selectedRows[i])
}
for (int row : selectedRows)
view.resultsTable.selectionModel.addSelectionInterval(row, row)
@ControllerAction
void filter() {
JTextField field = builder.getVariable("filter-field")
String filter = field.getText()
if (filter == null)
return
filter = filter.strip().replaceAll(SplitPattern.SPLIT_PATTERN," ").toLowerCase()
String [] split = filter.split(" ")
def hs = new HashSet()
split.each {if (it.length() > 0) hs << it}
model.filter = hs.toArray(new String[0])
model.filterResults()
}
@ControllerAction
void clearFilter() {
model.filter = null
model.filterResults()
}
@ControllerAction

View File

@ -1,15 +1,22 @@
package com.muwire.gui
import com.muwire.core.Persona
import com.muwire.core.search.UIResultEvent
import griffon.core.artifact.GriffonModel
import griffon.inject.MVCMember
import griffon.transform.Observable
import griffon.metadata.ArtifactProviderFor
import com.muwire.core.search.BrowseStatus
import javax.annotation.Nonnull
import javax.swing.SwingWorker
@ArtifactProviderFor(GriffonModel)
class BrowseModel {
@MVCMember @Nonnull
BrowseView view
Persona host
@Observable BrowseStatus status
@Observable boolean downloadActionEnabled
@ -19,7 +26,71 @@ class BrowseModel {
@Observable boolean chatActionEnabled
@Observable int totalResults
@Observable int resultCount
@Observable boolean filterEnabled
volatile UUID uuid
def results = []
List<UIResultEvent> allResults = []
volatile String[] filter
volatile Filterer filterer
private boolean filter(UIResultEvent result) {
if (filter == null)
return true
String name = result.getName().toLowerCase()
boolean contains = true
for (String keyword : filter) {
contains &= name.contains(keyword)
}
contains
}
void filterResults() {
results.clear()
filterer?.cancel()
if (filter != null) {
filterer = new Filterer()
filterer.execute()
} else {
synchronized (allResults) {
results.addAll(allResults)
}
view.refreshResults()
}
}
private class Filterer extends SwingWorker<List<UIResultEvent>, UIResultEvent> {
private volatile boolean cancelled;
void cancel() {
cancelled = true
}
@Override
protected List<UIResultEvent> doInBackground() throws Exception {
synchronized (allResults) {
for (UIResultEvent result : allResults) {
if (cancelled)
break
if (filter(result))
publish(result)
}
}
}
@Override
protected void process(List<UIResultEvent> chunks) {
if (cancelled)
return
results.addAll(chunks)
}
@Override
protected void done() {
if (cancelled)
return
view.refreshResults()
}
}
}

View File

@ -1,6 +1,10 @@
package com.muwire.gui
import com.muwire.core.search.BrowseStatus
import griffon.core.artifact.GriffonView
import javax.swing.JTextField
import static com.muwire.gui.Translator.trans
import griffon.inject.MVCMember
import griffon.metadata.ArtifactProviderFor
@ -63,13 +67,25 @@ class BrowseView {
}
}
panel (constraints : BorderLayout.SOUTH) {
gridLayout(rows: 1, cols: 3)
panel(border: etchedBorder()) {
button(text: trans("DOWNLOAD"), enabled: bind { model.downloadActionEnabled }, downloadAction)
label(text: trans("DOWNLOAD_SEQUENTIALLY"), enabled: bind {model.downloadActionEnabled})
sequentialDownloadCheckbox = checkBox(enabled: bind {model.downloadActionEnabled})
}
panel(border: etchedBorder()) {
button(text: trans("VIEW_COMMENT"), enabled: bind { model.viewCommentActionEnabled }, viewCommentAction)
button(text: trans("VIEW_CERTIFICATES"), enabled: bind { model.viewCertificatesActionEnabled }, viewCertificatesAction)
button(text: trans("VIEW_COLLECTIONS"), enabled: bind { model.viewCollectionsActionEnabled }, viewCollectionsAction)
button(text: trans("CHAT"), enabled: bind { model.chatActionEnabled }, chatAction)
label(text : trans("DOWNLOAD_SEQUENTIALLY"))
sequentialDownloadCheckbox = checkBox()
}
panel(border: etchedBorder()) {
def textField = new JTextField(15)
textField.addActionListener({ controller.filter() })
widget(id: "filter-field", enabled: bind { model.filterEnabled }, textField)
button(text: trans("FILTER"), enabled: bind { model.filterEnabled }, filterAction)
button(text: trans("CLEAR"), enabled: bind { model.filterEnabled }, clearFilterAction)
}
}
}
@ -217,6 +233,20 @@ class BrowseView {
parent.setTabComponentAt(index, tabPanel)
}
void refreshResults() {
int [] selectedRows = resultsTable.getSelectedRows()
if (lastSortEvent != null) {
for (int i = 0; i < selectedRows.length; i ++)
selectedRows[i] = resultsTable.rowSorter.convertRowIndexToModel(selectedRows[i])
}
resultsTable.model.fireTableDataChanged()
if (lastSortEvent != null) {
for (int i = 0; i < selectedRows.length; i ++)
selectedRows[i] = resultsTable.rowSorter.convertRowIndexToView(selectedRows[i])
}
for (int row : selectedRows)
resultsTable.selectionModel.addSelectionInterval(row, row)
}
def selectedResults() {
int [] rows = resultsTable.getSelectedRows()