mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
Thread safety: Tightened up conditions in FProgressBar, made a few changes to skin loading as appropriate.
This commit is contained in:
@@ -35,6 +35,8 @@ import java.util.regex.Pattern;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import net.slightlymagic.braids.util.UtilFunctions;
|
||||
import net.slightlymagic.braids.util.generator.FindNonDirectoriesSkipDotDirectoriesGenerator;
|
||||
import net.slightlymagic.braids.util.generator.GeneratorFunctions;
|
||||
@@ -273,8 +275,11 @@ public class CardReader implements Runnable {
|
||||
}
|
||||
|
||||
if (barProgress != null) {
|
||||
barProgress.setMaximum((int) this.estimatedFilesRemaining);
|
||||
barProgress.setDescription("Preloading card images: ");
|
||||
barProgress.setMaximum((int) estimatedFilesRemaining);
|
||||
SwingUtilities.invokeLater(new Runnable() { @Override
|
||||
public void run() {
|
||||
barProgress.setDescription("Preloading card images: ");
|
||||
} });
|
||||
}
|
||||
|
||||
for (final File cardTxtFile : this.findNonDirsIterable) {
|
||||
|
||||
@@ -30,6 +30,7 @@ import forge.CardReader;
|
||||
import forge.Singletons;
|
||||
import forge.card.CardRules;
|
||||
import forge.error.ErrorViewer;
|
||||
import forge.gui.GuiUtils;
|
||||
import forge.item.CardDb;
|
||||
import forge.properties.ForgeProps;
|
||||
import forge.properties.NewConstants;
|
||||
@@ -76,6 +77,7 @@ public class PreloadingCardFactory extends AbstractCardFactory {
|
||||
*/
|
||||
public PreloadingCardFactory(final File file) {
|
||||
super(file);
|
||||
GuiUtils.checkEDT("PreloadingCardFactory$constructor", false);
|
||||
|
||||
try {
|
||||
this.readCards(file);
|
||||
|
||||
@@ -155,7 +155,7 @@ public class ControlSettings {
|
||||
|
||||
FSkin skin = new FSkin(name);
|
||||
|
||||
skin.loadFontsAndImages();
|
||||
skin.load();
|
||||
|
||||
prefs.setPref(FPref.UI_SKIN, name);
|
||||
Singletons.getView().setSkin(skin);
|
||||
|
||||
@@ -35,6 +35,7 @@ import javax.swing.Box;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
|
||||
@@ -411,7 +412,8 @@ public final class GuiUtils {
|
||||
}
|
||||
|
||||
/** Duplicate in DeckEditorQuestMenu and
|
||||
* probably elsewhere...can streamline at some point.
|
||||
* probably elsewhere...can streamline at some point
|
||||
* (probably shouldn't be here).
|
||||
*
|
||||
* @param in   {@link java.lang.String}
|
||||
* @return {@link java.lang.String}
|
||||
@@ -428,4 +430,24 @@ public final class GuiUtils {
|
||||
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
/** Checks if calling method uses event dispatch thread.
|
||||
* Exception thrown if method is on "wrong" thread.
|
||||
* A boolean is passed to indicate if the method must be EDT or not.
|
||||
*
|
||||
* @param methodName   String, part of the custom exception message.
|
||||
* @param mustBeEDT   boolean: true = exception if not EDT, false = exception if EDT
|
||||
*/
|
||||
public static void checkEDT(String methodName, boolean mustBeEDT) {
|
||||
boolean isEDT = SwingUtilities.isEventDispatchThread();
|
||||
|
||||
if (!isEDT && mustBeEDT) {
|
||||
throw new IllegalStateException(
|
||||
methodName + " must be accessed from the event dispatch thread.");
|
||||
}
|
||||
else if (isEDT && !mustBeEDT) {
|
||||
throw new IllegalStateException(
|
||||
methodName + " may not be accessed from the event dispatch thread.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,16 +105,15 @@ public class FView {
|
||||
AllZone.getCardFactory();
|
||||
|
||||
// Preloads skin components (using progress bar).
|
||||
FView.this.skin.loadFontsAndImages();
|
||||
FView.this.skin.load();
|
||||
|
||||
// Does not use progress bar, due to be deprecated in favor of skin.
|
||||
// Does not use progress bar, due to be deprecated with battlefield refactoring.
|
||||
CardFaceSymbols.loadImages();
|
||||
|
||||
barProgress.setDescription("Creating display components.");
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
barProgress.setDescription("Creating display components.");
|
||||
final GuiTopLevel g = new GuiTopLevel();
|
||||
AllZone.setDisplay(g);
|
||||
g.getController().changeState(FControl.HOME_SCREEN);
|
||||
|
||||
@@ -1,28 +1,25 @@
|
||||
package forge.view.toolbox;
|
||||
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.swing.JProgressBar;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import forge.gui.GuiUtils;
|
||||
|
||||
/**
|
||||
* A simple progress bar component using the Forge skin.
|
||||
*
|
||||
* Can show
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class FProgressBar extends JProgressBar {
|
||||
private static final long serialVersionUID = 3479715871723156426L;
|
||||
private int tempVal = 0;
|
||||
private long startMillis = 0;
|
||||
private long tempMillis = 0;
|
||||
private long startMillis = 0, tempMillis = 0;
|
||||
private float timePerUnit = 0;
|
||||
private int eta = 0;
|
||||
private boolean isIncrementing = false;
|
||||
private int tempVal = 0, etaMillis = 0;
|
||||
private int hours, minutes, seconds;
|
||||
private String desc = "";
|
||||
private String str = "";
|
||||
private String desc = "", count = "", eta = "";
|
||||
private boolean showETA = true;
|
||||
private boolean showCount = true;
|
||||
|
||||
@@ -33,58 +30,43 @@ public class FProgressBar extends JProgressBar {
|
||||
this.setStringPainted(true);
|
||||
}
|
||||
|
||||
/** @param s0   A description to prepend before statistics. */
|
||||
/**
|
||||
* Sets description on bar. Must be called from EDT.
|
||||
*
|
||||
* @param s0   A description to prepend before statistics.
|
||||
*/
|
||||
public void setDescription(final String s0) {
|
||||
GuiUtils.checkEDT("FProgressBar$setDescription", true);
|
||||
this.desc = s0;
|
||||
this.setString(s0);
|
||||
}
|
||||
|
||||
/** */
|
||||
/** Increments bar, thread safe. Calculations executed on separate thread. */
|
||||
public void increment() {
|
||||
if (isIncrementing) { System.out.println("Rejected."); return; }
|
||||
final Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
tempVal++;
|
||||
count = (showCount ? " " + tempVal + " of " + getMaximum() : "");
|
||||
eta = (showETA ? calculateETA(tempVal) : "");
|
||||
|
||||
isIncrementing = true;
|
||||
tempVal++;
|
||||
this.setValue(tempVal);
|
||||
str = desc;
|
||||
if (showCount) { calculateCount(tempVal); }
|
||||
if (showETA) { calculateETA(tempVal); }
|
||||
updateString();
|
||||
isIncrementing = false;
|
||||
// When calculations finished; EDT can be used.
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FProgressBar.this.setValue(tempVal);
|
||||
updateString();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
r.run();
|
||||
}
|
||||
|
||||
private void calculateCount(int v0) {
|
||||
str += " " + v0 + " of " + this.getMaximum();
|
||||
}
|
||||
|
||||
/** */
|
||||
private void calculateETA(int v0) {
|
||||
tempMillis = new Date().getTime();
|
||||
timePerUnit = (tempMillis - startMillis) / (float) v0;
|
||||
eta = (int) ((this.getMaximum() - v0) * timePerUnit) / 1000;
|
||||
|
||||
seconds = eta;
|
||||
hours = seconds >= 3600 ? (seconds / 3600) : 0;
|
||||
seconds = eta % 3600;
|
||||
minutes = seconds >= 60 ? (seconds / 60) : 0;
|
||||
seconds = eta % 60 + 1;
|
||||
|
||||
str += ", ETA " + String.format("%02d", hours) + ":"
|
||||
+ String.format("%02d", minutes) + ":"
|
||||
+ String.format("%02d", seconds);
|
||||
}
|
||||
|
||||
private void updateString() {
|
||||
this.setString(str);
|
||||
}
|
||||
|
||||
/** Resets the various values required for this class. */
|
||||
/** Resets the various values required for this class. Must be called from EDT. */
|
||||
public void reset() {
|
||||
if (!SwingUtilities.isEventDispatchThread()) {
|
||||
throw new IllegalStateException(
|
||||
"FProgressBar > reset() must be accessed from an event dispatch thread.");
|
||||
}
|
||||
|
||||
GuiUtils.checkEDT("FProgressBar$reset", true);
|
||||
this.setIndeterminate(true);
|
||||
this.setValue(0);
|
||||
this.tempVal = 0;
|
||||
@@ -99,18 +81,30 @@ public class FProgressBar extends JProgressBar {
|
||||
this.showETA = b0;
|
||||
}
|
||||
|
||||
/** @return b0   Boolean, show the ETA statistic or not */
|
||||
public boolean isShowETA() {
|
||||
return showETA;
|
||||
}
|
||||
|
||||
/** @param b0   Boolean, show the ETA statistic or not */
|
||||
public void setShowCount(boolean b0) {
|
||||
this.showCount = b0;
|
||||
}
|
||||
|
||||
/** @return b0   Boolean, show the ETA statistic or not */
|
||||
public boolean isShowCount() {
|
||||
return showCount;
|
||||
/** */
|
||||
private String calculateETA(int v0) {
|
||||
GuiUtils.checkEDT("FProgressBar$calculateETA", false);
|
||||
tempMillis = new Date().getTime();
|
||||
timePerUnit = (tempMillis - startMillis) / (float) v0;
|
||||
etaMillis = (int) ((this.getMaximum() - v0) * timePerUnit) / 1000;
|
||||
|
||||
seconds = etaMillis;
|
||||
hours = seconds >= 3600 ? (seconds / 3600) : 0;
|
||||
seconds = etaMillis % 3600;
|
||||
minutes = seconds >= 60 ? (seconds / 60) : 0;
|
||||
seconds = etaMillis % 60 + 1;
|
||||
|
||||
return ", ETA " + String.format("%02d", hours) + ":"
|
||||
+ String.format("%02d", minutes) + ":"
|
||||
+ String.format("%02d", seconds);
|
||||
}
|
||||
|
||||
private void updateString() {
|
||||
this.setString(desc + count + eta);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,16 +45,6 @@ import forge.gui.GuiUtils;
|
||||
*/
|
||||
|
||||
public class FSkin {
|
||||
/** Properties of various components that make up the skin. */
|
||||
public interface SkinProp { }
|
||||
/** Add this interface for sub-sprite components, storing their coords. */
|
||||
public interface Coords {
|
||||
/** */
|
||||
int[] COORDS = null;
|
||||
/** @return int[] */
|
||||
int[] getCoords();
|
||||
}
|
||||
|
||||
/** */
|
||||
public enum Backgrounds implements SkinProp { /** */
|
||||
BG_SPLASH, /** */
|
||||
@@ -331,6 +321,16 @@ public class FSkin {
|
||||
public int[] getCoords() { return coords; }
|
||||
}
|
||||
|
||||
/** Properties of various components that make up the skin. */
|
||||
public interface SkinProp { }
|
||||
/** Add this interface for sub-sprite components, storing their coords. */
|
||||
public interface Coords {
|
||||
/** */
|
||||
int[] COORDS = null;
|
||||
/** @return int[] */
|
||||
int[] getCoords();
|
||||
}
|
||||
|
||||
private Map<SkinProp, ImageIcon> icons;
|
||||
private Map<SkinProp, Image> images;
|
||||
private Map<SkinProp, Color> colors;
|
||||
@@ -375,6 +375,8 @@ public class FSkin {
|
||||
* the skin name
|
||||
*/
|
||||
public FSkin(final String skinName) {
|
||||
GuiUtils.checkEDT("FSkin$constructor", false);
|
||||
|
||||
this.preferredName = skinName;
|
||||
this.preferredDir = FILE_SKINS_DIR + preferredName + "/";
|
||||
this.defaultDir = FILE_SKINS_DIR + "default/";
|
||||
@@ -423,7 +425,8 @@ public class FSkin {
|
||||
* preferred takes precedence over default, but if something is
|
||||
* missing, the default picture is retrieved.
|
||||
*/
|
||||
public void loadFontsAndImages() {
|
||||
public void load() {
|
||||
GuiUtils.checkEDT("FSkin$load", false);
|
||||
barProgress = Singletons.getView().getProgressBar();
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@@ -431,13 +434,12 @@ public class FSkin {
|
||||
public void run() {
|
||||
barProgress.reset();
|
||||
barProgress.setShowETA(false);
|
||||
barProgress.setDescription("Processing fonts and image sprites: ");
|
||||
barProgress.setDescription("Processing image sprites: ");
|
||||
}
|
||||
});
|
||||
|
||||
barProgress.setMaximum(57);
|
||||
|
||||
// Grab and test various sprite files.
|
||||
barProgress.setMaximum(4);
|
||||
final File f1 = new File(defaultDir + FILE_ICON_SPRITE);
|
||||
final File f2 = new File(preferredDir + FILE_ICON_SPRITE);
|
||||
final File f3 = new File(defaultDir + FILE_CREATURE_SPRITE);
|
||||
@@ -445,10 +447,13 @@ public class FSkin {
|
||||
|
||||
try {
|
||||
bimDefaultSprite = ImageIO.read(f1);
|
||||
barProgress.increment();
|
||||
bimPreferredSprite = ImageIO.read(f2);
|
||||
|
||||
barProgress.increment();
|
||||
bimCreatures = ImageIO.read(f3);
|
||||
barProgress.increment();
|
||||
bimFoils = ImageIO.read(f4);
|
||||
barProgress.increment();
|
||||
|
||||
preferredH = bimPreferredSprite.getHeight();
|
||||
preferredW = bimPreferredSprite.getWidth();
|
||||
@@ -458,31 +463,41 @@ public class FSkin {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// Images loaded; can start UI init.
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
barProgress.setShowETA(false);
|
||||
barProgress.setShowCount(false);
|
||||
barProgress.setDescription("Creating display components.");
|
||||
}
|
||||
});
|
||||
|
||||
// Pre-derive most fonts (plain, bold, and italic).
|
||||
// Exceptions handled inside method.
|
||||
this.font = GuiUtils.newFont(FILE_SKINS_DIR + preferredName + "/" + FILE_FONT);
|
||||
plainFonts = new HashMap<Integer, Font>();
|
||||
setFontAndIncrement(10);
|
||||
setFontAndIncrement(11);
|
||||
setFontAndIncrement(12);
|
||||
setFontAndIncrement(13);
|
||||
setFontAndIncrement(14);
|
||||
setFontAndIncrement(15);
|
||||
setFontAndIncrement(16);
|
||||
setFontAndIncrement(18);
|
||||
setFontAndIncrement(20);
|
||||
setFontAndIncrement(22);
|
||||
setFont(10);
|
||||
setFont(11);
|
||||
setFont(12);
|
||||
setFont(13);
|
||||
setFont(14);
|
||||
setFont(15);
|
||||
setFont(16);
|
||||
setFont(18);
|
||||
setFont(20);
|
||||
setFont(22);
|
||||
|
||||
boldFonts = new HashMap<Integer, Font>();
|
||||
setBoldFontAndIncrement(12);
|
||||
setBoldFontAndIncrement(14);
|
||||
setBoldFontAndIncrement(16);
|
||||
setBoldFontAndIncrement(18);
|
||||
setBoldFontAndIncrement(20);
|
||||
setBoldFont(12);
|
||||
setBoldFont(14);
|
||||
setBoldFont(16);
|
||||
setBoldFont(18);
|
||||
setBoldFont(20);
|
||||
|
||||
italicFonts = new HashMap<Integer, Font>();
|
||||
setItalicFontAndIncrement(12);
|
||||
setItalicFontAndIncrement(14);
|
||||
setItalicFont(12);
|
||||
setItalicFont(14);
|
||||
|
||||
// Put various images into map (except sprite and splash).
|
||||
// Exceptions handled inside method.
|
||||
@@ -749,19 +764,16 @@ public class FSkin {
|
||||
this.colors.put(s0, c0);
|
||||
}
|
||||
|
||||
private void setFontAndIncrement(int size) {
|
||||
private void setFont(int size) {
|
||||
plainFonts.put(size, font.deriveFont(Font.PLAIN, size));
|
||||
if (barProgress != null) { barProgress.increment(); }
|
||||
}
|
||||
|
||||
private void setBoldFontAndIncrement(int size) {
|
||||
private void setBoldFont(int size) {
|
||||
boldFonts.put(size, font.deriveFont(Font.BOLD, size));
|
||||
if (barProgress != null) { barProgress.increment(); }
|
||||
}
|
||||
|
||||
private void setItalicFontAndIncrement(int size) {
|
||||
private void setItalicFont(int size) {
|
||||
italicFonts.put(size, font.deriveFont(Font.ITALIC, size));
|
||||
if (barProgress != null) { barProgress.increment(); }
|
||||
}
|
||||
|
||||
private void setIcon(final SkinProp s0) {
|
||||
|
||||
Reference in New Issue
Block a user