Support editing individual filters via menu

This commit is contained in:
drdev
2015-09-20 16:32:37 +00:00
parent b3ae6ef349
commit 22bfc9f1e3
3 changed files with 98 additions and 49 deletions

View File

@@ -5,10 +5,12 @@ import com.google.common.base.Predicate;
import forge.Forge; import forge.Forge;
import forge.assets.FSkinImage; import forge.assets.FSkinImage;
import forge.assets.TextRenderer;
import forge.interfaces.IButton; import forge.interfaces.IButton;
import forge.item.InventoryItem; import forge.item.InventoryItem;
import forge.itemmanager.AdvancedSearch; import forge.itemmanager.AdvancedSearch;
import forge.itemmanager.ItemManager; import forge.itemmanager.ItemManager;
import forge.itemmanager.AdvancedSearch.IFilterControl;
import forge.menu.FMenuItem; import forge.menu.FMenuItem;
import forge.menu.FPopupMenu; import forge.menu.FPopupMenu;
import forge.menu.FTooltip; import forge.menu.FTooltip;
@@ -81,6 +83,15 @@ public class AdvancedSearchFilter<T extends InventoryItem> extends ItemFilter<T>
label.setSize(width, height); label.setSize(width, height);
} }
private final Runnable onFilterChange = new Runnable() {
@Override
public void run() {
//update expression when edit screen closed or a single filter is changed
model.updateExpression();
itemManager.applyNewOrModifiedFilter(AdvancedSearchFilter.this);
}
};
private class FiltersLabel extends FLabel { private class FiltersLabel extends FLabel {
private String toolTipText; private String toolTipText;
@@ -103,13 +114,24 @@ public class AdvancedSearchFilter<T extends InventoryItem> extends ItemFilter<T>
FPopupMenu menu = new FPopupMenu() { FPopupMenu menu = new FPopupMenu() {
@Override @Override
protected void buildMenu() { protected void buildMenu() {
addItem(new FMenuItem("Edit Advanced Search", FSkinImage.EDIT, new FEventHandler() { //add a menu item for each filter to allow easily editing just that filter
for (final IFilterControl<T> control : model.getControls()) {
FMenuItem item = new FMenuItem(control.getFilter().toString(), FSkinImage.EDIT, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
model.editFilterControl(control, onFilterChange);
}
});
item.setTextRenderer(new TextRenderer()); //ensure symbols are displayed
addItem(item);
}
addItem(new FMenuItem("Edit Expression", FSkinImage.EDIT, new FEventHandler() {
@Override @Override
public void handleEvent(FEvent e) { public void handleEvent(FEvent e) {
edit(); edit();
} }
})); }));
addItem(new FMenuItem("Clear Advanced Search", FSkinImage.DELETE, new FEventHandler() { addItem(new FMenuItem("Remove Filter", FSkinImage.DELETE, new FEventHandler() {
@Override @Override
public void handleEvent(FEvent e) { public void handleEvent(FEvent e) {
reset(); reset();
@@ -161,9 +183,7 @@ public class AdvancedSearchFilter<T extends InventoryItem> extends ItemFilter<T>
@Override @Override
public void onClose(Callback<Boolean> canCloseCallback) { public void onClose(Callback<Boolean> canCloseCallback) {
//update expression when screen closed onFilterChange.run();
model.updateExpression();
itemManager.applyNewOrModifiedFilter(AdvancedSearchFilter.this);
super.onClose(canCloseCallback); super.onClose(canCloseCallback);
} }

View File

@@ -9,6 +9,7 @@ import forge.UiCommand;
import forge.assets.FImage; import forge.assets.FImage;
import forge.assets.FSkinColor; import forge.assets.FSkinColor;
import forge.assets.FSkinFont; import forge.assets.FSkinFont;
import forge.assets.TextRenderer;
import forge.assets.FSkinColor.Colors; import forge.assets.FSkinColor.Colors;
import forge.assets.FSkinProp; import forge.assets.FSkinProp;
import forge.interfaces.IButton; import forge.interfaces.IButton;
@@ -36,6 +37,7 @@ public class FMenuItem extends FDisplayObject implements IButton {
private final FEventHandler handler; private final FEventHandler handler;
private boolean pressed, allowForIcon, selected, tabMode; private boolean pressed, allowForIcon, selected, tabMode;
private float textWidth; private float textWidth;
private TextRenderer textRenderer;
public FMenuItem(String text0, FEventHandler handler0) { public FMenuItem(String text0, FEventHandler handler0) {
this(text0, null, handler0, true); this(text0, null, handler0, true);
@@ -71,6 +73,10 @@ public class FMenuItem extends FDisplayObject implements IButton {
tabMode = tabMode0; tabMode = tabMode0;
} }
public void setTextRenderer(TextRenderer textRenderer0) {
textRenderer = textRenderer0;
}
public float getMinWidth() { public float getMinWidth() {
//pretend there's a divot even if there isn't to provide extra right padding and allow menu items to line up nicer //pretend there's a divot even if there isn't to provide extra right padding and allow menu items to line up nicer
float width = textWidth + DIVOT_WIDTH + 4 * GAP_X; float width = textWidth + DIVOT_WIDTH + 4 * GAP_X;
@@ -128,7 +134,12 @@ public class FMenuItem extends FDisplayObject implements IButton {
x += ICON_SIZE + GAP_X; x += ICON_SIZE + GAP_X;
} }
g.drawText(text, FONT, FORE_COLOR, x, 0, w - x - GAP_X, h, false, HAlignment.LEFT, true); if (textRenderer == null) {
g.drawText(text, FONT, FORE_COLOR, x, 0, w - x - GAP_X, h, false, HAlignment.LEFT, true);
}
else {
textRenderer.drawText(g, text, FONT, FORE_COLOR, x, 0, w - x - GAP_X, h, 0, h, false, HAlignment.LEFT, true);
}
//draw separator line //draw separator line
if (tabMode) { if (tabMode) {

View File

@@ -837,21 +837,26 @@ public class AdvancedSearch {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T extends InventoryItem> Filter<T> getFilter(Class<? super T> type, Filter<T> editFilter) { public static <T extends InventoryItem> Filter<T> getFilter(Class<? super T> type, Filter<T> editFilter, boolean reselectOption) {
//build list of filter options based on ItemManager type final FilterOption option;
List<FilterOption> options = new ArrayList<FilterOption>();
if (editFilter != null) {
options.add(FilterOption.NONE); //provide option to clear existing filter
}
for (FilterOption opt : FilterOption.values()) {
if (opt.type == type) {
options.add(opt);
}
}
final FilterOption defaultOption = editFilter == null ? null : editFilter.option; final FilterOption defaultOption = editFilter == null ? null : editFilter.option;
final FilterOption option = SGuiChoose.oneOrNone("Select a filter type", options, defaultOption, null); if (defaultOption == null || reselectOption) {
if (option == null) { return editFilter; } //build list of filter options based on ItemManager type
List<FilterOption> options = new ArrayList<FilterOption>();
if (editFilter != null) {
options.add(FilterOption.NONE); //provide option to clear existing filter
}
for (FilterOption opt : FilterOption.values()) {
if (opt.type == type) {
options.add(opt);
}
}
option = SGuiChoose.oneOrNone("Select a filter type", options, defaultOption, null);
if (option == null) { return editFilter; }
}
else {
option = defaultOption;
}
if (option == FilterOption.NONE) { return null; } //allow user to clear filter by selecting "(none)" if (option == FilterOption.NONE) { return null; } //allow user to clear filter by selecting "(none)"
@@ -928,6 +933,8 @@ public class AdvancedSearch {
} }
public static class Model<T extends InventoryItem> { public static class Model<T extends InventoryItem> {
private static final String EMPTY_FILTER_TEXT = "Select Filter...";
private final List<Object> expression = new ArrayList<Object>(); private final List<Object> expression = new ArrayList<Object>();
private final List<IFilterControl<T>> controls = new ArrayList<IFilterControl<T>>(); private final List<IFilterControl<T>> controls = new ArrayList<IFilterControl<T>>();
private IButton label; private IButton label;
@@ -1002,42 +1009,16 @@ public class AdvancedSearch {
@SuppressWarnings("serial") @SuppressWarnings("serial")
public void addFilterControl(final IFilterControl<T> control) { public void addFilterControl(final IFilterControl<T> control) {
final String emptyFilterText = "Select Filter..."; control.getBtnFilter().setText(EMPTY_FILTER_TEXT);
control.getBtnFilter().setText(emptyFilterText);
control.getBtnFilter().setCommand(new UiCommand() { control.getBtnFilter().setCommand(new UiCommand() {
@Override @Override
public void run() { public void run() {
FThreads.invokeInBackgroundThread(new Runnable() { editFilterControl(control, null);
@Override
public void run() {
final Filter<T> filter = getFilter(control.getGenericType(), control.getFilter());
if (control.getFilter() != filter) {
FThreads.invokeInEdtLater(new Runnable() {
@Override
public void run() {
control.setFilter(filter);
if (filter != null) {
control.getBtnFilter().setText(GuiBase.getInterface().encodeSymbols(filter.toString(), false));
}
else {
control.getBtnFilter().setText(emptyFilterText);
}
if (filter.getOption() == FilterOption.CARD_KEYWORDS) {
//the first time the user selects keywords, preload keywords for all cards
Runnable preloadTask = Keyword.getPreloadTask();
if (preloadTask != null) {
GuiBase.getInterface().runBackgroundTask("Loading keywords...", preloadTask);
}
}
}
});
}
}
});
} }
}); });
controls.add(control); controls.add(control);
} }
public void removeFilterControl(IFilterControl<T> control) { public void removeFilterControl(IFilterControl<T> control) {
int index = controls.indexOf(control); int index = controls.indexOf(control);
if (index > 0) { if (index > 0) {
@@ -1048,6 +1029,43 @@ public class AdvancedSearch {
controls.remove(index); controls.remove(index);
} }
public void editFilterControl(final IFilterControl<T> control, final Runnable onChange) {
FThreads.invokeInBackgroundThread(new Runnable() {
@Override
public void run() {
final Filter<T> filter = getFilter(control.getGenericType(), control.getFilter(), onChange == null); //reselect option if no change handler passed
if (control.getFilter() != filter) {
FThreads.invokeInEdtLater(new Runnable() {
@Override
public void run() {
control.setFilter(filter);
if (filter != null) {
control.getBtnFilter().setText(GuiBase.getInterface().encodeSymbols(filter.toString(), false));
}
else {
control.getBtnFilter().setText(EMPTY_FILTER_TEXT);
}
if (filter.getOption() == FilterOption.CARD_KEYWORDS) {
//the first time the user selects keywords, preload keywords for all cards
Runnable preloadTask = Keyword.getPreloadTask();
if (preloadTask != null) {
GuiBase.getInterface().runBackgroundTask("Loading keywords...", preloadTask);
}
}
if (onChange != null) {
onChange.run();
}
}
});
}
}
});
}
public Iterable<IFilterControl<T>> getControls() {
return controls;
}
public void setLabel(IButton label0) { public void setLabel(IButton label0) {
label = label0; label = label0;
updateLabel(); updateLabel();