Skip to content
Draft
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 @@ -762,7 +768,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 @@ -1138,6 +1144,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 @@ -1186,13 +1193,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 @@ -1202,6 +1217,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 @@ -1926,14 +1982,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 @@ -911,6 +911,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