Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions forge-gui-mobile/src/forge/deck/FDeckChooser.java
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,7 @@ public void initialize(FPref savedStateSetting, DeckType defaultDeckType) {
cmbDeckTypes.addItem(DeckType.PIONEER_CARDGEN_DECK);
cmbDeckTypes.addItem(DeckType.HISTORIC_CARDGEN_DECK);
}
cmbDeckTypes.addItem(DeckType.NET_EVENT_DECK);
cmbDeckTypes.addItem(DeckType.NET_DECK);
cmbDeckTypes.addItem(DeckType.NET_ARCHIVE_STANDARD_DECK);
cmbDeckTypes.addItem(DeckType.NET_ARCHIVE_PIONEER_DECK);
Expand Down Expand Up @@ -601,6 +602,7 @@ public void initialize(FPref savedStateSetting, DeckType defaultDeckType) {
cmbDeckTypes.addItem(DeckType.PRECONSTRUCTED_DECK);
cmbDeckTypes.addItem(DeckType.PRECON_COMMANDER_DECK);
cmbDeckTypes.addItem(DeckType.QUEST_OPPONENT_DECK);
cmbDeckTypes.addItem(DeckType.NET_EVENT_DECK);
cmbDeckTypes.addItem(DeckType.NET_DECK);
cmbDeckTypes.addItem(DeckType.NET_COMMANDER_DECK);
cmbDeckTypes.addItem(DeckType.NET_ARCHIVE_STANDARD_DECK);
Expand Down Expand Up @@ -1058,6 +1060,10 @@ private void refreshDecksList(DeckType deckType, boolean forceRefresh, FEvent ev
pool = DeckProxy.getNetArchiveBlockDecks(NetDeckArchiveBlock);
config = ItemManagerConfig.NET_ARCHIVE_BLOCK_DECKS;
break;
case NET_EVENT_DECK:
pool = DeckProxy.getAllNetworkEventDecks();
config = ItemManagerConfig.NET_EVENT_DECKS;
break;
case NET_DECK:
case NET_COMMANDER_DECK:
if (netDeckCategory != null) {
Expand Down Expand Up @@ -1356,12 +1362,7 @@ private DeckType getDeckTypeFromSavedState(String savedState) {
NetDeckArchiveBlock = NetDeckArchiveBlock.selectAndLoad(lstDecks.getGameType(), deckType.substring(NetDeckArchiveBlock.PREFIX.length()));
return DeckType.NET_ARCHIVE_BLOCK_DECK;
}
DeckType resolved = DeckType.valueOf(deckType);
// TODO: remove when network draft/sealed support is added to mobile.
if (resolved == DeckType.NET_EVENT_DECK) {
return selectedDeckType;
}
return resolved;
return DeckType.valueOf(deckType);
}
}
catch (IllegalArgumentException ex) {
Expand Down
66 changes: 61 additions & 5 deletions forge-gui-mobile/src/forge/deck/FDeckEditor.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package forge.deck;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Align;
Expand Down Expand Up @@ -34,6 +35,7 @@
import forge.model.FModel;
import forge.screens.FScreen;
import forge.screens.TabPageScreen;
import forge.screens.match.views.VChat;
import forge.screens.match.views.VLog;
import forge.toolbox.*;
import forge.toolbox.FEvent.FEventHandler;
Expand Down Expand Up @@ -331,6 +333,10 @@ public List<CardEdition> getBasicLandSets(Deck currentDeck) {
public static DeckEditorConfig EditorConfigSealed = new GameTypeDeckEditorConfig(GameType.Sealed,
new FileDeckGroupController(FModel.getDecks().getSealed(), DeckGroup::new, DeckPreferences::setSealedDeck))
.setSideboardConfig(ItemManagerConfig.SEALED_POOL);
/** Editor for network-event sealed/draft pools stored in {@code getNetworkEventDecks()}. */
public static DeckEditorConfig EditorConfigNetworkEventPool = new GameTypeDeckEditorConfig(GameType.Sealed,
new FileDeckController<>(FModel.getDecks().getNetworkEventDecks(), Deck::new, null))
.setSideboardConfig(ItemManagerConfig.SEALED_POOL);
public static DeckEditorConfig EditorConfigWinston = new GameTypeDeckEditorConfig(GameType.Winston,
new FileDeckGroupController(FModel.getDecks().getWinston(), DeckGroup::new, null));
public static DeckEditorConfig EditorConfigCommander = new GameTypeDeckEditorConfig(GameType.Commander,
Expand Down Expand Up @@ -747,7 +753,7 @@ public void notifyNewControllerModel() {
public Deck getDeck() {
return deck;
}
private void setDeck(Deck deck) {
public void setDeck(Deck deck) {
if (this.deck == deck) { return; }
this.deck = deck;
setHeaderText(getDeckController().getDeckDisplayName());
Expand Down Expand Up @@ -1123,6 +1129,7 @@ protected static class DeckHeader extends FContainer {
protected final FLabel btnSave;
protected final FLabel btnMoreOptions;
protected FDisplayObject btnDraftLog;
protected ChatHeaderButton btnChat;

protected DeckHeader() {
setHeight(HEADER_HEIGHT);
Expand Down Expand Up @@ -1171,13 +1178,21 @@ protected List<FDisplayObject> layoutHeaderElements(float height, float availabl
float width = Math.max(remainingWidth / 4, Math.min(height * 4, remainingWidth / 2));
btnDraftLog.setSize(width, height);
out.add(btnDraftLog);
remainingWidth -= width;
}
if(btnChat != null) {
float width = Math.max(remainingWidth / 4, Math.min(height * 4, remainingWidth / 2));
btnChat.setSize(width, height);
out.add(btnChat);
}
return out;
}

public void initDraftLog(GameLog draftLog, FContainer parentScreen) {
VLog draftLogContainer = new VLog(() -> draftLog);
VLog draftLogContainer = new VLog(() -> draftLog, true);
draftLogContainer.setDropDownContainer(parentScreen);
// Live-refresh the open dropdown so a remote player's pick shows without local interaction
draftLog.addObserver((o, arg) -> FThreads.invokeInEdtNowOrLater(draftLogContainer::refresh));
this.btnDraftLog = new FLabel.ButtonBuilder()
.text(Localizer.getInstance().getMessage("lblEditorLog"))
.pressedColor(Header.getBtnPressedColor())
Expand All @@ -1187,6 +1202,47 @@ public void initDraftLog(GameLog draftLog, FContainer parentScreen) {
draftLogContainer.setDropdownOwner(btnDraftLog);
this.add(btnDraftLog);
}

public VChat initChat(FContainer parentScreen) {
VChat chat = new VChat();
chat.setDropDownContainer(parentScreen);
this.btnChat = new ChatHeaderButton(new FLabel.ButtonBuilder()
.text(Localizer.getInstance().getMessage("lblChat"))
.pressedColor(Header.getBtnPressedColor())
.command((e) -> chat.show())
.font(FSkinFont.get(20)));
chat.setDropdownOwner(btnChat);
this.add(btnChat);
return chat;
}
}

/** Header chat button that renders the unread-message badge shared with the in-match chat tab. */
protected static class ChatHeaderButton extends FLabel implements IUnreadIndicator {
private int unreadCount;

protected ChatHeaderButton(Builder builder) {
super(builder);
}

@Override
public void incrementUnread() {
unreadCount++;
Gdx.graphics.requestRendering();
}

@Override
public void clearUnread() {
if (unreadCount == 0) { return; }
unreadCount = 0;
Gdx.graphics.requestRendering();
}

@Override
public void draw(Graphics g) {
super.draw(g);
FMenuTab.drawUnreadBadge(g, unreadCount, getWidth());
}
}

protected static abstract class DeckEditorPage extends TabPage<FDeckEditor> {
Expand Down Expand Up @@ -1911,14 +1967,14 @@ protected boolean cardIsFavorite(PaperCard card) {
}
}

protected static class DeckSectionPage extends CardManagerPage {
public static class DeckSectionPage extends CardManagerPage {
private final String captionPrefix;
protected final DeckSection deckSection;
public final DeckSection deckSection;

protected DeckSectionPage(CardManager cardManager, DeckSection deckSection) {
this(cardManager, deckSection, ItemManagerConfig.DECK_EDITOR);
}
protected DeckSectionPage(CardManager cardManager, DeckSection deckSection, ItemManagerConfig config) {
public DeckSectionPage(CardManager cardManager, DeckSection deckSection, ItemManagerConfig config) {
this(cardManager, deckSection, config, deckSection.getLocalizedShortName(), iconFromDeckSection(deckSection));
}
protected DeckSectionPage(CardManager cardManager, DeckSection deckSection, ItemManagerConfig config, String caption, FImage icon) {
Expand Down
25 changes: 14 additions & 11 deletions forge-gui-mobile/src/forge/menu/FMenuTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import forge.toolbox.FDisplayObject;
import forge.util.Utils;

public class FMenuTab extends FDisplayObject {
public class FMenuTab extends FDisplayObject implements IUnreadIndicator {
public static final FSkinFont FONT = FSkinFont.get(12);
boolean iconOnly = false;
boolean active = false;
Expand Down Expand Up @@ -195,16 +195,19 @@ public void draw(Graphics g) {
} else
g.drawText(text, FONT, foreColor, x, y, w, h, false, Align.center, true);

//unread badge in the top-right corner
if (unreadCount > 0) {
String label = unreadCount > 99 ? "99+" : Integer.toString(unreadCount);
float textW = BADGE_FONT.getBounds(label).width;
float diameter = Math.max(BADGE_FONT.getLineHeight(), textW + 2 * Utils.scale(4));
float bx = getWidth() - diameter - PADDING;
float by = PADDING;
g.fillRect(BADGE_COLOR, bx, by, diameter, diameter);
g.drawText(label, BADGE_FONT, BADGE_TEXT_COLOR, bx, by, diameter, diameter, false, Align.center, true);
}
drawUnreadBadge(g, unreadCount, getWidth());
}

/** Draws the unread-message count badge in the top-right corner of a widget of the given width. */
public static void drawUnreadBadge(Graphics g, int unreadCount, float widgetWidth) {
if (unreadCount <= 0) { return; }
String label = unreadCount > 99 ? "99+" : Integer.toString(unreadCount);
float textW = BADGE_FONT.getBounds(label).width;
float diameter = Math.max(BADGE_FONT.getLineHeight(), textW + 2 * Utils.scale(4));
float bx = widgetWidth - diameter - PADDING;
float by = PADDING;
g.fillRect(BADGE_COLOR, bx, by, diameter, diameter);
g.drawText(label, BADGE_FONT, BADGE_TEXT_COLOR, bx, by, diameter, diameter, false, Align.center, true);
}
public boolean isShowingDropdownMenu(boolean any) {
if (dropDown == null)
Expand Down
7 changes: 7 additions & 0 deletions forge-gui-mobile/src/forge/menu/IUnreadIndicator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package forge.menu;

/** A tab or button that tracks and displays a count of unread chat messages. */
public interface IUnreadIndicator {
void incrementUnread();
void clearUnread();
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@

public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
private static final ForgePreferences prefs = FModel.getPreferences();
private static final float PADDING = Utils.scale(5);
protected static final float PADDING = Utils.scale(5);
public static final int MAX_PLAYERS = 4;
private static final FSkinFont VARIANTS_FONT = FSkinFont.get(12);

Expand Down Expand Up @@ -913,6 +913,11 @@ protected void setLobbyControlsVisible(boolean visible) {
playersScroll.setVisible(visible);
}

protected void setVariantsVisible(boolean visible) {
lblVariants.setVisible(visible);
cbVariants.setVisible(visible);
}

public void setStartButtonAvailability() {
if (lobby.isAllowNetworking() && FServerManager.getInstance() != null)
btnStart.setVisible(FServerManager.getInstance().isHosting());
Expand Down
18 changes: 17 additions & 1 deletion forge-gui-mobile/src/forge/screens/limited/LoadDraftScreen.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import forge.game.GameType;
import forge.game.player.RegisteredPlayer;
import forge.gamemodes.match.HostedMatch;
import forge.gamemodes.net.EventFormat;
import forge.gui.FThreads;
import forge.gui.GuiBase;
import forge.gui.util.SGuiChoose;
Expand Down Expand Up @@ -69,7 +70,13 @@ public LoadDraftScreen() {

@Override
public void onActivate() {
lstDecks.setPool(DeckProxy.getAllDraftDecks());
List<DeckProxy> combined = new ArrayList<>(DeckProxy.getAllDraftDecks());
for (DeckProxy p : DeckProxy.getAllNetworkEventDecks()) {
if (EventFormat.BOOSTER_DRAFT.name().equals(DeckProxy.getEventTag(p.getDeck(), "eventFormat"))) {
combined.add(p);
}
}
lstDecks.setPool(combined);
lstDecks.setSelectedString(DeckPreferences.getDraftDeck());
cbGamesInMatchBinder.load();
}
Expand Down Expand Up @@ -120,6 +127,15 @@ protected void startMatch() {
return;
}

// Event decks lack a DeckGroup for gauntlet/AI play
if (FModel.getDecks().getDraft().get(humanDeck.getName()) == null) {
FThreads.invokeInEdtLater(() ->
FOptionPane.showErrorDialog(
Forge.getLocalizer().getMessage("lblEventDeckEditOnly"),
Forge.getLocalizer().getMessage("lblNoOpponentsForEventDeck")));
return;
}

// TODO: if booster draft tournaments are supported in the future, add the possibility to choose them here
final boolean gauntlet = cbMode.getSelectedItem().equals(Forge.getLocalizer().getMessage("lblGauntlet"));

Expand Down
18 changes: 17 additions & 1 deletion forge-gui-mobile/src/forge/screens/limited/LoadSealedScreen.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import forge.game.GameType;
import forge.game.player.RegisteredPlayer;
import forge.gamemodes.match.HostedMatch;
import forge.gamemodes.net.EventFormat;
import forge.gui.FThreads;
import forge.gui.GuiBase;
import forge.gui.util.SGuiChoose;
Expand Down Expand Up @@ -69,7 +70,13 @@ public LoadSealedScreen() {

@Override
public void onActivate() {
lstDecks.setPool(DeckProxy.getAllSealedDecks());
List<DeckProxy> combined = new ArrayList<>(DeckProxy.getAllSealedDecks());
for (DeckProxy p : DeckProxy.getAllNetworkEventDecks()) {
if (EventFormat.SEALED.name().equals(DeckProxy.getEventTag(p.getDeck(), "eventFormat"))) {
combined.add(p);
}
}
lstDecks.setPool(combined);
lstDecks.setSelectedString(DeckPreferences.getSealedDeck());
cbGamesInMatchBinder.load();
}
Expand Down Expand Up @@ -118,6 +125,15 @@ protected void startMatch() {
return;
}

// Event decks lack a DeckGroup for gauntlet/AI play
if (FModel.getDecks().getSealed().get(humanDeck.getName()) == null) {
FThreads.invokeInEdtLater(() ->
FOptionPane.showErrorDialog(
Forge.getLocalizer().getMessage("lblEventDeckEditOnly"),
Forge.getLocalizer().getMessage("lblNoOpponentsForEventDeck")));
return;
}

final boolean gauntlet = cbMode.getSelectedItem().equals(Forge.getLocalizer().getMessage("lblGauntlet"));

if (gauntlet) {
Expand Down
Loading
Loading