Implement DualListBox for mobile

This commit is contained in:
drdev
2014-04-29 04:28:57 +00:00
parent 96b9b3da00
commit 21a1c26cc7
6 changed files with 313 additions and 44 deletions

1
.gitattributes vendored
View File

@@ -1166,6 +1166,7 @@ forge-gui-mobile/src/forge/screens/match/winlose/ViewWinLose.java -text
forge-gui-mobile/src/forge/screens/quest/QuestScreen.java -text
forge-gui-mobile/src/forge/screens/sealed/SealedScreen.java -text
forge-gui-mobile/src/forge/screens/settings/SettingsScreen.java -text
forge-gui-mobile/src/forge/toolbox/DualListBox.java -text
forge-gui-mobile/src/forge/toolbox/FButton.java -text
forge-gui-mobile/src/forge/toolbox/FCardPanel.java -text
forge-gui-mobile/src/forge/toolbox/FCheckBox.java -text

View File

@@ -0,0 +1,289 @@
package forge.toolbox;
import forge.Forge.Graphics;
import forge.assets.FSkinColor;
import forge.assets.FSkinFont;
import forge.toolbox.FEvent.FEventHandler;
import forge.toolbox.FEvent.FEventType;
import forge.util.Callback;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment;
// An input box for handling the order of choices.
// Left box has the original choices
// Right box has the final order
// Top string will be like Top of the Stack or Top of the Library
// Bottom string will be like Bottom of the Stack or Bottom of the Library
// Single Arrows in between left box and right box for ordering
// Multi Arrows for moving everything in order
// Up/down arrows on the right of the right box for swapping
// Single ok button, disabled until left box has specified number of items remaining
public class DualListBox<T> extends FDialog {
private final ChoiceList sourceList;
private final ChoiceList destList;
private final FButton addButton;
private final FButton addAllButton;
private final FButton removeButton;
private final FButton removeAllButton;
private final FButton okButton;
private final FButton autoButton;
private final FLabel orderedLabel;
private final FLabel selectOrder;
private final int targetRemainingSourcesMin;
private final int targetRemainingSourcesMax;
private boolean sideboardingMode = false;
public DualListBox(String title, int remainingSources, List<T> sourceElements, List<T> destElements, final Callback<List<T>> callback) {
this(title, remainingSources, remainingSources, sourceElements, destElements, callback);
}
public DualListBox(String title, int remainingSourcesMin, int remainingSourcesMax, List<T> sourceElements, List<T> destElements, final Callback<List<T>> callback) {
super(title);
targetRemainingSourcesMin = remainingSourcesMin;
targetRemainingSourcesMax = remainingSourcesMax;
final FEventHandler onAdd = new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
if (!addButton.isEnabled()) { return; }
List<T> selected = new ArrayList<T>();
for (int index : sourceList.selectedIndices) {
selected.add(sourceList.getItemAt(index));
}
for (T item : selected) {
sourceList.removeItem(item);
destList.addItem(item);
}
setButtonState();
}
};
final FEventHandler onRemove = new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
if (!removeButton.isEnabled()) { return; }
List<T> selected = new ArrayList<T>();
for (int index : destList.selectedIndices) {
selected.add(destList.getItemAt(index));
}
for (T item : selected) {
destList.removeItem(item);
sourceList.addItem(item);
}
setButtonState();
}
};
sourceList = add(new ChoiceList(sourceElements, onAdd));
destList = add(new ChoiceList(destElements, onRemove));
// Dual List control buttons
addButton = add(new FButton(">", onAdd));
addAllButton = add(new FButton(">>", new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
addAll();
}
}));
removeButton = add(new FButton("<", onRemove));
removeAllButton = add(new FButton("<<", new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
removeAll();
}
}));
final FEventHandler onAccept = new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
hide();
callback.run(destList.extractListData());
}
};
// Dual List Complete Buttons
okButton = add(new FButton("OK", onAccept));
autoButton = add(new FButton("Auto", new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
addAll();
onAccept.handleEvent(e);
}
}));
selectOrder = add(new FLabel.Builder().align(HAlignment.CENTER).text("Select Order:").build());
orderedLabel = add(new FLabel.Builder().align(HAlignment.CENTER).build());
setButtonState();
}
@Override
protected float layoutAndGetHeight(float width, float maxHeight) {
float x = FOptionPane.PADDING;
float y = FOptionPane.PADDING;
width -= 2 * x;
float buttonHeight = FOptionPane.BUTTON_HEIGHT;
float labelHeight = selectOrder.getAutoSizeBounds().height;
float listHeight = (maxHeight - 2 * labelHeight - 2 * buttonHeight - 3 * FOptionPane.PADDING - FOptionPane.GAP_BELOW_BUTTONS) / 2;
selectOrder.setBounds(x, y, width, labelHeight);
y += labelHeight;
sourceList.setBounds(x, y, width, listHeight);
y += listHeight + FOptionPane.PADDING;
float gapBetweenButtons = FOptionPane.PADDING / 2;
float buttonWidth = (width - 3 * gapBetweenButtons) / 4;
float dx = buttonWidth + gapBetweenButtons;
addButton.setBounds(x, y, buttonWidth, buttonHeight);
x += dx;
addAllButton.setBounds(x, y, buttonWidth, buttonHeight);
x += dx;
removeButton.setBounds(x, y, buttonWidth, buttonHeight);
x += dx;
removeAllButton.setBounds(x, y, buttonWidth, buttonHeight);
x = FList.PADDING;
y += buttonHeight + FOptionPane.PADDING;
orderedLabel.setBounds(x, y, width, labelHeight);
y += labelHeight;
destList.setBounds(x, y, width, listHeight);
y += listHeight + FOptionPane.PADDING;
buttonWidth = (width - gapBetweenButtons) / 2;
dx = buttonWidth + gapBetweenButtons;
okButton.setBounds(x, y, buttonWidth, buttonHeight);
x += dx;
autoButton.setBounds(x, y, buttonWidth, buttonHeight);
return maxHeight;
}
public void setSecondColumnLabelText(String label) {
orderedLabel.setText(label);
}
public void setSideboardMode(boolean isSideboardMode) {
sideboardingMode = isSideboardMode;
if (sideboardingMode) {
addAllButton.setVisible(false);
removeAllButton.setVisible(false);
autoButton.setEnabled(false);
selectOrder.setText(String.format("Sideboard (%d):", sourceList.getCount()));
orderedLabel.setText(String.format("Main Deck (%d):", destList.getCount()));
}
}
public List<T> getRemainingSourceList() {
return sourceList.extractListData();
}
private void addAll() {
for (T item : sourceList) {
destList.addItem(item);
}
sourceList.clear();
setButtonState();
}
private void removeAll() {
for (T item : destList) {
sourceList.addItem(item);
}
destList.clear();
setButtonState();
}
private void setButtonState() {
if (sideboardingMode) {
removeAllButton.setVisible(false);
addAllButton.setVisible(false);
selectOrder.setText(String.format("Sideboard (%d):", sourceList.getCount()));
orderedLabel.setText(String.format("Main Deck (%d):", destList.getCount()));
}
boolean anySize = targetRemainingSourcesMax < 0;
boolean canAdd = sourceList.getCount() != 0 && (anySize || targetRemainingSourcesMin <= sourceList.getCount());
boolean canRemove = destList.getCount() != 0;
boolean targetReached = anySize || targetRemainingSourcesMin <= sourceList.getCount() && targetRemainingSourcesMax >= sourceList.getCount();
autoButton.setEnabled(targetRemainingSourcesMax == 0 && !targetReached && !sideboardingMode);
addButton.setEnabled(canAdd);
addAllButton.setEnabled(canAdd);
removeButton.setEnabled(canRemove);
removeAllButton.setEnabled(canRemove);
okButton.setEnabled(targetReached);
}
private class ChoiceList extends FList<T> {
private List<Integer> selectedIndices = new ArrayList<Integer>();
private ChoiceList(Collection<T> items, final FEventHandler dblTapCommand) {
super(items != null ? items : new ArrayList<T>()); //handle null without crashing
setListItemRenderer(new ListItemRenderer<T>() {
@Override
public float getItemHeight() {
return ListChooser.ITEM_HEIGHT;
}
@Override
public boolean tap(T value, float x, float y, int count) {
Integer index = ChoiceList.this.getIndexOf(value);
if (selectedIndices.contains(index)) {
selectedIndices.remove(index);
}
else {
selectedIndices.add(index);
}
if (count == 2) {
dblTapCommand.handleEvent(new FEvent(ChoiceList.this, FEventType.ACTIVATE, index));
}
return true;
}
@Override
public void drawValue(Graphics g, T value, FSkinFont font, FSkinColor foreColor, boolean pressed, float x, float y, float w, float h) {
g.drawText(value.toString(), font, foreColor, x, y, w, h, false, HAlignment.LEFT, true);
}
});
setFontSize(12);
}
@Override
protected void drawBackground(Graphics g) {
g.fillRect(ListChooser.BACK_COLOR, 0, 0, getWidth(), getHeight());
}
@Override
public void drawOverlay(Graphics g) {
g.drawRect(1.5f, ListChooser.BORDER_COLOR, 0, 0, getWidth(), getHeight());
}
@Override
protected FSkinColor getItemFillColor(int index) {
if (selectedIndices.contains(index)) {
return ListChooser.SEL_COLOR;
}
if (index % 2 == 1) {
return ListChooser.ALT_ITEM_COLOR;
}
return null;
}
@Override
protected boolean drawLineSeparators() {
return false;
}
}
}

View File

@@ -1,6 +1,7 @@
package forge.toolbox;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment;
@@ -13,7 +14,7 @@ import forge.assets.FSkinColor.Colors;
import forge.screens.FScreen;
import forge.util.Utils;
public class FList<E> extends FScrollPane {
public class FList<E> extends FScrollPane implements Iterable<E> {
public static final float PADDING = 3;
public static final FSkinColor FORE_COLOR = FSkinColor.get(Colors.CLR_TEXT);
public static final FSkinColor PRESSED_COLOR = FSkinColor.get(Colors.CLR_ACTIVE).alphaColor(0.9f);
@@ -59,6 +60,9 @@ public class FList<E> extends FScrollPane {
items.clear();
}
public List<E> extractListData() {
return new ArrayList<E>(items); //create copy to avoid modifying items
}
public void setListData(Iterable<E> items0) {
clear();
for (E item : items0) {
@@ -233,4 +237,9 @@ public class FList<E> extends FScrollPane {
g.drawText(value.toString(), font, color, x, y, w, h, false, HAlignment.LEFT, true);
}
}
@Override
public Iterator<E> iterator() {
return items.iterator();
}
}

View File

@@ -15,9 +15,9 @@ public class FOptionPane extends FDialog {
public static final FSkinImage WARNING_ICON = FSkinImage.WARNING;
public static final FSkinImage ERROR_ICON = FSkinImage.ERROR;
private static float PADDING = 10;
private static final float GAP_BELOW_BUTTONS = PADDING * 0.5f;
private static final float BUTTON_HEIGHT = Utils.AVG_FINGER_HEIGHT * 0.75f;
public static float PADDING = 10;
public static final float GAP_BELOW_BUTTONS = PADDING * 0.5f;
public static final float BUTTON_HEIGHT = Utils.AVG_FINGER_HEIGHT * 0.75f;
public static float getMaxDisplayObjHeight() {
return Forge.getCurrentScreen().getHeight() - 2 * VPrompt.HEIGHT - FDialog.TITLE_HEIGHT -

View File

@@ -263,40 +263,10 @@ public class GuiChoose {
public static <T> void order(final String title, final String top, final int remainingObjectsMin, final int remainingObjectsMax,
final List<T> sourceChoices, final List<T> destChoices, final Card referenceCard, final boolean sideboardingMode, final Callback<List<T>> callback) {
// An input box for handling the order of choices.
/*Callable<List<T>> callable = new Callable<List<T>>() {
@Override
public List<T> call() throws Exception {
DualListBox<T> dual = new DualListBox<T>(remainingObjectsMin, remainingObjectsMax, sourceChoices, destChoices);
DualListBox<T> dual = new DualListBox<T>(title, remainingObjectsMin, remainingObjectsMax, sourceChoices, destChoices, callback);
dual.setSecondColumnLabelText(top);
dual.setSideboardMode(sideboardingMode);
dual.setTitle(title);
dual.pack();
dual.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
if (referenceCard != null) {
CMatchUI.SINGLETON_INSTANCE.setCard(referenceCard);
// MARKED FOR UPDATE
}
dual.setVisible(true);
List<T> objects = dual.getOrderedList();
dual.dispose();
GuiUtils.clearPanelSelections();
return objects;
}
};
FutureTask<List<T>> ft = new FutureTask<List<T>>(callable);
FThreads.invokeInEdtAndWait(ft);
try {
return ft.get();
} catch (Exception e) { // we have waited enough
e.printStackTrace();
}*/
callback.run(null);
dual.show();
}
// If comparer is NULL, T has to be comparable. Otherwise you'll get an exception from inside the Arrays.sort() routine

View File

@@ -62,11 +62,11 @@ import java.util.List;
* @version $Id: ListChooser.java 25183 2014-03-14 23:09:45Z drdev $
*/
public class ListChooser<T> extends FContainer {
private static final FSkinColor BACK_COLOR = FSkinColor.get(Colors.CLR_ZEBRA);
private static final FSkinColor ALT_ITEM_COLOR = BACK_COLOR.getContrastColor(-20);
private static final FSkinColor SEL_COLOR = FSkinColor.get(Colors.CLR_ACTIVE);
private static final FSkinColor BORDER_COLOR = FSkinColor.get(Colors.CLR_BORDERS);
private static final float ITEM_HEIGHT = Utils.AVG_FINGER_HEIGHT * 0.75f;
public static final FSkinColor BACK_COLOR = FSkinColor.get(Colors.CLR_ZEBRA);
public static final FSkinColor ALT_ITEM_COLOR = BACK_COLOR.getContrastColor(-20);
public static final FSkinColor SEL_COLOR = FSkinColor.get(Colors.CLR_ACTIVE);
public static final FSkinColor BORDER_COLOR = FSkinColor.get(Colors.CLR_BORDERS);
public static final float ITEM_HEIGHT = Utils.AVG_FINGER_HEIGHT * 0.75f;
// Data and number of choices for the list
private int minChoices, maxChoices;
@@ -220,7 +220,7 @@ public class ListChooser<T> extends FContainer {
@Override
public boolean tap(T value, float x, float y, int count) {
int index = lstChoices.getIndexOf(value);
Integer index = ChoiceList.this.getIndexOf(value);
if (allowMultipleSelections) {
if (selectedIndices.contains(index)) {
selectedIndices.remove(index);