diff --git a/.gitattributes b/.gitattributes index 41a8bf1e177..3e0f8b139e9 100644 --- a/.gitattributes +++ b/.gitattributes @@ -14364,6 +14364,7 @@ src/main/java/forge/gui/framework/IDocIdList.java -text src/main/java/forge/gui/framework/ILocalRepaint.java -text src/main/java/forge/gui/framework/IVDoc.java -text src/main/java/forge/gui/framework/IVTopLevelUI.java -text +src/main/java/forge/gui/framework/RectangleOfDouble.java -text src/main/java/forge/gui/framework/SDisplayUtil.java -text src/main/java/forge/gui/framework/SLayoutConstants.java -text src/main/java/forge/gui/framework/SLayoutIO.java -text diff --git a/src/main/java/forge/game/MatchController.java b/src/main/java/forge/game/MatchController.java index b7d3be0aa6d..ac1c74bdb4a 100644 --- a/src/main/java/forge/game/MatchController.java +++ b/src/main/java/forge/game/MatchController.java @@ -178,11 +178,11 @@ public class MatchController { public static void attachUiToMatch(MatchController match, LobbyPlayer humanLobbyPlayer) { FControl.SINGLETON_INSTANCE.setMatch(match); - GameState currentGame = match.getCurrentGame(); - currentGame.getEvents().register(Singletons.getControl().getSoundSystem()); + GameState game = match.getCurrentGame(); + game.getEvents().register(Singletons.getControl().getSoundSystem()); Player localHuman = null; - for(Player p : currentGame.getPlayers()) { + for(Player p : game.getPlayers()) { if ( p.getLobbyPlayer() != humanLobbyPlayer) continue; localHuman = p; @@ -192,11 +192,11 @@ public class MatchController { FControl.SINGLETON_INSTANCE.setPlayer(localHuman); // The UI controls should use these game data as models - CMatchUI.SINGLETON_INSTANCE.initMatch(currentGame.getRegisteredPlayers(), localHuman); - CDock.SINGLETON_INSTANCE.setModel(currentGame, localHuman); - CStack.SINGLETON_INSTANCE.setModel(currentGame.getStack(), localHuman); - CLog.SINGLETON_INSTANCE.setModel(currentGame.getGameLog()); - CCombat.SINGLETON_INSTANCE.setModel(currentGame); + CMatchUI.SINGLETON_INSTANCE.initMatch(game.getRegisteredPlayers(), humanLobbyPlayer); + CDock.SINGLETON_INSTANCE.setModel(game, localHuman); + CStack.SINGLETON_INSTANCE.setModel(game.getStack(), localHuman); + CLog.SINGLETON_INSTANCE.setModel(game.getGameLog()); + CCombat.SINGLETON_INSTANCE.setModel(game); CMessage.SINGLETON_INSTANCE.setModel(match); @@ -204,18 +204,18 @@ public class MatchController { Singletons.getControl().changeState(FControl.Screens.MATCH_SCREEN); SDisplayUtil.showTab(EDocID.REPORT_LOG.getDoc()); - CMessage.SINGLETON_INSTANCE.getInputControl().setGame(currentGame); + CMessage.SINGLETON_INSTANCE.getInputControl().setGame(game); // models shall notify controllers of changes - currentGame.getStack().addObserver(CStack.SINGLETON_INSTANCE); - currentGame.getGameLog().addObserver(CLog.SINGLETON_INSTANCE); + game.getStack().addObserver(CStack.SINGLETON_INSTANCE); + game.getGameLog().addObserver(CLog.SINGLETON_INSTANCE); // some observers were set in CMatchUI.initMatch // black magic still - VAntes.SINGLETON_INSTANCE.setModel(currentGame.getRegisteredPlayers()); + VAntes.SINGLETON_INSTANCE.setModel(game.getRegisteredPlayers()); for (final VField field : VMatchUI.SINGLETON_INSTANCE.getFieldViews()) { field.getLblLibrary().setHoverable(Preferences.DEV_MODE); diff --git a/src/main/java/forge/gui/framework/DragCell.java b/src/main/java/forge/gui/framework/DragCell.java index 6697de1d12e..e446bc36c28 100644 --- a/src/main/java/forge/gui/framework/DragCell.java +++ b/src/main/java/forge/gui/framework/DragCell.java @@ -31,10 +31,7 @@ import forge.view.FView; @SuppressWarnings("serial") public final class DragCell extends JPanel implements ILocalRepaint { // Layout creation worker vars - private double roughX = 0; - private double roughY = 0; - private double roughW = 0; - private double roughH = 0; + private RectangleOfDouble roughSize; private int smoothX = 0; private int smoothY = 0; private int smoothW = 0; @@ -196,12 +193,13 @@ public final class DragCell extends JPanel implements ILocalRepaint { /** * Automatically calculates rough bounds of this cell. + * @param rectangleOfDouble */ - public void setRoughBounds() { + public void updateRoughBounds() { final double contentW = FView.SINGLETON_INSTANCE.getPnlContent().getWidth(); final double contentH = FView.SINGLETON_INSTANCE.getPnlContent().getHeight(); - setRoughBounds(this.getX() / contentW, this.getY() / contentH, + this.roughSize = new RectangleOfDouble(this.getX() / contentW, this.getY() / contentH, this.getW() / contentW, this.getH() / contentH); } @@ -212,36 +210,16 @@ public final class DragCell extends JPanel implements ILocalRepaint { * @param w0   double * @param h0   double */ - public void setRoughBounds(final double x0, final double y0, final double w0, final double h0) { - if (x0 > 1) { throw new IllegalArgumentException("X value greater than 100%!"); } - if (y0 > 1) { throw new IllegalArgumentException("Y value greater than 100%!"); } - if (w0 > 1) { throw new IllegalArgumentException("W value greater than 100%!"); } - if (h0 > 1) { throw new IllegalArgumentException("H value greater than 100%!"); } - - this.roughX = x0; - this.roughY = y0; - this.roughW = w0; - this.roughH = h0; + public void setRoughBounds(RectangleOfDouble rectangleOfDouble) { + this.roughSize = rectangleOfDouble; } - /** @return double */ - public double getRoughX() { - return this.roughX; - } - - /** @return double */ - public double getRoughY() { - return this.roughY; - } - - /** @return double */ - public double getRoughW() { - return this.roughW; - } - - /** @return double */ - public double getRoughH() { - return this.roughH; + /** + * TODO: Write javadoc for this method. + * @return + */ + public RectangleOfDouble getRoughBounds() { + return roughSize; } /** Sets bounds in superclass using smoothed values from this class. */ diff --git a/src/main/java/forge/gui/framework/EDocID.java b/src/main/java/forge/gui/framework/EDocID.java index a74d12fa918..ee51b7e86d5 100644 --- a/src/main/java/forge/gui/framework/EDocID.java +++ b/src/main/java/forge/gui/framework/EDocID.java @@ -101,6 +101,10 @@ public enum EDocID { /** */ HAND_1 (null), /** */ HAND_2 (null), /** */ HAND_3 (null), /** */ + HAND_4 (null), /** */ + HAND_5 (null), /** */ + HAND_6 (null), /** */ + HAND_7 (null), /** */ COMMAND_0 (null), /** */ COMMAND_1 (null), /** */ @@ -111,6 +115,10 @@ public enum EDocID { /** */ COMMAND_6 (null), /** */ COMMAND_7 (null); /** */ + public final static EDocID[] Commands = new EDocID[] {COMMAND_0, COMMAND_1, COMMAND_2, COMMAND_3, COMMAND_4, COMMAND_5, COMMAND_6, COMMAND_7}; + public final static EDocID[] Fields = new EDocID[] {FIELD_0, FIELD_1, FIELD_2, FIELD_3, FIELD_4, FIELD_5, FIELD_6, FIELD_7}; + public final static EDocID[] Hands = new EDocID[] {HAND_0, HAND_1, HAND_2, HAND_3, HAND_4, HAND_5, HAND_6, HAND_7}; + // End enum declarations, start enum methods. private IVDoc vDoc; diff --git a/src/main/java/forge/gui/framework/RectangleOfDouble.java b/src/main/java/forge/gui/framework/RectangleOfDouble.java new file mode 100644 index 00000000000..469c5242659 --- /dev/null +++ b/src/main/java/forge/gui/framework/RectangleOfDouble.java @@ -0,0 +1,90 @@ +package forge.gui.framework; + +/** + * Dimensions for a cell, stored as % of available space + * + */ +public class RectangleOfDouble { + private final double x; + private final double y; + private final double w; + private final double h; + + + public RectangleOfDouble(final double x0, final double y0, final double w0, final double h0) { + if (x0 > 1) { throw new IllegalArgumentException("X value greater than 100%!"); } + x = x0; + if (y0 > 1) { throw new IllegalArgumentException("Y value greater than 100%!"); } + y = y0; + if (w0 > 1) { throw new IllegalArgumentException("W value greater than 100%!"); } + w = w0; + if (h0 > 1) { throw new IllegalArgumentException("H value greater than 100%!"); } + h = h0; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(h); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(w); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(x); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(y); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RectangleOfDouble other = (RectangleOfDouble) obj; + if (Double.doubleToLongBits(h) != Double.doubleToLongBits(other.h)) + return false; + if (Double.doubleToLongBits(w) != Double.doubleToLongBits(other.w)) + return false; + if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x)) + return false; + if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y)) + return false; + return true; + } + + public final double getX() { + return x; + } + + + public final double getY() { + return y; + } + + + public final double getW() { + return w; + } + + + public final double getH() { + return h; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return String.format("Rectangle @(%f, %f) sz=(%f, %f)", x,y, w,h); + } + + + +} diff --git a/src/main/java/forge/gui/framework/SLayoutIO.java b/src/main/java/forge/gui/framework/SLayoutIO.java index ec42327b962..a247e37b993 100644 --- a/src/main/java/forge/gui/framework/SLayoutIO.java +++ b/src/main/java/forge/gui/framework/SLayoutIO.java @@ -4,10 +4,11 @@ import java.awt.BorderLayout; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.Map.Entry; -import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.border.EmptyBorder; import javax.xml.stream.XMLEventFactory; @@ -21,8 +22,12 @@ import javax.xml.stream.events.StartElement; import javax.xml.stream.events.XMLEvent; import forge.control.FControl; +import forge.control.FControl.Screens; import forge.properties.FileLocation; import forge.properties.NewConstants; +import forge.util.maps.CollectionSuppliers; +import forge.util.maps.HashMapOfLists; +import forge.util.maps.MapOfLists; import forge.view.FView; @@ -33,15 +38,14 @@ import forge.view.FView; */ public final class SLayoutIO { /** Each cell must save these elements of its display. */ - private enum Property { - x, - y, - w, - h, - doc + private static class Property { + public final static String x = "x"; + public final static String y = "y"; + public final static String w = "w"; + public final static String h = "h"; + public final static String doc = "doc"; } - private static FileLocation file = null; private static final XMLEventFactory EF = XMLEventFactory.newInstance(); private static final XMLEvent NEWLINE = EF.createDTD("\n"); private static final XMLEvent TAB = EF.createDTD("\t"); @@ -51,7 +55,7 @@ public final class SLayoutIO { * @return {@link java.lang.String} */ public static String getFilePreferred() { - return null == file ? null : file.userPrefLoc; + return SLayoutIO.getFileForState(FControl.SINGLETON_INSTANCE.getState()).userPrefLoc; } /** Publicly-accessible save method, to neatly handle exception handling. @@ -69,18 +73,9 @@ public final class SLayoutIO { } - /** - * Publicly-accessible load method, to neatly handle exception handling. - * @param f0   {@link java.io.File} - */ - public static void loadLayout(final File f0) { - try { load(f0); } - catch (final Exception e) { e.printStackTrace(); } - } - private synchronized static void save(final File f0) throws Exception { final String fWriteTo; - SLayoutIO.setFilesForState(); + FileLocation file = SLayoutIO.getFileForState(FControl.SINGLETON_INSTANCE.getState()); if (f0 == null) { if (null == file) { @@ -95,8 +90,6 @@ public final class SLayoutIO { final XMLOutputFactory out = XMLOutputFactory.newInstance(); final XMLEventWriter writer = out.createXMLEventWriter(new FileOutputStream(fWriteTo)); final List cells = FView.SINGLETON_INSTANCE.getDragCells(); - final JPanel pnl = FView.SINGLETON_INSTANCE.getPnlContent(); - double x0, y0, w0, h0; writer.add(EF.createStartDocument()); writer.add(NEWLINE); @@ -104,19 +97,15 @@ public final class SLayoutIO { writer.add(NEWLINE); for (final DragCell cell : cells) { - x0 = ((double) Math.round(((double) cell.getX() / (double) pnl.getWidth()) * 100000)) / 100000; - y0 = ((double) Math.round(((double) cell.getY() / (double) pnl.getHeight()) * 100000)) / 100000; - w0 = ((double) Math.round(((double) cell.getW() / (double) pnl.getWidth()) * 100000)) / 100000; - h0 = ((double) Math.round(((double) cell.getH() / (double) pnl.getHeight()) * 100000)) / 100000; - - //cell.setRoughBounds(x, y, w, h); - + cell.updateRoughBounds(); + RectangleOfDouble bounds = cell.getRoughBounds(); + writer.add(TAB); writer.add(EF.createStartElement("", "", "cell")); - writer.add(EF.createAttribute(Property.x.toString(), String.valueOf(x0))); - writer.add(EF.createAttribute(Property.y.toString(), String.valueOf(y0))); - writer.add(EF.createAttribute(Property.w.toString(), String.valueOf(w0))); - writer.add(EF.createAttribute(Property.h.toString(), String.valueOf(h0))); + writer.add(EF.createAttribute(Property.x.toString(), String.valueOf(Math.rint(bounds.getX() * 100000) / 100000))); + writer.add(EF.createAttribute(Property.y.toString(), String.valueOf(Math.rint(bounds.getY() * 100000) / 100000))); + writer.add(EF.createAttribute(Property.w.toString(), String.valueOf(Math.rint(bounds.getW() * 100000) / 100000))); + writer.add(EF.createAttribute(Property.h.toString(), String.valueOf(Math.rint(bounds.getH() * 100000) / 100000))); writer.add(NEWLINE); for (final IVDoc vDoc : cell.getDocs()) { @@ -133,36 +122,65 @@ public final class SLayoutIO { writer.close(); } - private static void load(final File f) throws Exception { + public static void loadLayout(final File f) { final FView view = FView.SINGLETON_INSTANCE; final XMLInputFactory inputFactory = XMLInputFactory.newInstance(); - SLayoutIO.setFilesForState(); + FileLocation file = SLayoutIO.getFileForState(FControl.SINGLETON_INSTANCE.getState()); view.getPnlInsets().removeAll(); view.getPnlInsets().setLayout(new BorderLayout()); view.getPnlInsets().add(view.getPnlContent(), BorderLayout.CENTER); - view.getPnlInsets().setBorder(new EmptyBorder( - SLayoutConstants.BORDER_T, SLayoutConstants.BORDER_T, 0, 0)); - - final XMLEventReader reader; - if (f != null && f.exists()) { - reader = inputFactory.createXMLEventReader(new FileInputStream(f)); - } else if (null == file) { - reader = null; - } else if (new File(file.userPrefLoc).exists()) { - reader = inputFactory.createXMLEventReader(new FileInputStream(file.userPrefLoc)); - } else { - reader = inputFactory.createXMLEventReader(new FileInputStream(file.defaultLoc)); - } + view.getPnlInsets().setBorder(new EmptyBorder(SLayoutConstants.BORDER_T, SLayoutConstants.BORDER_T, 0, 0)); view.removeAllDragCells(); + + // Read a model for new layout + MapOfLists model = null; + try { + FileInputStream fis = null; + if (f != null && f.exists()) + fis = new FileInputStream(f); + else { + File userSetting = new File(file.userPrefLoc); + fis = userSetting.exists() ? new FileInputStream(userSetting) : new FileInputStream(file.defaultLoc); + } + + model = readLayout(inputFactory.createXMLEventReader(fis)); + } catch (final Exception e) { e.printStackTrace(); } + + // Apply new layout + DragCell cell = null; + for(Entry> kv : model.entrySet()) { + cell = new DragCell(); + cell.setRoughBounds(kv.getKey()); + FView.SINGLETON_INSTANCE.addDragCell(cell); + for(EDocID edoc : kv.getValue()) { + try { +// System.out.println(String.format("adding doc %s -> %s", edoc, edoc.getDoc())); + cell.addDoc(edoc.getDoc()); + } catch (IllegalArgumentException e) { + System.err.println("Failed to get doc for " + edoc); + } + + } + + } + + // Rough bounds are all in place; resize the window. + SResizingUtil.resizeWindow(); + } + + private static MapOfLists readLayout(final XMLEventReader reader) + throws XMLStreamException { XMLEvent event; StartElement element; Iterator attributes; Attribute attribute; - DragCell cell = null; double x0 = 0, y0 = 0, w0 = 0, h0 = 0; - + + MapOfLists model = new HashMapOfLists(CollectionSuppliers.arrayLists()); + + RectangleOfDouble currentKey = null; while (null != reader && reader.hasNext()) { event = reader.nextEvent(); @@ -173,72 +191,59 @@ public final class SLayoutIO { attributes = element.getAttributes(); while (attributes.hasNext()) { attribute = (Attribute) attributes.next(); - if (attribute.getName().toString().equals(Property.x.toString())) { - x0 = Double.valueOf(attribute.getValue()); - } - else if (attribute.getName().toString().equals(Property.y.toString())) { - y0 = Double.valueOf(attribute.getValue()); - } - else if (attribute.getName().toString().equals(Property.w.toString())) { - w0 = Double.valueOf(attribute.getValue()); - } - else if (attribute.getName().toString().equals(Property.h.toString())) { - h0 = Double.valueOf(attribute.getValue()); - } - } + double val = Double.parseDouble(attribute.getValue()); + String atrName = attribute.getName().toString(); - cell = new DragCell(); - cell.setRoughBounds(x0, y0, w0, h0); - FView.SINGLETON_INSTANCE.addDragCell(cell); + if (atrName.equals(Property.x)) x0 = val; + else if (atrName.equals(Property.y)) y0 = val; + else if (atrName.equals(Property.w)) w0 = val; + else if (atrName.equals(Property.h)) h0 = val; + } + currentKey = new RectangleOfDouble(x0, y0, w0, h0); } - else if (element.getName().getLocalPart().equals("doc")) { + else if (element.getName().getLocalPart().equals(Property.doc)) { event = reader.nextEvent(); - try { - cell.addDoc(EDocID.valueOf(event.asCharacters().getData()).getDoc()); - } catch (IllegalArgumentException e) { /* ignore; just don't add invalid element */ } + model.add(currentKey, EDocID.valueOf(event.asCharacters().getData())); } } } - - // Rough bounds are all in place; resize the window. - SResizingUtil.resizeWindow(); + return model; } - private static void createNode(final XMLEventWriter writer0, final Property name0, - final String val0) throws XMLStreamException { - + private static void createNode(final XMLEventWriter writer0, final String propertyName, final String value) throws XMLStreamException { writer0.add(TAB); writer0.add(TAB); - writer0.add(EF.createStartElement("", "", name0.toString())); - writer0.add(EF.createCharacters(val0)); - writer0.add(EF.createEndElement("", "", name0.toString())); + writer0.add(EF.createStartElement("", "", propertyName)); + writer0.add(EF.createCharacters(value)); + writer0.add(EF.createEndElement("", "", propertyName)); writer0.add(NEWLINE); } /** * Updates preferred / default layout addresses particular to each UI state. * Always called before a load or a save, to ensure file addresses are correct. + * @return */ - private static void setFilesForState() { - switch(FControl.SINGLETON_INSTANCE.getState()) { + private static FileLocation getFileForState(Screens state) { + switch(state) { case HOME_SCREEN: - file = NewConstants.HOME_LAYOUT_FILE; - break; + return NewConstants.HOME_LAYOUT_FILE; case MATCH_SCREEN: - file = NewConstants.MATCH_LAYOUT_FILE; - break; + return NewConstants.MATCH_LAYOUT_FILE; + case DECK_EDITOR_CONSTRUCTED: case DECK_EDITOR_LIMITED: case DECK_EDITOR_QUEST: case DRAFTING_PROCESS: case QUEST_CARD_SHOP: - file = NewConstants.EDITOR_LAYOUT_FILE; - break; + return NewConstants.EDITOR_LAYOUT_FILE; + case QUEST_BAZAAR: - file = null; - break; + return null; + default: throw new IllegalStateException("Layout load failed; UI state unknown."); } } } + \ No newline at end of file diff --git a/src/main/java/forge/gui/framework/SRearrangingUtil.java b/src/main/java/forge/gui/framework/SRearrangingUtil.java index 967c9249cdf..7f95b750478 100644 --- a/src/main/java/forge/gui/framework/SRearrangingUtil.java +++ b/src/main/java/forge/gui/framework/SRearrangingUtil.java @@ -296,8 +296,8 @@ public final class SRearrangingUtil { FView.SINGLETON_INSTANCE.removeDragCell(cellSrc); } - cellNew.setRoughBounds(); - cellTarget.setRoughBounds(); + cellNew.updateRoughBounds(); + cellTarget.updateRoughBounds(); cellSrc.setSelected(srcSelectedDoc); cellSrc.refresh(); @@ -351,7 +351,7 @@ public final class SRearrangingUtil { if (foundT && foundB) { for (final DragCell cell : cellsToResize) { cell.setBounds(cell.getX(), cell.getY(), cell.getW() + srcW, cell.getH()); - cell.setRoughBounds(); + cell.updateRoughBounds(); } return; } @@ -377,7 +377,7 @@ public final class SRearrangingUtil { if (foundT && foundB) { for (final DragCell cell : cellsToResize) { cell.setBounds(cellSrc.getX(), cell.getY(), cell.getW() + srcW, cell.getH()); - cell.setRoughBounds(); + cell.updateRoughBounds(); } return; } @@ -404,7 +404,7 @@ public final class SRearrangingUtil { for (final DragCell cell : cellsToResize) { cell.setBounds(cell.getX(), cellSrc.getY(), cell.getW(), cell.getH() + srcH); - cell.setRoughBounds(); + cell.updateRoughBounds(); } return; } @@ -431,7 +431,7 @@ public final class SRearrangingUtil { for (final DragCell cell : cellsToResize) { cell.setBounds(cell.getX(), cell.getY(), cell.getW(), cell.getH() + srcH); - cell.setRoughBounds(); + cell.updateRoughBounds(); } return; } diff --git a/src/main/java/forge/gui/framework/SResizingUtil.java b/src/main/java/forge/gui/framework/SResizingUtil.java index 19a370352d7..2817a4f8286 100644 --- a/src/main/java/forge/gui/framework/SResizingUtil.java +++ b/src/main/java/forge/gui/framework/SResizingUtil.java @@ -141,28 +141,31 @@ public final class SResizingUtil { // 10% = 9.8px -> 10px -> x 3 = 30px // 30% = 29.4px -> 29px (!) for (final DragCell cellA : cells) { - roughVal = cellA.getRoughX() * w + cellA.getRoughW() * w; + RectangleOfDouble cellSizeA = cellA.getRoughBounds(); + roughVal = cellSizeA.getX() * w + cellSizeA.getW() * w; smoothVal = (int) Math.round(roughVal); for (final DragCell cellB : cells) { - if ((cellB.getRoughX() * w + cellB.getRoughW() * w) == roughVal) { - cellB.setSmoothW(smoothVal - (int) Math.round(cellB.getRoughX() * w)); + RectangleOfDouble cellSizeB = cellB.getRoughBounds(); + if ((cellSizeB.getX() * w + cellSizeB.getW() * w) == roughVal) { + cellB.setSmoothW(smoothVal - (int) Math.round(cellSizeB.getX() * w)); } } - cellA.setSmoothW(smoothVal - (int) Math.round(cellA.getRoughX() * w)); + cellA.setSmoothW(smoothVal - (int) Math.round(cellSizeA.getX() * w)); - roughVal = cellA.getRoughY() * h + cellA.getRoughH() * h; + roughVal = cellSizeA.getY() * h + cellSizeA.getH() * h; smoothVal = (int) Math.round(roughVal); for (final DragCell cellB : cells) { - if (cellB.getRoughY() * h + cellB.getRoughH() * h == roughVal) { - cellB.setSmoothH(smoothVal - (int) Math.round(cellB.getRoughY() * h)); + RectangleOfDouble cellSizeB = cellB.getRoughBounds(); + if (cellSizeB.getY() * h + cellSizeB.getH() * h == roughVal) { + cellB.setSmoothH(smoothVal - (int) Math.round(cellSizeB.getY() * h)); } } - cellA.setSmoothH(smoothVal - (int) Math.round(cellA.getRoughY() * h)); + cellA.setSmoothH(smoothVal - (int) Math.round(cellSizeA.getY() * h)); // X and Y coordinate can be rounded as usual. - cellA.setSmoothX((int) Math.round(cellA.getRoughX() * w)); - cellA.setSmoothY((int) Math.round(cellA.getRoughY() * h)); + cellA.setSmoothX((int) Math.round(cellSizeA.getX() * w)); + cellA.setSmoothY((int) Math.round(cellSizeA.getY() * h)); // only add component if not already in container; otherwise the keyboard focus // jumps around to the most recenly added component diff --git a/src/main/java/forge/gui/match/CMatchUI.java b/src/main/java/forge/gui/match/CMatchUI.java index 3597cc94975..8d43b97e6d9 100644 --- a/src/main/java/forge/gui/match/CMatchUI.java +++ b/src/main/java/forge/gui/match/CMatchUI.java @@ -81,7 +81,7 @@ public enum CMatchUI { * @param numFieldPanels int * @param numHandPanels int */ - public void initMatch(final List players, Player localPlayer) { + public void initMatch(final List players, LobbyPlayer localPlayer) { // TODO fix for use with multiplayer final String[] indices = Singletons.getModel().getPreferences().getPref(FPref.UI_AVATARS).split(","); @@ -89,19 +89,19 @@ public enum CMatchUI { // Instantiate all required field slots (user at 0) <-- that's not guaranteed final List fields = new ArrayList(); final List commands = new ArrayList(); + final List hands = new ArrayList(); + // get an arranged list so that the first local player is at index 0 List sortedPlayers = Lists.newArrayList(players); - - int ixLocal = -1; + int ixFirstHuman = -1; for(int i = 0; i < players.size(); i++) { - if( sortedPlayers.get(i) == localPlayer ) { - ixLocal = i; + if( sortedPlayers.get(i).getLobbyPlayer() == localPlayer ) { + ixFirstHuman = i; break; } } - if( ixLocal > 0 ) { - Player p0 = sortedPlayers.remove(ixLocal); - sortedPlayers.add(0, p0); + if( ixFirstHuman > 0 ) { + sortedPlayers.add(0, sortedPlayers.remove(ixFirstHuman)); } @@ -109,8 +109,8 @@ public enum CMatchUI { for (Player p : sortedPlayers) { // A field must be initialized after it's instantiated, to update player info. // No player, no init. - VField f = new VField(EDocID.valueOf("FIELD_" + i), p, localPlayer); - VCommand c = new VCommand(EDocID.valueOf("COMMAND_" + i), p); + VField f = new VField(EDocID.Fields[i], p, localPlayer); + VCommand c = new VCommand(EDocID.Commands[i], p); fields.add(f); commands.add(c); @@ -118,22 +118,20 @@ public enum CMatchUI { setAvatar(f, getPlayerAvatar(p, Integer.parseInt(indices[i > 2 ? 1 : 0]))); f.getLayoutControl().initialize(); c.getLayoutControl().initialize(); + + if (p.getLobbyPlayer() == localPlayer) { + VHand newHand = new VHand(EDocID.Hands[i], p); + newHand.getLayoutControl().initialize(); + hands.add(newHand); + } i++; } - - - // Instantiate all required hand slots (user at 0) - final List hands = new ArrayList(); - VHand newHand = new VHand(EDocID.HAND_0, localPlayer); - newHand.getLayoutControl().initialize(); - hands.add(newHand); - -// Max: 2+ hands are needed at 2HG (but this is quite far from now) - yet it's nice to have this possibility -// for (int i = 0; i < numHandPanels; i++) { -// switch (i) { -// hands.add(i, new VHand(EDocID.valueOf("HAND_" + i), null)); -// } -// } + + if(hands.isEmpty()) { // add empty hand for matches without human + VHand newHand = new VHand(EDocID.Hands[0], null); + newHand.getLayoutControl().initialize(); + hands.add(newHand); + } // Replace old instances VMatchUI.SINGLETON_INSTANCE.setCommandViews(commands); diff --git a/src/main/java/forge/gui/match/VMatchUI.java b/src/main/java/forge/gui/match/VMatchUI.java index 75127215ddc..d223ef83563 100644 --- a/src/main/java/forge/gui/match/VMatchUI.java +++ b/src/main/java/forge/gui/match/VMatchUI.java @@ -40,23 +40,10 @@ public enum VMatchUI implements IVTopLevelUI { private final CMatchUI control = null; private VMatchUI() { - // Create empty docs for all field slots - for (int i = 0; i < 8; i++) { - EDocID.valueOf("FIELD_" + i).setDoc( - new VEmptyDoc(EDocID.valueOf("FIELD_" + i))); - } - - // Create empty docs for all field slots - for (int i = 0; i < 8; i++) { - EDocID.valueOf("COMMAND_" + i).setDoc( - new VEmptyDoc(EDocID.valueOf("COMMAND_" + i))); - } - - // Create empty docs for all hand slots - for (int i = 0; i < 4; i++) { - EDocID.valueOf("HAND_" + i).setDoc( - new VEmptyDoc(EDocID.valueOf("HAND_" + i))); - } + // Create empty docs for all slots + for (int i = 0; i < 8; i++) EDocID.Fields[i].setDoc(new VEmptyDoc(EDocID.Fields[i])); + for (int i = 0; i < 8; i++) EDocID.Commands[i].setDoc(new VEmptyDoc(EDocID.Commands[i])); + for (int i = 0; i < 8; i++) EDocID.Hands[i].setDoc(new VEmptyDoc(EDocID.Hands[i])); } /** */ @@ -108,7 +95,7 @@ public enum VMatchUI implements IVTopLevelUI { } // Add extra hands to existing hand panel. - for (int i = 0; i < lstHands.size(); i++) { + for (int i = 1; i < lstHands.size(); i++) { // If already in layout, no need to add again. if (lstHands.get(i).getParentCell() == null) { // if i == 0, we get NPE in two lines DragCell cellWithHand = lstHands.get(0).getParentCell(); diff --git a/src/main/java/forge/gui/match/controllers/CDock.java b/src/main/java/forge/gui/match/controllers/CDock.java index bb1595ca730..211ea513496 100644 --- a/src/main/java/forge/gui/match/controllers/CDock.java +++ b/src/main/java/forge/gui/match/controllers/CDock.java @@ -27,10 +27,9 @@ import java.util.Map.Entry; import java.util.TreeMap; import javax.swing.JOptionPane; -import javax.swing.SwingWorker; - import forge.Card; import forge.CardLists; +import forge.FThreads; import forge.CardPredicates.Presets; import forge.Command; import forge.deck.Deck; @@ -94,54 +93,44 @@ public enum CDock implements ICDoc { SOverlayUtils.genericOverlay(); FView.SINGLETON_INSTANCE.getPnlContent().removeAll(); - final SwingWorker w = new SwingWorker() { - @Override - public Void doInBackground() { + FThreads.invokeInEdtLater(new Runnable(){ + @Override public void run() { SLayoutIO.loadLayout(null); SOverlayUtils.hideOverlay(); - return null; } - }; - w.execute(); + }); + } private void saveLayout() { - final SwingWorker w = new SwingWorker() { - @Override - public Void doInBackground() { - final SaveOpenDialog dlgSave = new SaveOpenDialog(); - final File defFile = new File(SLayoutIO.getFilePreferred()); - final File saveFile = dlgSave.SaveDialog(defFile, Filetypes.LAYOUT); - if (saveFile != null) { - SLayoutIO.saveLayout(saveFile); - } - return null; - } - }; - w.execute(); + final SaveOpenDialog dlgSave = new SaveOpenDialog(); + final File defFile = new File(SLayoutIO.getFilePreferred()); + final File saveFile = dlgSave.SaveDialog(defFile, Filetypes.LAYOUT); + if (saveFile != null) { + SLayoutIO.saveLayout(saveFile); + } } private void openLayout() { SOverlayUtils.genericOverlay(); + + final SaveOpenDialog dlgOpen = new SaveOpenDialog(); + final File defFile = new File(SLayoutIO.getFilePreferred()); + final File loadFile = dlgOpen.OpenDialog(defFile, Filetypes.LAYOUT); + FView.SINGLETON_INSTANCE.getPnlContent().removeAll(); - - final SwingWorker w = new SwingWorker() { + // let it redraw everything first + + FThreads.invokeInEdtLater(new Runnable() { @Override - public Void doInBackground() { - final SaveOpenDialog dlgOpen = new SaveOpenDialog(); - final File defFile = new File(SLayoutIO.getFilePreferred()); - final File loadFile = dlgOpen.OpenDialog(defFile, Filetypes.LAYOUT); - + public void run() { if (loadFile != null) { SLayoutIO.loadLayout(loadFile); SLayoutIO.saveLayout(null); } - SOverlayUtils.hideOverlay(); - return null; } - }; - w.execute(); + }); } /** diff --git a/src/main/java/forge/gui/match/controllers/CMessage.java b/src/main/java/forge/gui/match/controllers/CMessage.java index a220bbe0d10..9ad5a643064 100644 --- a/src/main/java/forge/gui/match/controllers/CMessage.java +++ b/src/main/java/forge/gui/match/controllers/CMessage.java @@ -46,6 +46,7 @@ public enum CMessage implements ICDoc, Observer { private InputProxy inputControl = new InputProxy(); private Component lastFocusedButton = null; + private VMessage view = VMessage.SINGLETON_INSTANCE; private final ActionListener actCancel = new ActionListener() { @Override @@ -63,7 +64,7 @@ public enum CMessage implements ICDoc, Observer { private final FocusListener onFocus = new FocusAdapter() { @Override public void focusGained(FocusEvent e) { - if (null != VMessage.SINGLETON_INSTANCE.getParentCell() && VMessage.SINGLETON_INSTANCE == VMessage.SINGLETON_INSTANCE.getParentCell().getSelected()) { + if (null != view.getParentCell() && view == view.getParentCell().getSelected()) { // only record focus changes when we're showing -- otherwise it is due to a tab visibility change lastFocusedButton = e.getComponent(); } @@ -81,8 +82,8 @@ public enum CMessage implements ICDoc, Observer { @Override public void initialize() { - _initButton(VMessage.SINGLETON_INSTANCE.getBtnCancel(), actCancel); - _initButton(VMessage.SINGLETON_INSTANCE.getBtnOK(), actOK); + _initButton(view.getBtnCancel(), actCancel); + _initButton(view.getBtnOK(), actOK); } /** @@ -96,12 +97,12 @@ public enum CMessage implements ICDoc, Observer { /** @param s0   {@link java.lang.String} */ public void setMessage(String s0) { - VMessage.SINGLETON_INSTANCE.getTarMessage().setText(s0); + view.getTarMessage().setText(s0); } /** Flashes animation on input panel if play is currently waiting on input. */ public void remind() { - SDisplayUtil.remind(VMessage.SINGLETON_INSTANCE); + SDisplayUtil.remind(view); } /* (non-Javadoc) @@ -117,7 +118,7 @@ public enum CMessage implements ICDoc, Observer { */ @Override public void update(Observable o, Object arg) { - VMessage.SINGLETON_INSTANCE.getLblGames().setText( + view.getLblGames().setText( match.getGameType().toString() + ": Game #" + (match.getPlayedGames().size() + 1) + " of " + match.getGamesPerMatch() diff --git a/src/main/java/forge/gui/match/nonsingleton/CField.java b/src/main/java/forge/gui/match/nonsingleton/CField.java index 40ee98a3486..54a3cdb72b6 100644 --- a/src/main/java/forge/gui/match/nonsingleton/CField.java +++ b/src/main/java/forge/gui/match/nonsingleton/CField.java @@ -38,6 +38,7 @@ import forge.control.input.Input; import forge.control.input.InputPayManaBase; import forge.game.GameState; import forge.game.player.HumanPlay; +import forge.game.player.LobbyPlayer; import forge.game.player.Player; import forge.game.zone.ZoneType; import forge.gui.ForgeAction.MatchConstants; @@ -53,7 +54,7 @@ public class CField implements ICDoc { // The one who owns cards on this side of table private final Player player; // Tho one who looks at screen and 'performs actions' - private final Player playerViewer; + private final LobbyPlayer viewer; private final VField view; private boolean initializedAlready = false; @@ -127,9 +128,9 @@ public class CField implements ICDoc { * @param playerViewer */ @SuppressWarnings("serial") - public CField(final Player p0, final VField v0, Player playerViewer) { + public CField(final Player p0, final VField v0, LobbyPlayer playerViewer) { this.player = p0; - this.playerViewer = playerViewer; + this.viewer = playerViewer; this.view = v0; handAction = new ZoneAction(player.getZone(ZoneType.Hand), MatchConstants.HUMANHAND); @@ -144,16 +145,18 @@ public class CField implements ICDoc { @Override protected void doAction(final Card c) { - // activate opponents cards only via your own flashback button - if (player != CField.this.playerViewer) { + // activate cards only via your own flashback button + if (player.getLobbyPlayer() != CField.this.viewer) { return; } final GameState game = player.getGame(); + // TODO: "can play" check needed! + // should I check for who owns these cards? Are there any abilities to be played from opponent's graveyard? - final SpellAbility ab = CField.this.playerViewer.getController().getAbilityToPlay(game.getAbilitesOfCard(c, CField.this.playerViewer)); + final SpellAbility ab = player.getController().getAbilityToPlay(game.getAbilitesOfCard(c, player)); if ( null != ab) { FThreads.invokeInNewThread(new Runnable(){ @Override public void run(){ - HumanPlay.playSpellAbility(CField.this.playerViewer, c, ab); + HumanPlay.playSpellAbility(player, c, ab); }}); } } @@ -161,7 +164,7 @@ public class CField implements ICDoc { } private void handClicked() { - if ( player == playerViewer || Preferences.DEV_MODE || player.hasKeyword("Play with your hand revealed.")) { + if ( player.getLobbyPlayer() == viewer || Preferences.DEV_MODE || player.hasKeyword("Play with your hand revealed.")) { handAction.actionPerformed(null); } } @@ -199,7 +202,7 @@ public class CField implements ICDoc { /** */ private void manaAction(byte colorCode) { - if (CField.this.player == CField.this.playerViewer) { + if (CField.this.player.getLobbyPlayer() == CField.this.viewer) { final Input in = CField.this.player.getGame().getInputQueue().getInput(); if (in instanceof InputPayManaBase) { // Do something diff --git a/src/main/java/forge/gui/match/nonsingleton/CHand.java b/src/main/java/forge/gui/match/nonsingleton/CHand.java index 4329b96aa16..371f388d4c9 100644 --- a/src/main/java/forge/gui/match/nonsingleton/CHand.java +++ b/src/main/java/forge/gui/match/nonsingleton/CHand.java @@ -34,7 +34,6 @@ import forge.Card; import forge.Command; import forge.Singletons; import forge.game.player.Player; -import forge.game.zone.PlayerZone; import forge.game.zone.ZoneType; import forge.gui.framework.ICDoc; import forge.gui.match.CMatchUI; @@ -47,7 +46,7 @@ import forge.view.arcane.util.Animation; * Controls Swing components of a player's hand instance. * */ -public class CHand implements ICDoc { +public class CHand implements ICDoc, Observer { private final Player player; private final VHand view; private boolean initializedAlready = false; @@ -58,9 +57,6 @@ public class CHand implements ICDoc { public void mousePressed(final MouseEvent e) { cardclickAction(e); } }; - private final Observer o1 = new Observer() { @Override - public void update(final Observable a, final Object b) { - observerAction(a); } }; /** * Controls Swing components of a player's hand instance. @@ -78,8 +74,8 @@ public class CHand implements ICDoc { if (initializedAlready) { return; } initializedAlready = true; - if ( player != null) - player.getZone(ZoneType.Hand).addObserver(o1); + if (player != null) + player.getZone(ZoneType.Hand).addObserver(this); view.getHandArea().addMouseListener(madCardClick); } @@ -136,48 +132,6 @@ public class CHand implements ICDoc { //this.view.refreshLayout(); } - /** - * Gets the cards. - * - * @return List - */ - public List getCards() { - return this.cardsInPanel; - } - - /** - * Removes the card. - * - * @param c - *   Card object - */ - public void removeCard(final Card c) { - this.cardsInPanel.remove(c); - //this.view.refreshLayout(); - } - - /** - * Removes the cards. - * - * @param c - *   List of Card objects - */ - public void removeCards(final List c) { - this.cardsInPanel.removeAll(c); - //this.view.refreshLayout(); - } - - /** - * Reset cards. - * - * @param c - *   List of Card objects - */ - public void resetCards(final List c) { - this.cardsInPanel.clear(); - this.addCards(c); - } - private void cardclickAction(final MouseEvent e) { if (e.getButton() != MouseEvent.BUTTON1) { return; @@ -188,13 +142,12 @@ public class CHand implements ICDoc { } } - private void observerAction(final Observable a) { - final PlayerZone pZone = (PlayerZone) a; + public void update(final Observable a, final Object b) { final HandArea p = view.getHandArea(); final Rectangle rctLibraryLabel = CMatchUI.SINGLETON_INSTANCE .getFieldControls().get(0) .getView().getLblLibrary().getBounds(); - final List c = pZone.getCards(); + final List c = player.getZone(ZoneType.Hand).getCards(); // Animation starts from the library label and runs to the hand panel. // This check prevents animation running if label hasn't been realized yet. diff --git a/src/main/java/forge/gui/match/nonsingleton/VField.java b/src/main/java/forge/gui/match/nonsingleton/VField.java index cdfd24c513e..211ce8d4115 100644 --- a/src/main/java/forge/gui/match/nonsingleton/VField.java +++ b/src/main/java/forge/gui/match/nonsingleton/VField.java @@ -42,6 +42,7 @@ import forge.card.MagicColor; import forge.card.cardfactory.CardFactoryUtil; import forge.card.mana.ManaPool; import forge.game.phase.PhaseType; +import forge.game.player.LobbyPlayer; import forge.game.player.Player; import forge.game.zone.ZoneType; import forge.gui.framework.DragCell; @@ -117,7 +118,7 @@ public class VField implements IVDoc { * @param playerOnwer   {@link forge.game.player.Player} * @param id0   {@link forge.gui.framework.EDocID} */ - public VField(final EDocID id0, final Player playerOnwer, Player playerViewer) { + public VField(final EDocID id0, final Player playerOnwer, LobbyPlayer playerViewer) { this.docID = id0; id0.setDoc(this); diff --git a/src/main/java/forge/gui/match/nonsingleton/VHand.java b/src/main/java/forge/gui/match/nonsingleton/VHand.java index baa01fe0e87..35f3787681a 100644 --- a/src/main/java/forge/gui/match/nonsingleton/VHand.java +++ b/src/main/java/forge/gui/match/nonsingleton/VHand.java @@ -50,16 +50,16 @@ public class VHand implements IVDoc { * Assembles Swing components of a player hand instance. * * @param id0   {@link forge.gui.framework.EDocID} - * @param player0   {@link forge.game.player.Player} + * @param owner   {@link forge.game.player.Player} */ - public VHand(final EDocID id0, final Player player0) { + public VHand(final EDocID id0, final Player owner) { docID = id0; id0.setDoc(this); - if (player0 == null) { + if (owner == null) { tab.setText("NO PLAYER Hand"); } else { - tab.setText(player0.getName() + " Hand"); + tab.setText(owner.getName() + " Hand"); } scroller.setBorder(null); @@ -69,7 +69,7 @@ public class VHand implements IVDoc { hand.setOpaque(false); - control = new CHand(player0, this); + control = new CHand(owner, this); } //========= Overridden methods