Thread safety: Tightened up conditions in FProgressBar, made a few changes to skin loading as appropriate.

This commit is contained in:
Doublestrike
2012-01-31 00:08:56 +00:00
parent 6d7e567d0d
commit d32b3c8e32
7 changed files with 139 additions and 105 deletions

View File

@@ -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) {

View File

@@ -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);

View 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);

View File

@@ -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.");
}
}
}

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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) {