* GUI: fixed multiple bugs and performance issues with Deck Editor and sets filter/search;

This commit is contained in:
Oleg Agafonov 2021-08-19 21:33:14 +04:00
parent fd719ad287
commit fb540e9728
3 changed files with 144 additions and 87 deletions

View file

@ -42,11 +42,14 @@ import java.util.*;
import static mage.client.dialog.PreferencesDialog.*; import static mage.client.dialog.PreferencesDialog.*;
/** /**
* @author BetaSteward_at_googlemail.com, nantuko * GUI: deck editor's panel with filters and search
*
* @author BetaSteward_at_googlemail.com, nantuko, JayDi85
*/ */
public class CardSelector extends javax.swing.JPanel implements ComponentListener, DragCardTarget { public class CardSelector extends javax.swing.JPanel implements ComponentListener, DragCardTarget {
private static final Logger logger = Logger.getLogger(CardSelector.class); private static final Logger logger = Logger.getLogger(CardSelector.class);
private final String MULTI_SETS_SELECTION_TEXT = "Multiple sets selected";
private final java.util.List<Card> cards = new ArrayList<>(); private final java.util.List<Card> cards = new ArrayList<>();
private BigCard bigCard; private BigCard bigCard;
@ -54,8 +57,7 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
private final SortSetting sortSetting; private final SortSetting sortSetting;
private static final Map<String, Integer> pdAllowed = new HashMap<>(); private static final Map<String, Integer> pdAllowed = new HashMap<>();
private static Listener<RepositoryEvent> setsDbListener = null; private static Listener<RepositoryEvent> setsDbListener = null;
private boolean isSetsFilterLoading = false; // use it on sets combobox modify
private final String TEST_MULTI_SET = "Multiple Sets selected";
private final ActionListener searchAction = evt -> jButtonSearchActionPerformed(evt); private final ActionListener searchAction = evt -> jButtonSearchActionPerformed(evt);
@ -71,17 +73,15 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
setGUISize(); setGUISize();
currentView = mainModel; // by default we use List View currentView = mainModel; // by default we use List View
// prepare search dialog with checkboxes
listCodeSelected = new CheckBoxList(); listCodeSelected = new CheckBoxList();
List<String> checkboxes = new ArrayList<>();
String[] setCodes = ConstructedFormats.getTypes(); for (String item : ConstructedFormats.getTypes()) {
java.util.List<String> result = new ArrayList<>();
for (String item : setCodes) {
if (!item.equals(ConstructedFormats.ALL_SETS)) { if (!item.equals(ConstructedFormats.ALL_SETS)) {
result.add(item); checkboxes.add(item);
} }
} }
listCodeSelected.setListData(result.toArray()); listCodeSelected.setListData(checkboxes.toArray());
} }
private void makeTransparent() { private void makeTransparent() {
@ -216,9 +216,15 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
this.btnClear.setVisible(true); this.btnClear.setVisible(true);
this.cbExpansionSet.setVisible(true); this.cbExpansionSet.setVisible(true);
this.btnExpansionSearch.setVisible(true); this.btnExpansionSearch.setVisible(true);
// cbExpansionSet.setModel(new DefaultComboBoxModel<>(ConstructedFormats.getTypes()));
// Action event on Expansion set triggers loadCards method // select "all" by default
try {
isSetsFilterLoading = true;
cbExpansionSet.setSelectedIndex(0); cbExpansionSet.setSelectedIndex(0);
} finally {
isSetsFilterLoading = false;
}
filterCards();
} }
private FilterCard buildFilter() { private FilterCard buildFilter() {
@ -274,21 +280,62 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
} }
filter.add(Predicates.or(predicates)); filter.add(Predicates.or(predicates));
if (this.cbExpansionSet.isVisible()) { List<String> filteredSets = getFilteredSets();
String expansionSelection = this.cbExpansionSet.getSelectedItem().toString(); if (!filteredSets.isEmpty()) {
if (!expansionSelection.equals("- All Sets")) {
List<Predicate<Card>> expansionPredicates = new ArrayList<>(); List<Predicate<Card>> expansionPredicates = new ArrayList<>();
for (String setCode : ConstructedFormats.getSetsByFormat(expansionSelection)) { for (String setCode : filteredSets) {
expansionPredicates.add(new ExpansionSetPredicate(setCode)); expansionPredicates.add(new ExpansionSetPredicate(setCode));
} }
filter.add(Predicates.or(expansionPredicates)); filter.add(Predicates.or(expansionPredicates));
} }
} }
}
return filter; return filter;
} }
private void setSetsSelection(String newSelection) {
// combo and checkbox can contain different elements (e.g. without "all" or "multi" options),
// so must search by string value
for (int index = 0; index < cbExpansionSet.getItemCount(); index++) {
if (cbExpansionSet.getItemAt(index).equals(newSelection)) {
if (cbExpansionSet.getSelectedIndex() != index) {
cbExpansionSet.setSelectedIndex(index);
}
}
}
}
private List<String> getFilteredSets() {
// empty list - show all sets
List<String> res = new ArrayList<>();
if (!this.cbExpansionSet.isVisible()) {
return res;
}
if (listCodeSelected.getCheckedIndices().length <= 1) {
// single set selected
String expansionSelection = this.cbExpansionSet.getSelectedItem().toString();
if (!expansionSelection.equals(ConstructedFormats.ALL_SETS)
&& !expansionSelection.startsWith(MULTI_SETS_SELECTION_TEXT)) {
res.addAll(ConstructedFormats.getSetsByFormat(expansionSelection));
}
} else {
// multiple sets selected
int[] choiseValue = listCodeSelected.getCheckedIndices();
ListModel x = listCodeSelected.getModel();
for (int itemIndex : choiseValue) {
java.util.List<String> listReceived = ConstructedFormats.getSetsByFormat(x.getElementAt(itemIndex).toString());
listReceived.stream()
.filter(item -> !res.contains(item))
.forEachOrdered(res::add);
}
}
return res;
}
private CardCriteria buildCriteria() { private CardCriteria buildCriteria() {
CardCriteria criteria = new CardCriteria(); CardCriteria criteria = new CardCriteria();
criteria.black(this.tbBlack.isSelected()); criteria.black(this.tbBlack.isSelected());
@ -338,27 +385,10 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
criteria.rarities(Rarity.SPECIAL); criteria.rarities(Rarity.SPECIAL);
criteria.rarities(Rarity.BONUS); criteria.rarities(Rarity.BONUS);
} }
if (this.cbExpansionSet.isVisible()) {
if (listCodeSelected.getCheckedIndices().length <= 1) {
String expansionSelection = this.cbExpansionSet.getSelectedItem().toString();
if (!expansionSelection.equals("- All Sets")) {
java.util.List<String> setCodes = ConstructedFormats.getSetsByFormat(expansionSelection);
criteria.setCodes(setCodes.toArray(new String[0]));
}
} else {
java.util.List<String> setCodes = new ArrayList<>();
//java.util.List<String> listReceived=new ArrayList<>() ;
int[] choiseValue = listCodeSelected.getCheckedIndices(); List<String> filteredSets = getFilteredSets();
ListModel x = listCodeSelected.getModel(); if (!filteredSets.isEmpty()) {
criteria.setCodes(filteredSets.toArray(new String[0]));
for (int itemIndex : choiseValue) {
java.util.List<String> listReceived = ConstructedFormats.getSetsByFormat(x.getElementAt(itemIndex).toString());
listReceived.stream().filter(item -> !setCodes.contains(item)).forEachOrdered(setCodes::add);
}
criteria.setCodes(setCodes.toArray(new String[0]));
}
} }
return criteria; return criteria;
@ -681,7 +711,9 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
cbExpansionSetActionPerformed(evt); cbExpansionSetActionPerformed(evt);
} }
}); });
// auto-update sets list on changes // auto-update sets list on changes
// doesn't use any more due to db recreation on update
setsDbListener = new Listener<RepositoryEvent>() { setsDbListener = new Listener<RepositoryEvent>() {
@Override @Override
public void event(RepositoryEvent event) { public void event(RepositoryEvent event) {
@ -1218,19 +1250,37 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
private void cbExpansionSetActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbExpansionSetActionPerformed private void cbExpansionSetActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbExpansionSetActionPerformed
if (!cbExpansionSet.getSelectedItem().toString().contains(TEST_MULTI_SET)) { // one item selected by user
int index = cbExpansionSet.getSelectedIndex();
if (cbExpansionSet.getItemAt(0).contains(TEST_MULTI_SET)) { // ignore combobox modifing
cbExpansionSet.removeItemAt(0); if (isSetsFilterLoading) {
index--; return;
} }
// auto-remove unused multi-select item and sync checkboxes
if (!cbExpansionSet.getSelectedItem().toString().startsWith(MULTI_SETS_SELECTION_TEXT)) {
int currentSelection = cbExpansionSet.getSelectedIndex();
isSetsFilterLoading = true;
try {
// remove multi item and fix selection
if (cbExpansionSet.getItemAt(0).startsWith(MULTI_SETS_SELECTION_TEXT)) {
cbExpansionSet.removeItemAt(0);
currentSelection = Math.max(0, currentSelection - 1);
}
} finally {
isSetsFilterLoading = false;
}
// sync checkboxes
listCodeSelected.uncheckAll(); listCodeSelected.uncheckAll();
if (index > 0) { if (currentSelection > 0) {
//ofset because all sets is removed from the list // if not "all" option selected
listCodeSelected.setChecked(index - 1, true); // checkbox haven't "all", so use another indexes
listCodeSelected.setChecked(currentSelection - 1, true);
} }
} }
// update data
filterCards(); filterCards();
}//GEN-LAST:event_cbExpansionSetActionPerformed }//GEN-LAST:event_cbExpansionSetActionPerformed
@ -1241,7 +1291,7 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
}//GEN-LAST:event_btnClearActionPerformed }//GEN-LAST:event_btnClearActionPerformed
private void btnBoosterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnBoosterActionPerformed private void btnBoosterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnBoosterActionPerformed
java.util.List<String> sets = ConstructedFormats.getSetsByFormat(this.cbExpansionSet.getSelectedItem().toString()); List<String> sets = getFilteredSets();
if (sets.size() == 1) { if (sets.size() == 1) {
if (!this.limited) { if (!this.limited) {
this.limited = true; this.limited = true;
@ -1415,43 +1465,45 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
}//GEN-LAST:event_chkRulesActionPerformed }//GEN-LAST:event_chkRulesActionPerformed
private void btnExpansionSearchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnExpansionSearchActionPerformed private void btnExpansionSearchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnExpansionSearchActionPerformed
// search and check multiple items
int[] oldChecks = listCodeSelected.getCheckedIndices();
// call dialog
FastSearchUtil.showFastSearchForStringComboBox(listCodeSelected, FastSearchUtil.DEFAULT_EXPANSION_SEARCH_MESSAGE); FastSearchUtil.showFastSearchForStringComboBox(listCodeSelected, FastSearchUtil.DEFAULT_EXPANSION_SEARCH_MESSAGE);
//
int[] choiseValue = listCodeSelected.getCheckedIndices();
ListModel x = listCodeSelected.getModel();
if (choiseValue.length == 0)//none int[] newChecks = listCodeSelected.getCheckedIndices();
{ if (Arrays.equals(oldChecks, newChecks)) {
// no changes or cancel
return;
}
isSetsFilterLoading = true;
try {
// delete old item
if (cbExpansionSet.getItemAt(0).startsWith(MULTI_SETS_SELECTION_TEXT)) {
cbExpansionSet.removeItemAt(0);
}
// set new selection
if (newChecks.length == 0) {
// all
cbExpansionSet.setSelectedIndex(0); cbExpansionSet.setSelectedIndex(0);
} else if (choiseValue.length == 1)//one } else if (newChecks.length == 1) {
{ // one
String itemSelected = listCodeSelected.getModel().getElementAt(choiseValue[0]).toString(); setSetsSelection(listCodeSelected.getModel().getElementAt(newChecks[0]).toString());
for (int index = 0; index < cbExpansionSet.getItemCount(); index++) { } else {
if (cbExpansionSet.getItemAt(index).equals(itemSelected)) { // multiple
cbExpansionSet.setSelectedIndex(index); // insert custom text
} String message = String.format("%s: %d", MULTI_SETS_SELECTION_TEXT, newChecks.length);
}
} else//many
{
String message = String.format("%s:%d", TEST_MULTI_SET, choiseValue.length);
cbExpansionSet.insertItemAt(message, 0); cbExpansionSet.insertItemAt(message, 0);
cbExpansionSet.setSelectedIndex(0); cbExpansionSet.setSelectedIndex(0);
}
if (cbExpansionSet.getItemAt(1).contains(TEST_MULTI_SET)) { } finally {
cbExpansionSet.removeItemAt(1); isSetsFilterLoading = false;
} }
//listCodeSelected.setChecked(index-1, true); // update data
//cbExpansionSet.
}
/*for(int itemIndex: choiseValue){
// LogLog.warn(String.format("%d:%s",itemIndex,x.getElementAt(itemIndex).toString()));
}
*/
//
filterCards(); filterCards();
}//GEN-LAST:event_btnExpansionSearchActionPerformed }//GEN-LAST:event_btnExpansionSearchActionPerformed

View file

@ -11,6 +11,7 @@ import java.awt.*;
import java.awt.event.*; import java.awt.event.*;
import java.util.*; import java.util.*;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
/** /**
* App GUI: fast search in the combobox, uses in deck editor (sets choosing) * App GUI: fast search in the combobox, uses in deck editor (sets choosing)
@ -26,6 +27,7 @@ public class PickCheckBoxDialog extends MageDialog {
CheckBoxList.CheckBoxListModel m_dataModel; CheckBoxList.CheckBoxListModel m_dataModel;
CheckBoxList tList; CheckBoxList tList;
int[] startingCheckboxes; // restore to it on cancel
final private static String HTML_TEMPLATE = "<html><div style='text-align: center;'>%s</div></html>"; final private static String HTML_TEMPLATE = "<html><div style='text-align: center;'>%s</div></html>";
@ -276,6 +278,12 @@ public class PickCheckBoxDialog extends MageDialog {
} }
private void doCancel() { private void doCancel() {
// restore starting checkboxes
Set<Integer> checks = Arrays.stream(startingCheckboxes).boxed().collect(Collectors.toSet());
for (int i = 0; i < tList.getModel().getSize(); i++) {
tList.setChecked(i, checks.contains(i));
}
this.listChoices.clearSelection(); this.listChoices.clearSelection();
this.choice.clearChoice(); this.choice.clearChoice();
hideDialog(); hideDialog();
@ -289,6 +297,7 @@ public class PickCheckBoxDialog extends MageDialog {
public PickCheckBoxDialog(CheckBoxList list) { public PickCheckBoxDialog(CheckBoxList list) {
initComponents(); initComponents();
tList = list; tList = list;
startingCheckboxes = list.getCheckedIndices();
this.listChoices.setModel(dataModel); this.listChoices.setModel(dataModel);
this.setModal(true); this.setModal(true);
@ -302,7 +311,6 @@ public class PickCheckBoxDialog extends MageDialog {
if (this.tList instanceof javax.swing.JList) { if (this.tList instanceof javax.swing.JList) {
setFocus(tList); setFocus(tList);
} }
} }
} }
@ -553,9 +561,7 @@ public class PickCheckBoxDialog extends MageDialog {
}//GEN-LAST:event_closeDialog }//GEN-LAST:event_closeDialog
private void btClearActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btClearActionPerformed private void btClearActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btClearActionPerformed
// TODO add your handling code here:
this.tList.uncheckAll(); this.tList.uncheckAll();
//this.tList.repaint();
scrollList.repaint(); scrollList.repaint();
}//GEN-LAST:event_btClearActionPerformed }//GEN-LAST:event_btClearActionPerformed

View file

@ -10,7 +10,7 @@ import mage.game.events.Listener;
import java.util.*; import java.util.*;
/** /**
* Utility class for constructed formats (expansions and other editions). * Utility class for constructed formats (expansions and other editions). Uses in GUI for set's combobox.
* *
* @author nantuko * @author nantuko
*/ */
@ -73,7 +73,6 @@ public final class ConstructedFormats {
return underlyingSetCodesPerFormat.get(format); return underlyingSetCodesPerFormat.get(format);
} }
return all; return all;
} }
public static void ensureLists() { public static void ensureLists() {