diff --git a/.gitattributes b/.gitattributes index 8c474305604..26e4c3f658b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -223,6 +223,7 @@ forge-core/src/main/java/forge/util/ItemPool.java -text forge-core/src/main/java/forge/util/ItemPoolSorter.java -text forge-core/src/main/java/forge/util/Lang.java -text forge-core/src/main/java/forge/util/MyRandom.java svneol=native#text/plain +forge-core/src/main/java/forge/util/NameGenerator.java -text forge-core/src/main/java/forge/util/PredicateString.java -text forge-core/src/main/java/forge/util/ReflectionUtil.java -text forge-core/src/main/java/forge/util/TextUtil.java -text @@ -15999,7 +16000,6 @@ forge-gui/src/main/java/forge/util/HttpUtil.java svneol=native#text/plain forge-gui/src/main/java/forge/util/IgnoringXStream.java -text forge-gui/src/main/java/forge/util/LineReader.java -text forge-gui/src/main/java/forge/util/MultiplexOutputStream.java svneol=native#text/plain -forge-gui/src/main/java/forge/util/NameGenerator.java -text forge-gui/src/main/java/forge/util/OperatingSystem.java -text forge-gui/src/main/java/forge/util/XmlUtil.java -text forge-gui/src/main/java/forge/util/package-info.java -text @@ -16130,6 +16130,7 @@ forge-m-base/src/forge/assets/FSkinFont.java -text forge-m-base/src/forge/assets/FSkinImage.java -text forge-m-base/src/forge/assets/FSkinTexture.java -text forge-m-base/src/forge/assets/FTextureImage.java -text +forge-m-base/src/forge/assets/FTextureRegionImage.java -text forge-m-base/src/forge/assets/ImageCache.java -text forge-m-base/src/forge/assets/ImageLoader.java -text forge-m-base/src/forge/deck/io/OldDeckParser.java -text diff --git a/forge-gui/src/main/java/forge/util/NameGenerator.java b/forge-core/src/main/java/forge/util/NameGenerator.java similarity index 100% rename from forge-gui/src/main/java/forge/util/NameGenerator.java rename to forge-core/src/main/java/forge/util/NameGenerator.java diff --git a/forge-m-base/src/forge/assets/FTextureRegionImage.java b/forge-m-base/src/forge/assets/FTextureRegionImage.java new file mode 100644 index 00000000000..e19706d95da --- /dev/null +++ b/forge-m-base/src/forge/assets/FTextureRegionImage.java @@ -0,0 +1,28 @@ +package forge.assets; + +import com.badlogic.gdx.graphics.g2d.TextureRegion; + +import forge.Forge.Graphics; + +public class FTextureRegionImage implements FImage { + private final TextureRegion textureRegion; + + public FTextureRegionImage(TextureRegion textureRegion0) { + textureRegion = textureRegion0; + } + + @Override + public float getWidth() { + return textureRegion.getRegionWidth(); + } + + @Override + public float getHeight() { + return textureRegion.getRegionHeight(); + } + + @Override + public void draw(Graphics g, float x, float y, float w, float h) { + g.drawImage(textureRegion, x, y, w, h); + } +} diff --git a/forge-m-base/src/forge/screens/FScreen.java b/forge-m-base/src/forge/screens/FScreen.java index bf3348c9472..5ef4c13819a 100644 --- a/forge-m-base/src/forge/screens/FScreen.java +++ b/forge-m-base/src/forge/screens/FScreen.java @@ -10,6 +10,8 @@ import forge.assets.FSkinImage; import forge.assets.FSkinColor.Colors; import forge.assets.FSkinTexture; import forge.toolbox.FContainer; +import forge.toolbox.FEvent; +import forge.toolbox.FEvent.FEventHandler; import forge.toolbox.FLabel; import forge.utils.Utils; @@ -25,9 +27,9 @@ public abstract class FScreen extends FContainer { protected FScreen(boolean showBackButton, String headerCaption, boolean showMenuButton) { if (showBackButton) { - btnBack = add(new FLabel.Builder().icon(new BackIcon()).pressedColor(HEADER_BTN_PRESSED_COLOR).align(HAlignment.CENTER).command(new Runnable() { + btnBack = add(new FLabel.Builder().icon(new BackIcon()).pressedColor(HEADER_BTN_PRESSED_COLOR).align(HAlignment.CENTER).command(new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { Forge.back(); } }).build()); @@ -42,9 +44,9 @@ public abstract class FScreen extends FContainer { lblHeader = null; } if (showMenuButton) { - btnMenu = add(new FLabel.Builder().icon(FSkinImage.FAVICON).pressedColor(HEADER_BTN_PRESSED_COLOR).align(HAlignment.CENTER).command(new Runnable() { + btnMenu = add(new FLabel.Builder().icon(FSkinImage.FAVICON).pressedColor(HEADER_BTN_PRESSED_COLOR).align(HAlignment.CENTER).command(new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { showMenu(); } }).build()); diff --git a/forge-m-base/src/forge/screens/constructed/ConstructedScreen.java b/forge-m-base/src/forge/screens/constructed/ConstructedScreen.java index 9563ec76f29..85d8173d822 100644 --- a/forge-m-base/src/forge/screens/constructed/ConstructedScreen.java +++ b/forge-m-base/src/forge/screens/constructed/ConstructedScreen.java @@ -1,28 +1,26 @@ package forge.screens.constructed; -import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.event.FocusAdapter; -import java.awt.event.FocusEvent; -import java.awt.event.MouseEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Set; import java.util.TreeSet; import java.util.Vector; -import javax.swing.ButtonGroup; -import javax.swing.JPanel; - import org.apache.commons.lang3.StringUtils; -import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.google.common.base.Predicate; import forge.assets.FSkin; +import forge.assets.FSkinColor; +import forge.assets.FSkinColor.Colors; +import forge.assets.FSkinImage; +import forge.assets.FTextureRegionImage; import forge.deck.Deck; -import forge.deck.DeckSection; import forge.game.GameType; import forge.game.player.LobbyPlayer; import forge.game.player.RegisteredPlayer; @@ -34,24 +32,29 @@ import forge.screens.LaunchScreen; import forge.toolbox.FCheckBox; import forge.toolbox.FComboBox; import forge.toolbox.FContainer; +import forge.toolbox.FEvent; +import forge.toolbox.FEvent.FEventHandler; import forge.toolbox.FLabel; +import forge.toolbox.FOptionPane; import forge.toolbox.FRadioButton; +import forge.toolbox.FRadioButton.RadioButtonGroup; import forge.toolbox.FScrollPane; import forge.toolbox.FTextField; import forge.util.MyRandom; +import forge.util.NameGenerator; import forge.utils.ForgePreferences; import forge.utils.ForgePreferences.FPref; import forge.utils.Utils; public class ConstructedScreen extends LaunchScreen { + private static final FSkinColor PLAYER_BORDER_COLOR = FSkinColor.get(Colors.CLR_THEME).alphaColor(0.8f); private static final ForgePreferences prefs = FModel.getPreferences(); private static final int MAX_PLAYERS = 8; // General variables private int activePlayersNum = 2; - private int playerWithFocus = 0; // index of the player that currently has focus - private PlayerPanel playerPanelWithFocus; + private int lastArchenemy = 0; private GameType currentGameMode = GameType.Constructed; private List teams = new ArrayList(MAX_PLAYERS); private List archenemyTeams = new ArrayList(MAX_PLAYERS); @@ -67,6 +70,13 @@ public class ConstructedScreen extends LaunchScreen { "Archenemy (Classic - One player is the Archenemy)", "Supervillan Rumble (All players are Archenemies)"}); private final List playerPanels = new ArrayList(MAX_PLAYERS); + private final FScrollPane playersScroll = new FScrollPane() { + @Override + protected ScrollBounds layoutAndGetScrollBounds(float visibleWidth, float visibleHeight) { + //TODO + return new ScrollBounds(visibleWidth, visibleHeight); + } + }; private final List closePlayerBtnList = new ArrayList(6); private final FLabel addPlayerBtn = new FLabel.ButtonBuilder().fontSize(14).text("Add a Player").build(); @@ -80,6 +90,124 @@ public class ConstructedScreen extends LaunchScreen { public ConstructedScreen() { super("Constructed"); + + /*lblTitle.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2)); + + //////////////////////////////////////////////////////// + //////////////////// Variants Panel //////////////////// + + // Populate and add variants panel + vntVanguard.addItemListener(iListenerVariants); + vntCommander.addItemListener(iListenerVariants); + vntPlanechase.addItemListener(iListenerVariants); + vntArchenemy.addItemListener(iListenerVariants); + comboArchenemy.setSelectedIndex(0); + comboArchenemy.setEnabled(vntArchenemy.isSelected()); + comboArchenemy.addActionListener(aeComboListener); + + variantsPanel.setOpaque(false); + variantsPanel.add(newLabel("Variants:")); + variantsPanel.add(vntVanguard); + variantsPanel.add(vntCommander); + variantsPanel.add(vntPlanechase); + variantsPanel.add(vntArchenemy); + comboArchenemy.addTo(variantsPanel); + + constructedFrame.add(new FScrollPane(variantsPanel, false, true, + ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, + ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED), + "w 100%, h 45px!, gapbottom 10px, spanx 2, wrap");*/ + + //////////////////////////////////////////////////////// + ///////////////////// Player Panel ///////////////////// + + // Construct individual player panels + String constraints = "pushx, growx, wrap, hidemode 3"; + for (int i = 0; i < MAX_PLAYERS; i++) { + teams.add(i+1); + archenemyTeams.add(i == 0 ? 1 : 2); + + PlayerPanel player = new PlayerPanel(i); + playerPanels.add(player); + + // Populate players panel + player.setVisible(i < activePlayersNum); + + playersScroll.add(player); + + if (i == 0) { + constraints += ", gaptop 5px"; + } + } + + add(playersScroll); + + addPlayerBtn.setCommand(new FEventHandler() { + @Override + public void handleEvent(FEvent e) { + addPlayer(); + } + }); + add(addPlayerBtn); + } + + private void addPlayer() { + if (activePlayersNum >= MAX_PLAYERS) { + return; + } + + int freeIndex = -1; + for (int i = 0; i < MAX_PLAYERS; i++) { + if (!playerPanels.get(i).isVisible()) { + freeIndex = i; + break; + } + } + + playerPanels.get(freeIndex).setVisible(true); + + activePlayersNum++; + addPlayerBtn.setEnabled(activePlayersNum < MAX_PLAYERS); + + playerPanels.get(freeIndex).setVisible(true); + } + + private void removePlayer(int playerIndex) { + activePlayersNum--; + PlayerPanel player = playerPanels.get(playerIndex); + player.setVisible(false); + addPlayerBtn.setEnabled(true); + + //find closest player still in game and give focus + int min = MAX_PLAYERS; + int closest = 2; + + for (int participantIndex : getParticipants()) { + final int diff = Math.abs(playerIndex - participantIndex); + + if (diff < min) { + min = diff; + closest = participantIndex; + } + } + } + + public boolean isPlayerAI(int playernum) { + return playerPanels.get(playernum).getPlayerType() == PlayerType.COMPUTER; + } + + public int getNumPlayers() { + return activePlayersNum; + } + + public final List getParticipants() { + final List participants = new ArrayList(activePlayersNum); + for (final PlayerPanel panel : playerPanels) { + if (panel.isVisible()) { + participants.add(playerPanels.indexOf(panel)); + } + } + return participants; } @Override @@ -109,7 +237,7 @@ public class ConstructedScreen extends LaunchScreen { } private class PlayerPanel extends FContainer { - /*private final int index; + private final int index; private final FLabel nameRandomiser; private final FLabel avatarLabel = new FLabel.Builder().opaque(true).iconScaleFactor(0.99f).iconInBackground(true).build(); @@ -125,8 +253,6 @@ public class ConstructedScreen extends LaunchScreen { private final FLabel deckBtn = new FLabel.ButtonBuilder().text("Select a deck").build(); private final FLabel deckLabel = newLabel("Deck:"); - private final String variantBtnConstraints = "height 30px, hidemode 3"; - private boolean playerIsArchenemy = false; private final FLabel scmDeckSelectorBtn = new FLabel.ButtonBuilder().text("Select a scheme deck").build(); private final FLabel scmDeckEditor = new FLabel.ButtonBuilder().text("Scheme Deck Editor").build(); @@ -143,9 +269,9 @@ public class ConstructedScreen extends LaunchScreen { private final FLabel vgdSelectorBtn = new FLabel.ButtonBuilder().text("Select a Vanguard avatar").build(); private final FLabel vgdLabel = newLabel("Vanguard:"); - public PlayerPanel(final int index) { + public PlayerPanel(final int index0) { super(); - index = index; + index = index0; playerIsArchenemy = index == 0; // Add a button to players 3+ to remove them from the setup @@ -165,65 +291,52 @@ public class ConstructedScreen extends LaunchScreen { add(nameRandomiser); createPlayerTypeOptions(); - add(radioHuman, "gapright 5px"); - add(radioAi, "wrap"); + add(radioHuman); + add(radioAi); - add(newLabel("Team:"), "w 40px, h 30px"); + add(newLabel("Team:")); populateTeamsComboBoxes(); - teamComboBox.addActionListener(teamListener); - aeTeamComboBox.addActionListener(teamListener); - teamComboBox.addTo(this, variantBtnConstraints + ", pushx, growx, gaptop 5px"); - aeTeamComboBox.addTo(this, variantBtnConstraints + ", pushx, growx, gaptop 5px"); + teamComboBox.setChangedHandler(teamChangedHandler); + aeTeamComboBox.setChangedHandler(teamChangedHandler); + add(teamComboBox); + add(aeTeamComboBox); - add(deckLabel, variantBtnConstraints + ", cell 0 2, sx 2, ax right"); - add(deckBtn, variantBtnConstraints + ", cell 2 2, pushx, growx, wmax 100%-153px, h 30px, spanx 4, wrap"); + add(deckLabel); + add(deckBtn); addHandlersDeckSelector(); - add(cmdLabel, variantBtnConstraints + ", cell 0 3, sx 2, ax right"); - add(cmdDeckSelectorBtn, variantBtnConstraints + ", cell 2 3, growx, pushx"); - add(cmdDeckEditor, variantBtnConstraints + ", cell 3 3, sx 3, growx, wrap"); + add(cmdLabel); + add(cmdDeckSelectorBtn); + add(cmdDeckEditor); - add(scmLabel, variantBtnConstraints + ", cell 0 4, sx 2, ax right"); - add(scmDeckSelectorBtn, variantBtnConstraints + ", cell 2 4, growx, pushx"); - add(scmDeckEditor, variantBtnConstraints + ", cell 3 4, sx 3, growx, wrap"); + add(scmLabel); + add(scmDeckSelectorBtn); + add(scmDeckEditor); - add(pchLabel, variantBtnConstraints + ", cell 0 5, sx 2, ax right"); - add(pchDeckSelectorBtn, variantBtnConstraints + ", cell 2 5, growx, pushx"); - add(pchDeckEditor, variantBtnConstraints + ", cell 3 5, sx 3, growx, wrap"); + add(pchLabel); + add(pchDeckSelectorBtn); + add(pchDeckEditor); - add(vgdLabel, variantBtnConstraints + ", cell 0 6, sx 2, ax right"); - add(vgdSelectorBtn, variantBtnConstraints + ", cell 2 6, sx 4, growx, wrap"); + add(vgdLabel); + add(vgdSelectorBtn); addHandlersToVariantsControls(); updateVariantControlsVisibility(); + } - addMouseListener(new FMouseAdapter() { - @Override - public void onLeftMouseDown(MouseEvent e) { - avatarLabel.requestFocusInWindow(); - } - }); - }*/ - - /*private final FMouseAdapter radioMouseAdapter = new FMouseAdapter() { + private final FEventHandler radioMouseAdapter = new FEventHandler() { @Override - public void onLeftClick(MouseEvent e) { - avatarLabel.requestFocusInWindow(); + public void handleEvent(FEvent e) { updateVanguardList(index); } }; //Listens to name text fields and gives the appropriate player focus. //Also saves the name preference when leaving player one's text field. */ - /*private FocusAdapter nameFocusListener = new FocusAdapter() { + private FEventHandler nameChangedHandler = new FEventHandler() { @Override - public void focusGained(FocusEvent e) { - changePlayerFocus(index); - } - - @Override - public void focusLost(FocusEvent e) { + public void handleEvent(FEvent e) { final Object source = e.getSource(); if (source instanceof FTextField) { // the text box FTextField nField = (FTextField)source; @@ -237,52 +350,34 @@ public class ConstructedScreen extends LaunchScreen { } }; - // Listens to avatar buttons and gives the appropriate player focus. - private FocusAdapter avatarFocusListener = new FocusAdapter() { - @Override - public void focusGained(FocusEvent e) { - changePlayerFocus(index); - } - };*/ - @Override protected void doLayout(float width, float height) { // TODO Auto-generated method stub } - /*private FMouseAdapter avatarMouseListener = new FMouseAdapter() { + private FEventHandler avatarCommand = new FEventHandler() { @Override - public void onLeftClick(MouseEvent e) { - final FLabel avatar = (FLabel)e.getSource(); + public void handleEvent(FEvent e) { + setRandomAvatar(); - changePlayerFocus(index); - avatar.requestFocusInWindow(); + //TODO: Support selecting avatar with option at top or bottom to select a random avatar + + /*final FLabel avatar = (FLabel)e.getSource(); final AvatarSelector aSel = new AvatarSelector(getPlayerName(), avatarIndex, getUsedAvatars()); for (final FLabel lbl : aSel.getSelectables()) { - lbl.setCommand(new UiCommand() { + lbl.setCommand(new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { setAvatar(Integer.valueOf(lbl.getName().substring(11))); aSel.setVisible(false); } }); } - + aSel.setVisible(true); - aSel.dispose(); - - if (index < 2) { - updateAvatarPrefs(); - } - } - @Override - public void onRightClick(MouseEvent e) { - changePlayerFocus(index); - avatarLabel.requestFocusInWindow(); - - setRandomAvatar(); + aSel.dispose();*/ if (index < 2) { updateAvatarPrefs(); @@ -341,12 +436,10 @@ public class ConstructedScreen extends LaunchScreen { teamComboBox.setEnabled(true); } - private ActionListener teamListener = new ActionListener() { - @SuppressWarnings("unchecked") + private FEventHandler teamChangedHandler = new FEventHandler() { @Override - public void actionPerformed(ActionEvent e) { + public void handleEvent(FEvent e) { FComboBox cb = (FComboBox)e.getSource(); - cb.requestFocusInWindow(); Object selection = cb.getSelectedItem(); if (null == selection) { @@ -363,41 +456,36 @@ public class ConstructedScreen extends LaunchScreen { pp.toggleIsPlayerArchenemy(); } } - } else { + } + else { Integer sel = (Integer) selection; teams.set(index, sel); } - - changePlayerFocus(index); } }; public void toggleIsPlayerArchenemy() { if (appliedVariants.contains(GameType.Archenemy)) { playerIsArchenemy = lastArchenemy == index; - } else { + } + else { playerIsArchenemy = appliedVariants.contains(GameType.ArchenemyRumble); } updateVariantControlsVisibility(); } - *//** - * @param index - *//* private void addHandlersToVariantsControls() { // Archenemy buttons - scmDeckSelectorBtn.setCommand(new Runnable() { + scmDeckSelectorBtn.setCommand(new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { currentGameMode = archenemyType.contains("Classic") ? GameType.Archenemy : GameType.ArchenemyRumble; - scmDeckSelectorBtn.requestFocusInWindow(); - changePlayerFocus(index, currentGameMode); } }); - scmDeckEditor.setCommand(new UiCommand() { + scmDeckEditor.setCommand(new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { currentGameMode = archenemyType.contains("Classic") ? GameType.Archenemy : GameType.ArchenemyRumble; Predicate predSchemes = new Predicate() { @Override @@ -406,109 +494,89 @@ public class ConstructedScreen extends LaunchScreen { } }; - Singletons.getControl().setCurrentScreen(FScreen.DECK_EDITOR_ARCHENEMY); + /*Forge.setCurrentScreen(FScreen.DECK_EDITOR_ARCHENEMY); CDeckEditorUI.SINGLETON_INSTANCE.setEditorController( - new CEditorVariant(Singletons.getModel().getDecks().getScheme(), predSchemes, DeckSection.Schemes, FScreen.DECK_EDITOR_PLANECHASE)); + new CEditorVariant(FModel.getDecks().getScheme(), predSchemes, DeckSection.Schemes, FScreen.DECK_EDITOR_PLANECHASE));*/ } }); // Commander buttons - cmdDeckSelectorBtn.setCommand(new Runnable() { + cmdDeckSelectorBtn.setCommand(new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { currentGameMode = GameType.Commander; - cmdDeckSelectorBtn.requestFocusInWindow(); - changePlayerFocus(index, currentGameMode); } }); - cmdDeckEditor.setCommand(new UiCommand() { + cmdDeckEditor.setCommand(new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { currentGameMode = GameType.Commander; - Singletons.getControl().setCurrentScreen(FScreen.DECK_EDITOR_COMMANDER); - CDeckEditorUI.SINGLETON_INSTANCE.setEditorController(new CEditorCommander()); + //Forge.setCurrentScreen(FScreen.DECK_EDITOR_COMMANDER); } }); // Planechase buttons - pchDeckSelectorBtn.setCommand(new Runnable() { + pchDeckSelectorBtn.setCommand(new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { currentGameMode = GameType.Planechase; - pchDeckSelectorBtn.requestFocusInWindow(); - changePlayerFocus(index, GameType.Planechase); } }); - pchDeckEditor.setCommand(new UiCommand() { + pchDeckEditor.setCommand(new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { currentGameMode = GameType.Planechase; - Predicate predPlanes = new Predicate() { + /*Predicate predPlanes = new Predicate() { @Override public boolean apply(PaperCard arg0) { return arg0.getRules().getType().isPlane() || arg0.getRules().getType().isPhenomenon(); } }; - Singletons.getControl().setCurrentScreen(FScreen.DECK_EDITOR_PLANECHASE); + Forge.setCurrentScreen(FScreen.DECK_EDITOR_PLANECHASE); CDeckEditorUI.SINGLETON_INSTANCE.setEditorController( - new CEditorVariant(Singletons.getModel().getDecks().getPlane(), predPlanes, DeckSection.Planes, FScreen.DECK_EDITOR_PLANECHASE)); + new CEditorVariant(FModel.getDecks().getPlane(), predPlanes, DeckSection.Planes, FScreen.DECK_EDITOR_PLANECHASE));*/ } }); // Vanguard buttons - vgdSelectorBtn.setCommand(new Runnable() { + vgdSelectorBtn.setCommand(new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { currentGameMode = GameType.Vanguard; - vgdSelectorBtn.requestFocusInWindow(); - changePlayerFocus(index, GameType.Vanguard); } }); } - /** - * @param index - *//* private void createPlayerTypeOptions() { radioHuman = new FRadioButton("Human", index == 0); radioAi = new FRadioButton("AI", index != 0); - radioHuman.addMouseListener(radioMouseAdapter); - radioAi.addMouseListener(radioMouseAdapter); + radioHuman.setCommand(radioMouseAdapter); + radioAi.setCommand(radioMouseAdapter); - ButtonGroup tempBtnGroup = new ButtonGroup(); - tempBtnGroup.add(radioHuman); - tempBtnGroup.add(radioAi); + RadioButtonGroup radioButtonGroup = new RadioButtonGroup(); + radioHuman.setGroup(radioButtonGroup); + radioAi.setGroup(radioButtonGroup); } - *//** - * @param index - *//* private void addHandlersDeckSelector() { - deckBtn.setCommand(new Runnable() { + deckBtn.setCommand(new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { currentGameMode = GameType.Constructed; - deckBtn.requestFocusInWindow(); - changePlayerFocus(index, GameType.Constructed); } }); } - *//** - * @param index - * @return - *//* private FLabel createNameRandomizer() { - final FLabel newNameBtn = new FLabel.Builder().tooltip("Get a new random name").iconInBackground(false) - .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_EDIT)).hoverable(true).opaque(false) - .unhoveredAlpha(0.9f).build(); - newNameBtn.setCommand(new UiCommand() { + final FLabel newNameBtn = new FLabel.Builder().iconInBackground(false) + .icon(FSkinImage.EDIT).opaque(false).build(); + newNameBtn.setCommand(new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { String newName = getNewName(); if (null == newName) { return; @@ -519,22 +587,15 @@ public class ConstructedScreen extends LaunchScreen { prefs.setPref(FPref.PLAYER_NAME, newName); prefs.save(); } - txtPlayerName.requestFocus(); - changePlayerFocus(index); } }); - newNameBtn.addFocusListener(nameFocusListener); return newNameBtn; } - *//** - * @param index - * @return - *//* private void createNameEditor() { String name; if (index == 0) { - name = Singletons.getModel().getPreferences().getPref(FPref.PLAYER_NAME); + name = FModel.getPreferences().getPref(FPref.PLAYER_NAME); if (name.isEmpty()) { name = "Human"; } @@ -544,18 +605,16 @@ public class ConstructedScreen extends LaunchScreen { } txtPlayerName.setText(name); - txtPlayerName.setFocusable(true); - txtPlayerName.setFont(FSkin.getFont(14)); - txtPlayerName.addActionListener(nameListener); - txtPlayerName.addFocusListener(nameFocusListener); + txtPlayerName.setFontSize(14); + txtPlayerName.setChangedHandler(nameChangedHandler); } private FLabel createCloseButton() { final FLabel closeBtn = new FLabel.Builder().iconInBackground(false) - .icon(FSkin.getIcon(FSkin.InterfaceIcons.ICO_CLOSE)).hoverable(true).build(); - closeBtn.setCommand(new Runnable() { + .icon(FSkinImage.CLOSE).build(); + closeBtn.setCommand(new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { removePlayer(closePlayerBtnList.indexOf(closeBtn) + 2); } }); @@ -567,19 +626,16 @@ public class ConstructedScreen extends LaunchScreen { String[] currentPrefs = prefs.getPref(FPref.UI_AVATARS).split(","); if (index < currentPrefs.length) { avatarIndex = Integer.parseInt(currentPrefs[index]); - avatarLabel.setIcon(FSkin.getAvatars().get(avatarIndex)); + avatarLabel.setIcon(new FTextureRegionImage(FSkin.getAvatars().get(avatarIndex))); } else { setRandomAvatar(); } - avatarLabel.setToolTipText("L-click: Select avatar. R-click: Randomize avatar."); - avatarLabel.addFocusListener(avatarFocusListener); - avatarLabel.addMouseListener(avatarMouseListener); + avatarLabel.setCommand(avatarCommand); } - *//** Applies a random avatar, avoiding avatars already used. - * @param playerIndex *//* + //Applies a random avatar, avoiding avatars already used. public void setRandomAvatar() { int random = 0; @@ -592,14 +648,9 @@ public class ConstructedScreen extends LaunchScreen { public void setAvatar(int newAvatarIndex) { avatarIndex = newAvatarIndex; - TextureRegion icon = FSkin.getAvatars().get(newAvatarIndex); - avatarLabel.setIcon(icon); - avatarLabel.repaintSelf(); + avatarLabel.setIcon(new FTextureRegionImage(FSkin.getAvatars().get(newAvatarIndex))); } - private final FSkin.LineSkinBorder focusedBorder = new FSkin.LineSkinBorder(FSkin.getColor(FSkin.Colors.CLR_BORDERS).alphaColor(255), 3); - private final FSkin.LineSkinBorder defaultBorder = new FSkin.LineSkinBorder(FSkin.getColor(FSkin.Colors.CLR_THEME).alphaColor(200), 2); - public int getAvatarIndex() { return avatarIndex; } @@ -610,6 +661,290 @@ public class ConstructedScreen extends LaunchScreen { public String getPlayerName() { return txtPlayerName.getText(); + } + } + + /** Saves avatar prefs for players one and two. */ + private void updateAvatarPrefs() { + int pOneIndex = playerPanels.get(0).getAvatarIndex(); + int pTwoIndex = playerPanels.get(1).getAvatarIndex(); + + prefs.setPref(FPref.UI_AVATARS, pOneIndex + "," + pTwoIndex); + prefs.save(); + } + + /** Updates the avatars from preferences on update. */ + public void updatePlayersFromPrefs() { + ForgePreferences prefs = FModel.getPreferences(); + + // Avatar + String[] avatarPrefs = prefs.getPref(FPref.UI_AVATARS).split(","); + for (int i = 0; i < avatarPrefs.length; i++) { + int avatarIndex = Integer.parseInt(avatarPrefs[i]); + playerPanels.get(i).setAvatar(avatarIndex); + } + + // Name + String prefName = prefs.getPref(FPref.PLAYER_NAME); + playerPanels.get(0).setPlayerName(StringUtils.isBlank(prefName) ? "Human" : prefName); + } + + /** Adds a pre-styled FLabel component with the specified title. */ + private FLabel newLabel(String title) { + return new FLabel.Builder().text(title).fontSize(14).build(); + } + + private List getUsedAvatars() { + List usedAvatars = Arrays.asList(-1,-1,-1,-1,-1,-1,-1,-1); + int i = 0; + for (PlayerPanel pp : playerPanels) { + usedAvatars.set(i++, pp.avatarIndex); + } + return usedAvatars; + } + + private final String getNewName() { + final String title = "Get new random name"; + final String message = "What type of name do you want to generate?"; + final FSkinImage icon = FOptionPane.QUESTION_ICON; + final String[] genderOptions = new String[]{ "Male", "Female", "Any" }; + final String[] typeOptions = new String[]{ "Fantasy", "Generic", "Any" }; + + final int genderIndex = FOptionPane.showOptionDialog(message, title, icon, genderOptions, 2); + if (genderIndex < 0) { + return null; + } + final int typeIndex = FOptionPane.showOptionDialog(message, title, icon, typeOptions, 2); + if (typeIndex < 0) { + return null; + } + + final String gender = genderOptions[genderIndex]; + final String type = typeOptions[typeIndex]; + + String confirmMsg, newName; + List usedNames = getPlayerNames(); + do { + newName = NameGenerator.getRandomName(gender, type, usedNames); + confirmMsg = "Would you like to use the name \"" + newName + "\", or try again?"; + } while (!FOptionPane.showConfirmDialog(confirmMsg, title, "Use this name", "Try again", true)); + + return newName; + } + + private List getPlayerNames() { + List names = new ArrayList(); + for (PlayerPanel pp : playerPanels) { + names.add(pp.getPlayerName()); + } + return names; + } + + public String getPlayerName(int i) { + return playerPanels.get(i).getPlayerName(); + } + + public int getPlayerAvatar(int i) { + return playerPanels.get(i).getAvatarIndex(); + } + + public boolean isEnoughTeams() { + int lastTeam = -1; + final List teamList = appliedVariants.contains(GameType.Archenemy) ? archenemyTeams : teams; + + for (final int i : getParticipants()) { + if (lastTeam == -1) { + lastTeam = teamList.get(i); + } + else if (lastTeam != teamList.get(i)) { + return true; + } + } + return false; + } + + ///////////////////////////////////////////// + //========== Various listeners in build order + + /** This listener unlocks the relevant buttons for players + * and enables/disables archenemy combobox as appropriate. */ + private ItemListener iListenerVariants = new ItemListener() { + @Override + public void itemStateChanged(ItemEvent arg0) { + FCheckBox cb = (FCheckBox) arg0.getSource(); + GameType variantType = null; + + if (cb == vntVanguard) { + variantType = GameType.Vanguard; + } + else if (cb == vntCommander) { + variantType = GameType.Commander; + } + else if (cb == vntPlanechase) { + variantType = GameType.Planechase; + } + else if (cb == vntArchenemy) { + variantType = archenemyType.contains("Classic") ? GameType.Archenemy : GameType.ArchenemyRumble; + comboArchenemy.setEnabled(vntArchenemy.isSelected()); + if (arg0.getStateChange() != ItemEvent.SELECTED) { + appliedVariants.remove(GameType.Archenemy); + appliedVariants.remove(GameType.ArchenemyRumble); + } + } + + if (null != variantType) { + if (arg0.getStateChange() == ItemEvent.SELECTED) { + appliedVariants.add(variantType); + currentGameMode = variantType; + } + else { + appliedVariants.remove(variantType); + if (currentGameMode == variantType) { + currentGameMode = GameType.Constructed; + } + } + } + + for (PlayerPanel pp : playerPanels) { + pp.toggleIsPlayerArchenemy(); + pp.updateVariantControlsVisibility(); + } + } + }; + + // Listens to the archenemy combo box + private ActionListener aeComboListener = new ActionListener() { + @SuppressWarnings("unchecked") + @Override + public void actionPerformed(ActionEvent e) { + FComboBox cb = (FComboBox)e.getSource(); + archenemyType = (String)cb.getSelectedItem(); + GameType mode = archenemyType.contains("Classic") ? GameType.Archenemy : GameType.ArchenemyRumble; + appliedVariants.remove(GameType.Archenemy); + appliedVariants.remove(GameType.ArchenemyRumble); + appliedVariants.add(mode); + + currentGameMode = mode; + for (PlayerPanel pp : playerPanels) { + pp.toggleIsPlayerArchenemy(); + pp.updateVariantControlsVisibility(); + } + } + }; + + //This listener will look for a vanguard avatar being selected in the lists + //and update the corresponding detail panel. + /*private ListSelectionListener vgdLSListener = new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + int index = vgdAvatarLists.indexOf(e.getSource()); + Object obj = vgdAvatarLists.get(index).getSelectedValue(); + PlayerPanel pp = playerPanels.get(index); + CardDetailPanel cdp = vgdAvatarDetails.get(index); + + if (obj instanceof PaperCard) { + pp.setVanguardButtonText(((PaperCard) obj).getName()); + cdp.setCard(Card.getCardForUi((PaperCard) obj)); + cdp.setVisible(true); + refreshPanels(false, true); + } + else { + pp.setVanguardButtonText((String) obj); + cdp.setVisible(false); + } + } + };*/ + + ///////////////////////////////////// + //========== METHODS FOR VARIANTS + + public Set getAppliedVariants() { + return appliedVariants; + } + + public int getTeam(final int playerIndex) { + return appliedVariants.contains(GameType.Archenemy) ? archenemyTeams.get(playerIndex) : teams.get(playerIndex); + } + + /*public List> getPlanarDeckLists() { + return planarDeckLists; + } + + public List> getCommanderDeckLists() { + return commanderDeckLists; + } + + public List> getSchemeDeckLists() { + return schemeDeckLists; + } + + public List> getVanguardLists() { + return vgdAvatarLists; + }*/ + + public boolean isPlayerArchenemy(final int playernum) { + return playerPanels.get(playernum).playerIsArchenemy; + } + + /** Return all the Vanguard avatars. */ + public Iterable getAllAvatars() { + if (vgdAllAvatars.isEmpty()) { + for (PaperCard c : FModel.getMagicDb().getVariantCards().getAllCards()) { + if (c.getRules().getType().isVanguard()) { + vgdAllAvatars.add(c); + } + } + } + return vgdAllAvatars; + } + + /** Return the Vanguard avatars not flagged RemAIDeck. */ + public List getAllAiAvatars() { + return vgdAllAiAvatars; + } + + /** Return the Vanguard avatars not flagged RemRandomDeck. */ + public List getNonRandomHumanAvatars() { + return nonRandomHumanAvatars; + } + + /** Return the Vanguard avatars not flagged RemAIDeck or RemRandomDeck. */ + public List getNonRandomAiAvatars() { + return nonRandomAiAvatars; + } + + /** Populate vanguard lists. */ + private void populateVanguardLists() { + humanListData.add("Use deck's default avatar (random if unavailable)"); + humanListData.add("Random"); + aiListData.add("Use deck's default avatar (random if unavailable)"); + aiListData.add("Random"); + for (PaperCard cp : getAllAvatars()) { + humanListData.add(cp); + if (!cp.getRules().getAiHints().getRemRandomDecks()) { + nonRandomHumanAvatars.add(cp); + } + if (!cp.getRules().getAiHints().getRemAIDecks()) { + aiListData.add(cp); + vgdAllAiAvatars.add(cp); + if (!cp.getRules().getAiHints().getRemRandomDecks()) { + nonRandomAiAvatars.add(cp); + } + } + } + } + + /** update vanguard list. */ + public void updateVanguardList(int playerIndex) { + /*FList vgdList = getVanguardLists().get(playerIndex); + Object lastSelection = vgdList.getSelectedValue(); + vgdList.setListData(isPlayerAI(playerIndex) ? aiListData : humanListData); + if (null != lastSelection) { + vgdList.setSelectedValue(lastSelection, true); + } + + if (-1 == vgdList.getSelectedIndex()) { + vgdList.setSelectedIndex(0); }*/ } } diff --git a/forge-m-base/src/forge/screens/home/HomeScreen.java b/forge-m-base/src/forge/screens/home/HomeScreen.java index ccb6cbba1ee..7400d705d98 100644 --- a/forge-m-base/src/forge/screens/home/HomeScreen.java +++ b/forge-m-base/src/forge/screens/home/HomeScreen.java @@ -13,6 +13,8 @@ import forge.screens.quest.QuestScreen; import forge.screens.sealed.SealedScreen; import forge.screens.settings.SettingsScreen; import forge.toolbox.FButton; +import forge.toolbox.FEvent; +import forge.toolbox.FEvent.FEventHandler; public class HomeScreen extends FScreen { private static final float LOGO_SIZE_FACTOR = 0.7f; @@ -23,45 +25,45 @@ public class HomeScreen extends FScreen { public HomeScreen() { super(false, null, false); - addButton("Constructed", new Runnable() { + addButton("Constructed", new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { Forge.openScreen(new ConstructedScreen()); } }); - addButton("Draft", new Runnable() { + addButton("Draft", new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { Forge.openScreen(new DraftScreen()); } }); - addButton("Sealed", new Runnable() { + addButton("Sealed", new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { Forge.openScreen(new SealedScreen()); } }); - addButton("Quest", new Runnable() { + addButton("Quest", new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { Forge.openScreen(new QuestScreen()); } }); - addButton("Guantlet", new Runnable() { + addButton("Guantlet", new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { Forge.openScreen(new GuantletScreen()); } }); - addButton("Settings", new Runnable() { + addButton("Settings", new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { Forge.openScreen(new SettingsScreen()); } }); } - private void addButton(String caption, Runnable command) { + private void addButton(String caption, FEventHandler command) { buttons.add(add(new FButton(caption, command))); } diff --git a/forge-m-base/src/forge/screens/match/MatchScreen.java b/forge-m-base/src/forge/screens/match/MatchScreen.java index b3e06df849d..288761192b1 100644 --- a/forge-m-base/src/forge/screens/match/MatchScreen.java +++ b/forge-m-base/src/forge/screens/match/MatchScreen.java @@ -24,6 +24,8 @@ import forge.game.Game; import forge.game.player.LobbyPlayer; import forge.game.player.Player; import forge.game.zone.ZoneType; +import forge.toolbox.FEvent; +import forge.toolbox.FEvent.FEventHandler; public class MatchScreen extends FScreen { public static FSkinColor BORDER_COLOR = FSkinColor.get(Colors.CLR_BORDERS); @@ -49,15 +51,15 @@ public class MatchScreen extends FScreen { bottomPlayerPanel.setSelectedZone(ZoneType.Hand); prompt = add(new VPrompt("", "", - new Runnable() { + new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { FControl.getInputProxy().selectButtonOK(); } }, - new Runnable() { + new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { FControl.getInputProxy().selectButtonCancel(); } })); diff --git a/forge-m-base/src/forge/screens/match/views/VPrompt.java b/forge-m-base/src/forge/screens/match/views/VPrompt.java index c78ef6fc97d..4e81ee7b806 100644 --- a/forge-m-base/src/forge/screens/match/views/VPrompt.java +++ b/forge-m-base/src/forge/screens/match/views/VPrompt.java @@ -12,6 +12,7 @@ import forge.game.Game; import forge.toolbox.FButton; import forge.toolbox.FButton.Corner; import forge.toolbox.FContainer; +import forge.toolbox.FEvent.FEventHandler; import forge.utils.Utils; public class VPrompt extends FContainer { @@ -26,7 +27,7 @@ public class VPrompt extends FContainer { private final FButton btnOk, btnCancel; private String message; - public VPrompt(String okText, String cancelText, Runnable okCommand, Runnable cancelCommand) { + public VPrompt(String okText, String cancelText, FEventHandler okCommand, FEventHandler cancelCommand) { btnOk = add(new FButton(okText, okCommand)); btnCancel = add(new FButton(cancelText, cancelCommand)); btnOk.setSize(BTN_WIDTH, HEIGHT); diff --git a/forge-m-base/src/forge/screens/match/winlose/ControlWinLose.java b/forge-m-base/src/forge/screens/match/winlose/ControlWinLose.java index 797e9fe22c0..f90f4aa4cda 100644 --- a/forge-m-base/src/forge/screens/match/winlose/ControlWinLose.java +++ b/forge-m-base/src/forge/screens/match/winlose/ControlWinLose.java @@ -4,6 +4,8 @@ import forge.game.Game; import forge.game.Match; import forge.model.FModel; import forge.screens.match.FControl; +import forge.toolbox.FEvent; +import forge.toolbox.FEvent.FEventHandler; /** * Default controller for a ViewWinLose object. This class can @@ -25,23 +27,23 @@ public class ControlWinLose { /** */ public void addListeners() { - view.getBtnContinue().setCommand(new Runnable() { + view.getBtnContinue().setCommand(new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { actionOnContinue(); } }); - view.getBtnRestart().setCommand(new Runnable() { + view.getBtnRestart().setCommand(new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { actionOnRestart(); } }); - view.getBtnQuit().setCommand(new Runnable() { + view.getBtnQuit().setCommand(new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { actionOnQuit(); view.getBtnQuit().setEnabled(false); } diff --git a/forge-m-base/src/forge/screens/match/winlose/ViewWinLose.java b/forge-m-base/src/forge/screens/match/winlose/ViewWinLose.java index 70a904d2486..599af749e32 100644 --- a/forge-m-base/src/forge/screens/match/winlose/ViewWinLose.java +++ b/forge-m-base/src/forge/screens/match/winlose/ViewWinLose.java @@ -15,6 +15,8 @@ import forge.model.FModel; import forge.toolbox.FButton; import forge.toolbox.FContainer; import forge.toolbox.FDisplayObject; +import forge.toolbox.FEvent; +import forge.toolbox.FEvent.FEventHandler; import forge.toolbox.FLabel; import forge.toolbox.FOverlay; import forge.toolbox.FPanel; @@ -81,9 +83,9 @@ public class ViewWinLose extends FOverlay { txtLog = add(new FTextArea(game.getGameLog().getLogText(null).replace("[COMPUTER]", "[AI]"))); txtLog.setFontSize(14); - btnCopyLog = add(new FLabel.ButtonBuilder().text("Copy to clipboard").command(new Runnable() { + btnCopyLog = add(new FLabel.ButtonBuilder().text("Copy to clipboard").command(new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { Forge.getClipboard().setContents(txtLog.getText()); } }).build()); diff --git a/forge-m-base/src/forge/toolbox/FButton.java b/forge-m-base/src/forge/toolbox/FButton.java index 99f1da519c4..9cc50f92cbf 100644 --- a/forge-m-base/src/forge/toolbox/FButton.java +++ b/forge-m-base/src/forge/toolbox/FButton.java @@ -10,6 +10,8 @@ import forge.assets.FSkinColor; import forge.assets.FSkinColor.Colors; import forge.assets.FSkinFont; import forge.assets.FSkinImage; +import forge.toolbox.FEvent.FEventHandler; +import forge.toolbox.FEvent.FEventType; public class FButton extends FDisplayObject { private static final FSkinColor FORE_COLOR = FSkinColor.get(Colors.CLR_TEXT); @@ -20,8 +22,8 @@ public class FButton extends FDisplayObject { private String text; private FSkinFont font; private boolean toggled = false; - private Runnable command; - + private FEventHandler command; + public enum Corner { None, BottomLeft, @@ -40,7 +42,7 @@ public class FButton extends FDisplayObject { this(text0, null); } - public FButton(final String text0, Runnable command0) { + public FButton(final String text0, FEventHandler command0) { text = text0; command = command0; font = FSkinFont.get(14); @@ -113,7 +115,7 @@ public class FButton extends FDisplayObject { corner = corner0; } - public void setCommand(Runnable command0) { + public void setCommand(FEventHandler command0) { command = command0; } @@ -136,7 +138,7 @@ public class FButton extends FDisplayObject { @Override public final boolean tap(float x, float y, int count) { if (count == 1 && command != null) { - command.run(); + command.handleEvent(new FEvent(this, FEventType.TAP)); } return true; } diff --git a/forge-m-base/src/forge/toolbox/FCardZoom.java b/forge-m-base/src/forge/toolbox/FCardZoom.java index 9dd419ef745..230a4028812 100644 --- a/forge-m-base/src/forge/toolbox/FCardZoom.java +++ b/forge-m-base/src/forge/toolbox/FCardZoom.java @@ -12,6 +12,8 @@ import forge.assets.FSkinFont; import forge.assets.FSkinColor.Colors; import forge.game.card.Card; import forge.screens.match.views.VPrompt; +import forge.toolbox.FEvent; +import forge.toolbox.FEvent.FEventHandler; import forge.toolbox.FList.ListItemRenderer; public class FCardZoom extends FOverlay { @@ -119,15 +121,15 @@ public class FCardZoom extends FOverlay { } }); prompt = add(new VPrompt("Hide", "More", - new Runnable() { + new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { hide(); } }, - new Runnable() { + new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { optionListExpanded = !optionListExpanded; prompt.getBtnCancel().setText(optionListExpanded ? "Less" : "More"); revalidate(); diff --git a/forge-m-base/src/forge/toolbox/FCheckBox.java b/forge-m-base/src/forge/toolbox/FCheckBox.java index 1b4e0277250..bdd256f92b2 100644 --- a/forge-m-base/src/forge/toolbox/FCheckBox.java +++ b/forge-m-base/src/forge/toolbox/FCheckBox.java @@ -1,6 +1,7 @@ package forge.toolbox; import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment; + import forge.Forge.Graphics; import forge.assets.FImage; import forge.assets.FSkinColor; @@ -11,11 +12,14 @@ public class FCheckBox extends FLabel { private static final FSkinColor BOX_COLOR = CHECK_COLOR.alphaColor(0.5f); public FCheckBox() { - this(""); + this("", false); } public FCheckBox(String text0) { - super(new Builder().align(HAlignment.LEFT).selectable()); - this.setIcon(new CheckBoxIcon()); + this(text0, false); + } + public FCheckBox(String text0, boolean selected0) { + super(new Builder().align(HAlignment.LEFT).selectable().selected(selected0)); + setIcon(new CheckBoxIcon()); } private class CheckBoxIcon implements FImage { diff --git a/forge-m-base/src/forge/toolbox/FComboBox.java b/forge-m-base/src/forge/toolbox/FComboBox.java index cb69613592b..b7b07872c45 100644 --- a/forge-m-base/src/forge/toolbox/FComboBox.java +++ b/forge-m-base/src/forge/toolbox/FComboBox.java @@ -4,9 +4,11 @@ import java.util.ArrayList; import java.util.List; import forge.Forge.Graphics; +import forge.toolbox.FEvent.FEventType; public class FComboBox extends FTextField { private final List items = new ArrayList(); + private E selectedItem; public FComboBox() { initialize(); @@ -24,11 +26,88 @@ public class FComboBox extends FTextField { initialize(); } + public void addItem(E item) { + items.add(item); + } + + public boolean removeItem(E item) { + int restoreIndex = -1; + if (selectedItem == item) { + restoreIndex = getSelectedIndex(); + } + if (items.remove(item)) { + if (restoreIndex >= 0) { + setSelectedIndex(restoreIndex); + } + } + return false; + } + + public int getSelectedIndex() { + if (selectedItem == null) { return -1; } + return items.indexOf(selectedItem); + } + + public void setSelectedIndex(int index) { + if (index < 0) { + setSelectedItem(null); + return; + } + + if (index >= items.size()) { + index = items.size() - 1; + } + setSelectedItem(items.get(index)); + } + + public E getSelectedItem() { + return selectedItem; + } + + public void setSelectedItem(E item) { + if (selectedItem == item) { return; } + + if (item != null) { + if (items.contains(item)) { + selectedItem = item; + super.setText(item.toString()); + } + } + else { + selectedItem = null; + super.setText(""); + } + + if (getChangedHandler() != null) { + getChangedHandler().handleEvent(new FEvent(this, FEventType.CHANGE, item)); + } + } + + @Override + public void setText(String text0) { + for (E item : items) { + if (item.toString().equals(text0)) { + setSelectedItem(item); + return; + } + } + selectedItem = null; + setText(text0); + } + private void initialize() { + if (!items.isEmpty()) { + setSelectedItem(items.get(0)); //select first item by default + } + } + + @Override + public boolean tap(float x, float y, int count) { + return true; } @Override public void draw(Graphics g) { - + super.draw(g); } } diff --git a/forge-m-base/src/forge/toolbox/FEvent.java b/forge-m-base/src/forge/toolbox/FEvent.java index 862456c4c42..785f50038b7 100644 --- a/forge-m-base/src/forge/toolbox/FEvent.java +++ b/forge-m-base/src/forge/toolbox/FEvent.java @@ -2,24 +2,25 @@ package forge.toolbox; public class FEvent { public enum FEventType { - TAP + TAP, + CHANGE } - private FDisplayObject owner; + private FDisplayObject source; private FEventType type; private Object args; - public FEvent(FDisplayObject owner0, FEventType type0) { - this(owner0, type0, null); + public FEvent(FDisplayObject source0, FEventType type0) { + this(source0, type0, null); } - public FEvent(FDisplayObject owner0, FEventType type0, Object args0) { - owner = owner0; + public FEvent(FDisplayObject source0, FEventType type0, Object args0) { + source = source0; type = type0; args = args0; } - public FDisplayObject getOwner() { - return owner; + public FDisplayObject getSource() { + return source; } public FEventType getType() { diff --git a/forge-m-base/src/forge/toolbox/FLabel.java b/forge-m-base/src/forge/toolbox/FLabel.java index e9340234293..a8b551faf3e 100644 --- a/forge-m-base/src/forge/toolbox/FLabel.java +++ b/forge-m-base/src/forge/toolbox/FLabel.java @@ -9,6 +9,8 @@ import forge.assets.FImage; import forge.assets.FSkinColor; import forge.assets.FSkinColor.Colors; import forge.assets.FSkinFont; +import forge.toolbox.FEvent.FEventHandler; +import forge.toolbox.FEvent.FEventType; public class FLabel extends FDisplayObject { public static class Builder { @@ -29,7 +31,7 @@ public class FLabel extends FDisplayObject { private FImage bldIcon; private FSkinColor bldTextColor = DEFAULT_TEXT_COLOR; private FSkinColor bldPressedColor; - private Runnable bldCommand; + private FEventHandler bldCommand; public FLabel build() { return new FLabel(this); } @@ -44,7 +46,7 @@ public class FLabel extends FDisplayObject { public Builder selectable() { selectable(true); return this; } public Builder selected(final boolean b0) { this.bldSelected = b0; return this; } public Builder selected() { selected(true); return this; } - public Builder command(final Runnable c0) { this.bldCommand = c0; return this; } + public Builder command(final FEventHandler c0) { this.bldCommand = c0; return this; } public Builder fontSize(final int i0) { this.bldFontSize = i0; return this; } public Builder enabled(final boolean b0) { this.bldEnabled = b0; return this; } public Builder iconScaleAuto(final boolean b0) { this.bldIconScaleAuto = b0; return this; } @@ -80,7 +82,7 @@ public class FLabel extends FDisplayObject { private String text; private FImage icon; private FSkinColor textColor, pressedColor; - private Runnable command; + private FEventHandler command; // Call this using FLabel.Builder()... protected FLabel(final Builder b0) { @@ -133,7 +135,7 @@ public class FLabel extends FDisplayObject { icon = icon0; } - public void setCommand(final Runnable command0) { + public void setCommand(final FEventHandler command0) { command = command0; } @@ -163,7 +165,7 @@ public class FLabel extends FDisplayObject { handled = true; } if (command != null) { - command.run(); + command.handleEvent(new FEvent(this, FEventType.TAP)); handled = true; } return handled; diff --git a/forge-m-base/src/forge/toolbox/FList.java b/forge-m-base/src/forge/toolbox/FList.java index 83b06b67cbe..29abbed2554 100644 --- a/forge-m-base/src/forge/toolbox/FList.java +++ b/forge-m-base/src/forge/toolbox/FList.java @@ -11,6 +11,7 @@ import forge.assets.FSkinFont; import forge.assets.FSkinTexture; import forge.assets.FSkinColor.Colors; import forge.screens.FScreen; +import forge.toolbox.FEvent.FEventHandler; import forge.utils.Utils; public class FList extends FScrollPane { @@ -143,9 +144,9 @@ public class FList extends FScrollPane { header = null; } else { - header = add(new FLabel.ButtonBuilder().text(name0).command(new Runnable() { + header = add(new FLabel.ButtonBuilder().text(name0).command(new FEventHandler() { @Override - public void run() { + public void handleEvent(FEvent e) { isCollapsed = !isCollapsed; FList.this.revalidate(); } diff --git a/forge-m-base/src/forge/toolbox/FRadioButton.java b/forge-m-base/src/forge/toolbox/FRadioButton.java index f4a284274a5..f135e7a7051 100644 --- a/forge-m-base/src/forge/toolbox/FRadioButton.java +++ b/forge-m-base/src/forge/toolbox/FRadioButton.java @@ -1,24 +1,60 @@ package forge.toolbox; +import java.util.ArrayList; +import java.util.List; + import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment; + import forge.Forge.Graphics; import forge.assets.FImage; import forge.assets.FSkinColor; import forge.assets.FSkinColor.Colors; public class FRadioButton extends FLabel { - private static final FSkinColor CHECK_COLOR = FSkinColor.get(Colors.CLR_TEXT); - private static final FSkinColor BOX_COLOR = CHECK_COLOR.alphaColor(0.5f); + private static final FSkinColor INNER_CIRCLE_COLOR = FSkinColor.get(Colors.CLR_TEXT); + private static final FSkinColor OUTER_CIRCLE_COLOR = INNER_CIRCLE_COLOR.alphaColor(0.5f); + + private RadioButtonGroup group; public FRadioButton() { - this(""); + this("", false); } public FRadioButton(String text0) { - super(new Builder().align(HAlignment.LEFT).selectable()); - this.setIcon(new CheckBoxIcon()); + this(text0, false); + } + public FRadioButton(String text0, boolean selected0) { + super(new Builder().align(HAlignment.LEFT).selectable().selected(selected0)); + setIcon(new RadioButtonIcon()); + } + + public RadioButtonGroup getGroup() { + return group; + } + public void setGroup(RadioButtonGroup group0) { + if (group != null) { + group.buttons.remove(this); + } + group = group0; + if (group != null) { + group.buttons.add(this); + } } - private class CheckBoxIcon implements FImage { + @Override + public void setSelected(final boolean b0) { + if (isSelected() == b0) { return; } + + if (b0 && group != null) { //if selecting and in group, unselect all other radio buttons in group + for (FRadioButton button : group.buttons) { + if (button != this) { + button.setSelected(false); + } + } + } + super.setSelected(b0); + } + + private class RadioButtonIcon implements FImage { @Override public float getWidth() { return FRadioButton.this.getHeight(); @@ -31,16 +67,17 @@ public class FRadioButton extends FLabel { @Override public void draw(Graphics g, float x, float y, float w, float h) { - g.drawRect(1, BOX_COLOR, x, y, w, h); + float radius = h / 5; + x += w - radius; + y = h / 2; + g.drawCircle(1, OUTER_CIRCLE_COLOR, x, y, radius); if (isSelected()) { - //draw check mark - x += 3; - y++; - w -= 6; - h -= 3; - g.drawLine(2, CHECK_COLOR, x, y + h / 2, x + w / 2, y + h); - g.drawLine(2, CHECK_COLOR, x + w / 2, y + h, x + w, y); + g.fillCircle(INNER_CIRCLE_COLOR, x, y, radius / 2); } } } + + public static class RadioButtonGroup { + private final List buttons = new ArrayList(); + } } diff --git a/forge-m-base/src/forge/toolbox/FScrollPane.java b/forge-m-base/src/forge/toolbox/FScrollPane.java index 412e74ac75f..31682bcfeac 100644 --- a/forge-m-base/src/forge/toolbox/FScrollPane.java +++ b/forge-m-base/src/forge/toolbox/FScrollPane.java @@ -16,7 +16,7 @@ public abstract class FScrollPane extends FContainer { private float scrollLeft, scrollTop; private ScrollBounds scrollBounds; - protected FScrollPane() { + public FScrollPane() { scrollBounds = new ScrollBounds(); } diff --git a/forge-m-base/src/forge/toolbox/FTextField.java b/forge-m-base/src/forge/toolbox/FTextField.java index e822423db09..bf900194607 100644 --- a/forge-m-base/src/forge/toolbox/FTextField.java +++ b/forge-m-base/src/forge/toolbox/FTextField.java @@ -1,14 +1,17 @@ package forge.toolbox; import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment; + import forge.Forge.Graphics; import forge.assets.FSkinColor; import forge.assets.FSkinFont; import forge.assets.FSkinColor.Colors; +import forge.toolbox.FEvent.FEventHandler; public class FTextField extends FDisplayObject { private static final float PADDING = 3; private static final FSkinColor FORE_COLOR = FSkinColor.get(Colors.CLR_TEXT); + private FEventHandler changedHandler; private String text; private FSkinFont font; @@ -41,6 +44,19 @@ public class FTextField extends FDisplayObject { font = FSkinFont.get(fontSize0); } + public FEventHandler getChangedHandler() { + return changedHandler; + } + public void setChangedHandler(FEventHandler changedHandler0) { + changedHandler = changedHandler0; + } + + @Override + public boolean tap(float x, float y, int count) { + //TODO: Support entering text when tapped + return true; + } + @Override public void draw(Graphics g) { g.drawText(text, font, FORE_COLOR, PADDING, 0, getWidth() - 2 * PADDING, getHeight(), false, alignment, true);