mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
Make it faster to edit existing filters
This commit is contained in:
@@ -253,7 +253,7 @@ public class AdvancedSearchFilter<T extends InventoryItem> extends ItemFilter<T>
|
|||||||
FThreads.invokeInBackgroundThread(new Runnable() {
|
FThreads.invokeInBackgroundThread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
final AdvancedSearch.Filter<T> newFilter = AdvancedSearch.getFilter(itemManager.getGenericType());
|
final AdvancedSearch.Filter<T> newFilter = AdvancedSearch.getFilter(itemManager.getGenericType(), filter);
|
||||||
if (newFilter != null) {
|
if (newFilter != null) {
|
||||||
FThreads.invokeInEdtLater(new Runnable() {
|
FThreads.invokeInEdtLater(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import java.util.Arrays;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import com.google.common.base.Function;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import com.google.common.base.Predicate;
|
||||||
|
|
||||||
import forge.card.CardEdition;
|
import forge.card.CardEdition;
|
||||||
import forge.card.CardRarity;
|
import forge.card.CardRarity;
|
||||||
@@ -22,7 +22,7 @@ public class AdvancedSearch {
|
|||||||
private enum FilterOption {
|
private enum FilterOption {
|
||||||
CARD_NAME("Name", PaperCard.class, FilterOperator.STRING_OPS, new StringValueSelector()),
|
CARD_NAME("Name", PaperCard.class, FilterOperator.STRING_OPS, new StringValueSelector()),
|
||||||
CARD_RULES_TEXT("Rules Text", PaperCard.class, FilterOperator.STRING_OPS, new StringValueSelector()),
|
CARD_RULES_TEXT("Rules Text", PaperCard.class, FilterOperator.STRING_OPS, new StringValueSelector()),
|
||||||
CARD_EXPANSION("Expansion", PaperCard.class, FilterOperator.SINGLE_LIST_OPS, new CustomListValueSelector<CardEdition>(FModel.getMagicDb().getSortedEditions())),
|
CARD_SET("Set", PaperCard.class, FilterOperator.SINGLE_LIST_OPS, new CustomListValueSelector<CardEdition>(FModel.getMagicDb().getSortedEditions(), CardEdition.FN_GET_CODE)),
|
||||||
CARD_FORMAT("Format", PaperCard.class, FilterOperator.SINGLE_LIST_OPS, new CustomListValueSelector<GameFormat>((List<GameFormat>)FModel.getFormats().getOrderedList())),
|
CARD_FORMAT("Format", PaperCard.class, FilterOperator.SINGLE_LIST_OPS, new CustomListValueSelector<GameFormat>((List<GameFormat>)FModel.getFormats().getOrderedList())),
|
||||||
CARD_COLOR("Color", PaperCard.class, FilterOperator.MULTI_LIST_OPS, new CustomListValueSelector<String>(MagicColor.Constant.COLORS_AND_COLORLESS)),
|
CARD_COLOR("Color", PaperCard.class, FilterOperator.MULTI_LIST_OPS, new CustomListValueSelector<String>(MagicColor.Constant.COLORS_AND_COLORLESS)),
|
||||||
CARD_TYPE("Type", PaperCard.class, FilterOperator.MULTI_LIST_OPS, new CustomListValueSelector<String>(CardType.getSortedCoreAndSuperTypes())),
|
CARD_TYPE("Type", PaperCard.class, FilterOperator.MULTI_LIST_OPS, new CustomListValueSelector<String>(CardType.getSortedCoreAndSuperTypes())),
|
||||||
@@ -37,9 +37,9 @@ public class AdvancedSearch {
|
|||||||
private final String name;
|
private final String name;
|
||||||
private final Class<? extends InventoryItem> type;
|
private final Class<? extends InventoryItem> type;
|
||||||
private final FilterOperator[] operatorOptions;
|
private final FilterOperator[] operatorOptions;
|
||||||
private final FilterValueSelector<?> valueSelector;
|
private final FilterValueSelector valueSelector;
|
||||||
|
|
||||||
private FilterOption(String name0, Class<? extends InventoryItem> type0, FilterOperator[] operatorOptions0, FilterValueSelector<?> valueSelector0) {
|
private FilterOption(String name0, Class<? extends InventoryItem> type0, FilterOperator[] operatorOptions0, FilterValueSelector valueSelector0) {
|
||||||
name = name0;
|
name = name0;
|
||||||
type = type0;
|
type = type0;
|
||||||
operatorOptions = operatorOptions0;
|
operatorOptions = operatorOptions0;
|
||||||
@@ -114,11 +114,11 @@ public class AdvancedSearch {
|
|||||||
MANY_AND
|
MANY_AND
|
||||||
}
|
}
|
||||||
|
|
||||||
private static abstract class FilterValueSelector<T> {
|
private static abstract class FilterValueSelector {
|
||||||
public abstract List<T> getValues(String message, FilterOption option, FilterOperator operator);
|
public abstract <T extends InventoryItem> Filter<T> createFilter(String message, FilterOption option, FilterOperator operator);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class NumericValueSelector extends FilterValueSelector<Integer> {
|
private static class NumericValueSelector extends FilterValueSelector {
|
||||||
private final int min, max;
|
private final int min, max;
|
||||||
|
|
||||||
public NumericValueSelector(int min0, int max0) {
|
public NumericValueSelector(int min0, int max0) {
|
||||||
@@ -127,7 +127,7 @@ public class AdvancedSearch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Integer> getValues(String message, FilterOption option, FilterOperator operator) {
|
public <T extends InventoryItem> Filter<T> createFilter(String message, FilterOption option, FilterOperator operator) {
|
||||||
String msg = message;
|
String msg = message;
|
||||||
if (operator.valueCount == FilterValueCount.TWO) {
|
if (operator.valueCount == FilterValueCount.TWO) {
|
||||||
msg += " (Lower Bound)";
|
msg += " (Lower Bound)";
|
||||||
@@ -135,55 +135,111 @@ public class AdvancedSearch {
|
|||||||
Integer lowerBound = SGuiChoose.getInteger(msg, min, max);
|
Integer lowerBound = SGuiChoose.getInteger(msg, min, max);
|
||||||
if (lowerBound == null) { return null; }
|
if (lowerBound == null) { return null; }
|
||||||
|
|
||||||
List<Integer> values = new ArrayList<Integer>();
|
final String caption;
|
||||||
values.add(lowerBound);
|
|
||||||
if (operator.valueCount == FilterValueCount.TWO) { //prompt for upper bound if needed
|
if (operator.valueCount == FilterValueCount.TWO) { //prompt for upper bound if needed
|
||||||
msg = message + " (Upper Bound)";
|
msg = message + " (Upper Bound)";
|
||||||
Integer upperBound = SGuiChoose.getInteger(msg, lowerBound, max);
|
Integer upperBound = SGuiChoose.getInteger(msg, lowerBound, max);
|
||||||
if (upperBound == null) { return null; }
|
if (upperBound == null) { return null; }
|
||||||
values.add(upperBound);
|
|
||||||
|
caption = String.format(operator.formatStr, option.name, lowerBound, upperBound);
|
||||||
}
|
}
|
||||||
return values;
|
else {
|
||||||
|
caption = String.format(operator.formatStr, option.name, lowerBound);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Filter<T>(option, operator, caption, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class StringValueSelector extends FilterValueSelector<String> {
|
private static class StringValueSelector extends FilterValueSelector {
|
||||||
public StringValueSelector() {
|
public StringValueSelector() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getValues(String message, FilterOption option, FilterOperator operator) {
|
public <T extends InventoryItem> Filter<T> createFilter(String message, FilterOption option, FilterOperator operator) {
|
||||||
String value = SOptionPane.showInputDialog("", message);
|
String value = SOptionPane.showInputDialog("", message);
|
||||||
if (value == null) { return null; }
|
if (value == null) { return null; }
|
||||||
|
|
||||||
List<String> values = new ArrayList<String>();
|
final String caption = String.format(operator.formatStr, option.name, value);
|
||||||
values.add(value);
|
|
||||||
return values;
|
return new Filter<T>(option, operator, caption, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class CustomListValueSelector<T> extends FilterValueSelector<T> {
|
private static class CustomListValueSelector<V> extends FilterValueSelector {
|
||||||
private final Collection<T> choices;
|
private final Collection<V> choices;
|
||||||
|
private final Function<V, String> toShortString, toLongString;
|
||||||
|
|
||||||
public CustomListValueSelector(Collection<T> choices0) {
|
public CustomListValueSelector(Collection<V> choices0) {
|
||||||
|
this(choices0, null, null);
|
||||||
|
}
|
||||||
|
public CustomListValueSelector(Collection<V> choices0, Function<V, String> toShortString0) {
|
||||||
|
this(choices0, toShortString0, null);
|
||||||
|
}
|
||||||
|
public CustomListValueSelector(Collection<V> choices0, Function<V, String> toShortString0, Function<V, String> toLongString0) {
|
||||||
choices = choices0;
|
choices = choices0;
|
||||||
|
toShortString = toShortString0;
|
||||||
|
toLongString = toLongString0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<T> getValues(String message, FilterOption option, FilterOperator operator) {
|
public <T extends InventoryItem> Filter<T> createFilter(String message, FilterOption option, FilterOperator operator) {
|
||||||
int max = choices.size();
|
int max = choices.size();
|
||||||
if (operator == FilterOperator.IS_EXACTLY && option.operatorOptions == FilterOperator.SINGLE_LIST_OPS) {
|
if (operator == FilterOperator.IS_EXACTLY && option.operatorOptions == FilterOperator.SINGLE_LIST_OPS) {
|
||||||
max = 1;
|
max = 1;
|
||||||
}
|
}
|
||||||
List<T> values = SGuiChoose.getChoices(message, 0, max, choices);
|
List<V> values = SGuiChoose.getChoices(message, 0, max, choices);
|
||||||
if (values == null || values.isEmpty()) {
|
if (values == null || values.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return values;
|
|
||||||
|
String valuesStr;
|
||||||
|
switch (operator.valueCount) {
|
||||||
|
case MANY:
|
||||||
|
valuesStr = formatValues(values, " ", " ");
|
||||||
|
break;
|
||||||
|
case MANY_OR:
|
||||||
|
valuesStr = formatValues(values, ", ", " or ");
|
||||||
|
break;
|
||||||
|
case MANY_AND:
|
||||||
|
default:
|
||||||
|
valuesStr = formatValues(values, ", ", " and ");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
final String caption = String.format(operator.formatStr, option.name, valuesStr);
|
||||||
|
|
||||||
|
return new Filter<T>(option, operator, caption, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatValues(List<V> values, String delim, String finalDelim) {
|
||||||
|
int valueCount = values.size();
|
||||||
|
switch (valueCount) {
|
||||||
|
case 1:
|
||||||
|
return formatValue(values.get(0));
|
||||||
|
case 2:
|
||||||
|
return formatValue(values.get(0)) + finalDelim + " " + formatValue(values.get(1));
|
||||||
|
default:
|
||||||
|
int lastValueIdx = valueCount - 1;
|
||||||
|
String result = formatValue(values.get(0));
|
||||||
|
for (int i = 1; i < lastValueIdx; i++) {
|
||||||
|
result += delim + formatValue(values.get(i));
|
||||||
|
}
|
||||||
|
result += delim.trim() + finalDelim + formatValue(values.get(lastValueIdx));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatValue(V value) {
|
||||||
|
if (toShortString == null) {
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
return toShortString.apply(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends InventoryItem> Filter<T> getFilter(Class<? super T> type) {
|
public static <T extends InventoryItem> Filter<T> getFilter(Class<? super T> type, Filter<T> editFilter) {
|
||||||
//build list of filter options based on ItemManager type
|
//build list of filter options based on ItemManager type
|
||||||
List<FilterOption> options = new ArrayList<FilterOption>();
|
List<FilterOption> options = new ArrayList<FilterOption>();
|
||||||
for (FilterOption opt : FilterOption.values()) {
|
for (FilterOption opt : FilterOption.values()) {
|
||||||
@@ -192,66 +248,38 @@ public class AdvancedSearch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final FilterOption option = SGuiChoose.oneOrNone("Select a filter type", options);
|
final FilterOption defaultOption = editFilter == null ? null : editFilter.option;
|
||||||
|
final FilterOption option = SGuiChoose.oneOrNone("Select a filter type", options, defaultOption, null);
|
||||||
if (option == null) { return null; }
|
if (option == null) { return null; }
|
||||||
|
|
||||||
final FilterOperator operator = SGuiChoose.oneOrNone("Select an operator for " + option.name, option.operatorOptions);
|
final FilterOperator defaultOperator = option == defaultOption ? editFilter.operator : null;
|
||||||
|
final FilterOperator operator = SGuiChoose.oneOrNone("Select an operator for " + option.name, option.operatorOptions, defaultOperator, null);
|
||||||
if (operator == null) { return null; }
|
if (operator == null) { return null; }
|
||||||
|
|
||||||
final String message = option.name + " " + operator.caption + " ?";
|
final String message = option.name + " " + operator.caption + " ?";
|
||||||
final List<?> values = option.valueSelector.getValues(message, option, operator);
|
return option.valueSelector.createFilter(message, option, operator);
|
||||||
if (values == null) { return null; }
|
|
||||||
|
|
||||||
return new Filter<T>(option, operator, values);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Filter<T extends InventoryItem> {
|
public static class Filter<T extends InventoryItem> {
|
||||||
private final FilterOption option;
|
private final FilterOption option;
|
||||||
private final FilterOperator operator;
|
private final FilterOperator operator;
|
||||||
private final List<?> values;
|
|
||||||
private final String caption;
|
private final String caption;
|
||||||
|
private final Predicate<T> predicate;
|
||||||
|
|
||||||
private Filter(FilterOption option0, FilterOperator operator0, List<?> values0) {
|
private Filter(FilterOption option0, FilterOperator operator0, String caption0, Predicate<T> predicate0) {
|
||||||
option = option0;
|
option = option0;
|
||||||
operator = operator0;
|
operator = operator0;
|
||||||
values = values0;
|
caption = caption0;
|
||||||
|
predicate = predicate0;
|
||||||
|
}
|
||||||
|
|
||||||
switch (operator.valueCount) {
|
public Predicate<T> getPredicate() {
|
||||||
case ONE:
|
return predicate;
|
||||||
caption = String.format(operator.formatStr, option.name, values.get(0));
|
|
||||||
break;
|
|
||||||
case TWO:
|
|
||||||
caption = String.format(operator.formatStr, option.name, values.get(0), values.get(1));
|
|
||||||
break;
|
|
||||||
case MANY:
|
|
||||||
caption = String.format(operator.formatStr, option.name, StringUtils.join(values, ", "));
|
|
||||||
break;
|
|
||||||
case MANY_OR:
|
|
||||||
caption = String.format(operator.formatStr, option.name, formatValues(", ", "or"));
|
|
||||||
break;
|
|
||||||
case MANY_AND:
|
|
||||||
default:
|
|
||||||
caption = String.format(operator.formatStr, option.name, formatValues(", ", "and"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return caption;
|
return caption;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String formatValues(String delim, String finalDelim) {
|
|
||||||
switch (values.size()) {
|
|
||||||
case 1:
|
|
||||||
return values.get(0).toString();
|
|
||||||
case 2:
|
|
||||||
return values.get(0) + " " + finalDelim + " " + values.get(1);
|
|
||||||
default:
|
|
||||||
String result = StringUtils.join(values, delim);
|
|
||||||
int index = result.lastIndexOf(delim) + delim.length();
|
|
||||||
return result.substring(0, index) + finalDelim + " " + result.substring(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,18 +29,23 @@ public class SGuiChoose {
|
|||||||
* @see #getChoices(String, int, int, Object...)
|
* @see #getChoices(String, int, int, Object...)
|
||||||
*/
|
*/
|
||||||
public static <T> T oneOrNone(final String message, final T[] choices) {
|
public static <T> T oneOrNone(final String message, final T[] choices) {
|
||||||
|
return oneOrNone(message, choices, null, null);
|
||||||
|
}
|
||||||
|
public static <T> T oneOrNone(final String message, final T[] choices, T selected, Function<T, String> display) {
|
||||||
if ((choices == null) || (choices.length == 0)) {
|
if ((choices == null) || (choices.length == 0)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final List<T> choice = SGuiChoose.getChoices(message, 0, 1, choices);
|
final List<T> choice = SGuiChoose.getChoices(message, 0, 1, choices, selected, display);
|
||||||
return choice.isEmpty() ? null : choice.get(0);
|
return choice.isEmpty() ? null : choice.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> T oneOrNone(final String message, final Collection<T> choices) {
|
public static <T> T oneOrNone(final String message, final Collection<T> choices) {
|
||||||
|
return oneOrNone(message, choices, null, null);
|
||||||
|
}
|
||||||
|
public static <T> T oneOrNone(final String message, final Collection<T> choices, T selected, Function<T, String> display) {
|
||||||
if ((choices == null) || choices.isEmpty()) {
|
if ((choices == null) || choices.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final List<T> choice = SGuiChoose.getChoices(message, 0, 1, choices);
|
final List<T> choice = SGuiChoose.getChoices(message, 0, 1, choices, selected, display);
|
||||||
return choice.isEmpty() ? null : choice.get(0);
|
return choice.isEmpty() ? null : choice.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,11 +148,12 @@ public class SGuiChoose {
|
|||||||
public static <T> List<T> getChoices(final String message, final int min, final int max, final T[] choices) {
|
public static <T> List<T> getChoices(final String message, final int min, final int max, final T[] choices) {
|
||||||
return getChoices(message, min, max, Arrays.asList(choices), null, null);
|
return getChoices(message, min, max, Arrays.asList(choices), null, null);
|
||||||
}
|
}
|
||||||
|
public static <T> List<T> getChoices(final String message, final int min, final int max, final T[] choices, final T selected, final Function<T, String> display) {
|
||||||
|
return getChoices(message, min, max, Arrays.asList(choices), selected, display);
|
||||||
|
}
|
||||||
public static <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices) {
|
public static <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices) {
|
||||||
return getChoices(message, min, max, choices, null, null);
|
return getChoices(message, min, max, choices, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final T selected, final Function<T, String> display) {
|
public static <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final T selected, final Function<T, String> display) {
|
||||||
return GuiBase.getInterface().getChoices(message, min, max, choices, selected, display);
|
return GuiBase.getInterface().getChoices(message, min, max, choices, selected, display);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user