You can subscribe to this list here.
| 2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(3) |
Nov
(46) |
Dec
(57) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2009 |
Jan
(51) |
Feb
(10) |
Mar
|
Apr
|
May
(14) |
Jun
|
Jul
(13) |
Aug
(30) |
Sep
(83) |
Oct
(56) |
Nov
(148) |
Dec
(107) |
| 2010 |
Jan
(260) |
Feb
(164) |
Mar
(183) |
Apr
(99) |
May
(160) |
Jun
(40) |
Jul
(33) |
Aug
(48) |
Sep
(22) |
Oct
(24) |
Nov
(1) |
Dec
(12) |
| 2011 |
Jan
(6) |
Feb
(15) |
Mar
(13) |
Apr
(37) |
May
(27) |
Jun
(29) |
Jul
(33) |
Aug
(20) |
Sep
(17) |
Oct
(20) |
Nov
(33) |
Dec
(17) |
| 2012 |
Jan
(39) |
Feb
(38) |
Mar
(20) |
Apr
(21) |
May
(17) |
Jun
(22) |
Jul
(16) |
Aug
(3) |
Sep
(9) |
Oct
(10) |
Nov
|
Dec
|
|
From: Frederick W. <fre...@us...> - 2012-02-19 15:57:32
|
rails/sound/SoundContext.java | 18 +++++++++++-------
rails/sound/SoundPlayer.java | 36 +++++++++++++++++++++++++++---------
2 files changed, 38 insertions(+), 16 deletions(-)
New commits:
commit 1f16f2ebfa66afd2971dc0c28675d4d360b6d804
Author: Frederick Weld <fre...@gm...>
Date: Sun Feb 19 16:56:16 2012 +0100
Fixed bug of initially playing 2 music files for command line loading
diff --git a/rails/sound/SoundContext.java b/rails/sound/SoundContext.java
index c38b334..f18f190 100644
--- a/rails/sound/SoundContext.java
+++ b/rails/sound/SoundContext.java
@@ -70,8 +70,10 @@ public class SoundContext {
}
private void playBackgroundMusic() {
- //do nothing if music is not enabled
- if (!SoundConfig.isBGMEnabled()) return;
+ //do nothing if
+ // - music is not enabled
+ // - phase is not initialized
+ if (!SoundConfig.isBGMEnabled() || currentPhase == null) return;
String currentRoundConfigKey = null;
if (currentRound instanceof StartRound) {
@@ -83,7 +85,9 @@ public class SoundContext {
} else if (currentRound instanceof EndOfGameRound) {
currentRoundConfigKey = SoundConfig.KEY_BGM_EndOfGameRound;
}
- //only play anything if round is recognized and new music is to be played
+ //only play anything if
+ // - round is recognized
+ // - new music is to be played
if (currentRoundConfigKey != null) {
String currentPhaseName = "";
if (currentPhase != null) currentPhaseName = currentPhase.getName();
@@ -95,15 +99,15 @@ public class SoundContext {
}
}
}
- public void notifyOfPhase(PhaseI newPhase) {
- if (!newPhase.equals(currentPhase)) {
+ synchronized public void notifyOfPhase(PhaseI newPhase) {
+ if (newPhase != null && !newPhase.equals(currentPhase)) {
currentPhase = newPhase;
playBackgroundMusic();
}
}
- public void notifyOfRound(RoundI newRound) {
- if (!newRound.equals(currentRound)) {
+ synchronized public void notifyOfRound(RoundI newRound) {
+ if (newRound != null && !newRound.equals(currentRound)) {
//play stock market opening bell if stock round became current round
//and the round before was not
commit d6567259d5bee060e02f84393e1db655f8b13342
Author: Frederick Weld <fre...@gm...>
Date: Sun Feb 19 16:33:11 2012 +0100
Added caching of sound files (both sfx and background music)
diff --git a/rails/sound/SoundPlayer.java b/rails/sound/SoundPlayer.java
index be380d3..ecb60fb 100644
--- a/rails/sound/SoundPlayer.java
+++ b/rails/sound/SoundPlayer.java
@@ -4,7 +4,11 @@
package rails.sound;
import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
import java.io.FileInputStream;
+import java.util.HashMap;
+import java.util.Map;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.Player;
@@ -21,6 +25,23 @@ import javazoom.jl.player.advanced.AdvancedPlayer;
*/
public class SoundPlayer {
+ private class SoundFileBuffer {
+ private Map<String,byte[]> fileBuffer = new HashMap<String,byte[]>();
+ synchronized public BufferedInputStream getFileInputStream(String fileName) {
+ if (!fileBuffer.containsKey(fileName)) {
+ try {
+ long length = new File(fileName).length();
+ FileInputStream fis = new FileInputStream(fileName);
+ byte[] fileContent = new byte[(int)length];
+ fis.read(fileContent);
+ fileBuffer.put(fileName, fileContent);
+ } catch (Exception e) {return null;}
+ }
+ return new BufferedInputStream(
+ new ByteArrayInputStream(fileBuffer.get(fileName)));
+ }
+ }
+
private class PlayerThread extends Thread {
String fileName;
PlayerThread priorThread;
@@ -56,9 +77,7 @@ public class SoundPlayer {
}
public void play() {
try {
- FileInputStream fis = new FileInputStream(fileName);
- BufferedInputStream bis = new BufferedInputStream(fis);
- Player player = new Player(bis);
+ Player player = new Player(soundFileBuffer.getFileInputStream(fileName));
player.play();
player.close();
}
@@ -82,9 +101,8 @@ public class SoundPlayer {
@Override
public void play() {
try {
- FileInputStream fis = new FileInputStream(fileName);
- BufferedInputStream bis = new BufferedInputStream(fis);
- PortionPlayer player = new PortionPlayer(bis);
+ PortionPlayer player = new PortionPlayer(
+ soundFileBuffer.getFileInputStream(fileName));
player.play(startPos, endPos);
player.close();
}
@@ -137,9 +155,7 @@ public class SoundPlayer {
}
while (!isStopped) {
- FileInputStream fis = new FileInputStream(fileName);
- BufferedInputStream bis = new BufferedInputStream(fis);
- player = new Player(bis);
+ player = new Player(soundFileBuffer.getFileInputStream(fileName));
player.play();
player.close();
}
@@ -163,6 +179,8 @@ public class SoundPlayer {
private LoopPlayerThread lastBGMThread = null;
+ private SoundFileBuffer soundFileBuffer = new SoundFileBuffer();
+
/**
* atomic switching of the pointer to the last thread which played an sfx.
* @param newThread Player thread for the new sfx
|
|
From: Frederick W. <fre...@us...> - 2012-02-19 12:21:52
|
rails/ui/swing/ReportWindowDynamic.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
New commits:
commit 5467d59293b48a45470ccf779b84520040495ffa
Author: Frederick Weld <fre...@gm...>
Date: Sun Feb 19 13:19:39 2012 +0100
Fixed order of initing DynamicReportWindow (pack only after layout done)
Found out issue when running on other computer:
Report window gets zero size.
This commit fixes this issue which was traced back to a premature
call of super.init to the AbstractReportWindow's pack - dyn report
window only sets up layout afterwards (against EDT rules).
This is fixed by postponing the super.init call to the point in time
when the layout is ready.
diff --git a/rails/ui/swing/ReportWindowDynamic.java b/rails/ui/swing/ReportWindowDynamic.java
index 00daad2..df789f8 100644
--- a/rails/ui/swing/ReportWindowDynamic.java
+++ b/rails/ui/swing/ReportWindowDynamic.java
@@ -55,8 +55,6 @@ public class ReportWindowDynamic extends AbstractReportWindow implements Action
@Override
public void init() {
- super.init();
-
setLayout(new BorderLayout());
JPanel messagePanel = new JPanel();
@@ -142,6 +140,8 @@ public class ReportWindowDynamic extends AbstractReportWindow implements Action
);
buttonPanel.add(commentButton);
+ super.init();
+
}
@Override
|
|
From: Frederick W. <fre...@us...> - 2012-02-18 06:25:00
|
images/icon/notile_2towns.png |binary
images/icon/notile_station.png |binary
rails/ui/swing/SplashWindow.java | 1 +
3 files changed, 1 insertion(+)
New commits:
commit 3e53fe3344012e2c4ee3b1d10e2d1823224c4b00
Author: Frederick Weld <fre...@gm...>
Date: Sat Feb 18 07:23:36 2012 +0100
Added initial hexes (no-tile laid) for splash screen icon visualization
diff --git a/images/icon/notile_2towns.png b/images/icon/notile_2towns.png
new file mode 100644
index 0000000..84c0d63
Binary files /dev/null and b/images/icon/notile_2towns.png differ
diff --git a/images/icon/notile_station.png b/images/icon/notile_station.png
new file mode 100644
index 0000000..8a5987e
Binary files /dev/null and b/images/icon/notile_station.png differ
diff --git a/rails/ui/swing/SplashWindow.java b/rails/ui/swing/SplashWindow.java
index 8104a6d..ab5a3f8 100644
--- a/rails/ui/swing/SplashWindow.java
+++ b/rails/ui/swing/SplashWindow.java
@@ -108,6 +108,7 @@ public class SplashWindow {
private final static String iconPath = "/images/icon/";
private final static String[][] icons = new String[][] {
+ { "notile_2towns.png" , "notile_station.png" },
{ "yellow_track.png" , "yellow_station.png" },
{ "green_track.png" , "green_station.png" },
{ "russet_track.png" , "russet_station.png" },
|
|
From: Stefan F. <ste...@us...> - 2012-02-17 19:12:42
|
rails/algorithms/RevenueManager.java | 4
rails/common/GuiHints.java | 4
rails/game/Bank.java | 118 +--
rails/game/BaseToken.java | 1
rails/game/Certificate.java | 14
rails/game/Company.java | 24
rails/game/CompanyManager.java | 2
rails/game/Game.java | 3
rails/game/GameManager.java | 68 -
rails/game/MapHex.java | 10
rails/game/MapManager.java | 4
rails/game/OperatingRound.java | 48 -
rails/game/PhaseManager.java | 4
rails/game/Player.java | 175 +++-
rails/game/PlayerManager.java | 13
rails/game/PrivateCompany.java | 33
rails/game/PublicCertificate.java | 39 -
rails/game/PublicCompany.java | 45 -
rails/game/Round.java | 28
rails/game/ShareSellingRound.java | 6
rails/game/StartItem.java | 14
rails/game/StartRound.java | 6
rails/game/StartRoundI.java | 2
rails/game/StockMarket.java | 4
rails/game/StockRound.java | 28
rails/game/StockSpace.java | 2
rails/game/Tile.java | 6
rails/game/TileManager.java | 2
rails/game/Token.java | 23
rails/game/Train.java | 35
rails/game/TrainCertificateType.java | 4
rails/game/TrainManager.java | 4
rails/game/TreasuryShareRound.java | 12
rails/game/action/BuyCertificate.java | 10
rails/game/action/BuyTrain.java | 12
rails/game/correct/CashCorrectionManager.java | 8
rails/game/correct/CorrectionManager.java | 4
rails/game/model/AbstractOwnable.java | 46 -
rails/game/model/BaseTokensModel.java | 31
rails/game/model/BonusModel.java | 24
rails/game/model/CalculatedMoneyModel.java | 86 --
rails/game/model/CashModel.java | 85 --
rails/game/model/CashMoneyModel.java | 68 +
rails/game/model/CashOwner.java | 8
rails/game/model/CertificateCountModel.java | 32
rails/game/model/CertificatesModel.java | 80 --
rails/game/model/DirectCashOwner.java | 33
rails/game/model/DirectOwner.java | 45 -
rails/game/model/Model.java | 47 -
rails/game/model/MoneyModel.java | 168 ++--
rails/game/model/Ownable.java | 19
rails/game/model/Owner.java | 28
rails/game/model/Owners.java | 75 --
rails/game/model/Portfolio.java | 648 ------------------
rails/game/model/PortfolioCashOwner.java | 28
rails/game/model/PortfolioModel.java | 629 +++++++++++++++++
rails/game/model/PortfolioOwner.java | 39 -
rails/game/model/PresidentModel.java | 16
rails/game/model/PriceModel.java | 15
rails/game/model/PrivatesModel.java | 41 +
rails/game/model/SingleOwner.java | 63 -
rails/game/model/Storage.java | 37 -
rails/game/model/StorageModel.java | 109 ---
rails/game/model/TrainsModel.java | 50 -
rails/game/special/SpecialProperty.java | 4
rails/game/special/SpecialPropertyI.java | 3
rails/game/specific/_1825/StockRound_1825.java | 6
rails/game/specific/_1835/OperatingRound_1835.java | 6
rails/game/specific/_1835/PrussianFormationRound.java | 6
rails/game/specific/_1835/StockRound_1835.java | 4
rails/game/specific/_1856/CGRFormationRound.java | 13
rails/game/specific/_1856/OperatingRound_1856.java | 8
rails/game/specific/_1856/StockRound_1856.java | 4
rails/game/specific/_1880/StartRound_1880.java | 2
rails/game/specific/_1889/OperatingRound_1889.java | 2
rails/game/specific/_18AL/OperatingRound_18AL.java | 4
rails/game/specific/_18EU/GameManager_18EU.java | 7
rails/game/specific/_18EU/OperatingRound_18EU.java | 10
rails/game/specific/_18EU/StockRound_18EU.java | 16
rails/game/state/AbstractItem.java | 76 ++
rails/game/state/ArrayListMultimapState.java | 25
rails/game/state/ArrayListState.java | 30
rails/game/state/BooleanState.java | 28
rails/game/state/ChangeStack.java | 22
rails/game/state/Context.java | 180 ++---
rails/game/state/CountableItem.java | 6
rails/game/state/GameItem.java | 73 --
rails/game/state/GenericState.java | 29
rails/game/state/HashMapState.java | 36 -
rails/game/state/HashMultimapState.java | 28
rails/game/state/HashSetState.java | 47 -
rails/game/state/IntegerState.java | 35
rails/game/state/Item.java | 25
rails/game/state/ItemType.java | 5
rails/game/state/Model.java | 42 +
rails/game/state/MultimapState.java | 4
rails/game/state/Observable.java | 26
rails/game/state/OwnableItem.java | 13
rails/game/state/Portfolio.java | 55 +
rails/game/state/PortfolioChange.java | 8
rails/game/state/PortfolioList.java | 71 +
rails/game/state/PortfolioManager.java | 20
rails/game/state/PortfolioMap.java | 100 ++
rails/game/state/PortfolioNG.java | 117 ---
rails/game/state/Root.java | 88 ++
rails/game/state/State.java | 73 --
rails/game/state/StateManager.java | 53 -
rails/game/state/StringState.java | 30
rails/game/state/Wallet.java | 29
rails/game/state/WalletManager.java | 15
rails/ui/swing/GameStatus.java | 6
rails/ui/swing/GridPanel.java | 2
rails/ui/swing/ORUIManager.java | 6
rails/ui/swing/RemainingTilesWindow.java | 2
rails/ui/swing/elements/GUIStockSpace.java | 2
rails/ui/swing/hexmap/GUIHex.java | 2
116 files changed, 2151 insertions(+), 2722 deletions(-)
New commits:
commit 0a640b489db8e119f3567e6eb4e5267772562fee
Author: Stefan Frey <ste...@we...>
Date: Mon Feb 13 18:52:12 2012 +0100
Updated Item and Context mechanisms
Removing the previous storage and owner mechanism
Refactored StateManager and ChangeStack mechanisms
Refactored MoneyModel, CashModel and CalculatedMoneyModel
Refactored Player, Bank
diff --git a/rails/algorithms/RevenueManager.java b/rails/algorithms/RevenueManager.java
index 06c506f..bfba854 100644
--- a/rails/algorithms/RevenueManager.java
+++ b/rails/algorithms/RevenueManager.java
@@ -12,7 +12,7 @@ import rails.common.parser.ConfigurableComponentI;
import rails.common.parser.ConfigurationException;
import rails.common.parser.Tag;
import rails.game.GameManager;
-import rails.game.state.GameItem;
+import rails.game.state.AbstractItem;
import rails.game.state.ArrayListState;
/**
@@ -25,7 +25,7 @@ import rails.game.state.ArrayListState;
*
*/
-public final class RevenueManager extends GameItem implements ConfigurableComponentI {
+public final class RevenueManager extends AbstractItem implements ConfigurableComponentI {
protected static Logger log =
Logger.getLogger(RevenueManager.class.getPackage().getName());
diff --git a/rails/common/GuiHints.java b/rails/common/GuiHints.java
index 64d8dde..b386bc8 100644
--- a/rails/common/GuiHints.java
+++ b/rails/common/GuiHints.java
@@ -5,7 +5,7 @@ import java.util.ArrayList;
import java.util.List;
import rails.game.RoundI;
-import rails.game.state.GameItem;
+import rails.game.state.AbstractItem;
import rails.game.state.GenericState;
/**
@@ -16,7 +16,7 @@ import rails.game.state.GenericState;
* @author VosE
*
*/
-public class GuiHints extends GameItem implements Serializable{
+public class GuiHints extends AbstractItem implements Serializable{
public static final long serialVersionUID = 1L;
diff --git a/rails/game/Bank.java b/rails/game/Bank.java
index e35d100..5bf426a 100644
--- a/rails/game/Bank.java
+++ b/rails/game/Bank.java
@@ -9,14 +9,18 @@ import rails.common.parser.Config;
import rails.common.parser.ConfigurableComponentI;
import rails.common.parser.ConfigurationException;
import rails.common.parser.Tag;
-import rails.game.model.CashModel;
+import rails.game.model.CashMoneyModel;
import rails.game.model.CashOwner;
+import rails.game.model.MoneyModel;
import rails.game.model.PortfolioModel;
-import rails.game.state.GameItem;
+import rails.game.state.AbstractItem;
import rails.game.state.BooleanState;
+import rails.game.state.Item;
import rails.util.*;
-public class Bank extends GameItem implements CashOwner, ConfigurableComponentI {
+public class Bank extends AbstractItem implements CashOwner, ConfigurableComponentI {
+
+ private static Bank instance = null;
/** Specific portfolio names */
public static final String IPO_NAME = "IPO";
@@ -29,21 +33,19 @@ public class Bank extends GameItem implements CashOwner, ConfigurableComponentI
private static final String DEFAULT_MONEY_FORMAT = "$@";
/** The Bank's amount of cash */
- private CashModel money;
+ private final CashMoneyModel cash;
/** The IPO */
- private PortfolioModel ipo = null;
+ private final PortfolioModel ipo;
/** The Bank Pool */
- private PortfolioModel pool = null;
+ private final PortfolioModel pool;
/** Collection of items that will (may) become available in the future */
- private PortfolioModel unavailable = null;
+ private final PortfolioModel unavailable;
/** Collection of items that have been discarded (but are kept to allow Undo) */
- private PortfolioModel scrapHeap = null;
-
- private static Bank instance = null;
+ private final PortfolioModel scrapHeap;
- /** Is the bank broken (remains true once set) */
- private BooleanState broken = BooleanState.create(this, "Bank.broken", false);
+ /** Is the bank broken */
+ private final BooleanState broken;
/**
* The money format template. '@' is replaced by the numeric amount, the
@@ -55,22 +57,40 @@ public class Bank extends GameItem implements CashOwner, ConfigurableComponentI
Logger.getLogger(Bank.class.getPackage().getName());
public Bank() {
+ super(Bank.class.getSimpleName());
instance = this;
- money = CashModel.create(this);
+ cash = MoneyModel.createCash("cash");
+
// Create the IPO and the Bank Pool.
- ipo = new PortfolioModel(ipo, IPO_NAME);
- pool = new PortfolioModel(pool, POOL_NAME);
- unavailable = new PortfolioModel(unavailable, UNAVAILABLE_NAME);
- scrapHeap = new PortfolioModel(scrapHeap, SCRAPHEAP_NAME);
+ ipo = PortfolioModel.create(IPO_NAME);
+ pool = PortfolioModel.create(POOL_NAME);
+ unavailable = PortfolioModel.create(UNAVAILABLE_NAME);
+ scrapHeap = PortfolioModel.create(SCRAPHEAP_NAME);
+ broken = BooleanState.create("broken");
+
String configFormat = Config.get("money_format");
if (Util.hasValue(configFormat) && configFormat.matches(".*@.*")) {
moneyFormat = configFormat;
}
}
+ @Override
+ public Bank init(Item parent) {
+ super.init(parent);
+
+ cash.init(this);
+ ipo.init(this);
+ pool.init(this);
+ unavailable.init(this);
+ scrapHeap.init(this);
+ broken.init(this);
+
+ return this;
+ }
+
/**
* @see rails.common.parser.ConfigurableComponentI#configureFromXML(org.w3c.dom.Element)
*/
@@ -94,7 +114,7 @@ public class Bank extends GameItem implements CashOwner, ConfigurableComponentI
Tag bankTag = tag.getChild("Bank");
if (bankTag != null) {
- money.set(bankTag.getAttributeAsInteger("amount",
+ cash.set(bankTag.getAttributeAsInteger("amount",
DEFAULT_BANK_AMOUNT));
}
@@ -103,7 +123,7 @@ public class Bank extends GameItem implements CashOwner, ConfigurableComponentI
public void finishConfiguration (GameManager gameManager) {
ReportBuffer.add(LocalText.getText("BankSizeIs",
- format(money.value())));
+ format(cash.value())));
// Add privates
List<PrivateCompany> privates =
@@ -118,9 +138,9 @@ public class Bank extends GameItem implements CashOwner, ConfigurableComponentI
for (PublicCompany comp : companies) {
for (PublicCertificate cert : comp.getCertificates()) {
if (cert.isInitiallyAvailable()) {
- cert.moveTo(ipo);
+ ipo.moveInto(cert);
} else {
- cert.moveTo(unavailable);
+ unavailable.moveInto(cert);
}
}
}
@@ -137,30 +157,15 @@ public class Bank extends GameItem implements CashOwner, ConfigurableComponentI
return scrapHeap;
}
- /**
- * @return Bank's current cash level
- */
- public int getCashValue() {
- return money.value();
- }
-
- /**
- * Adds cash back to the bank
- */
- public void addCash(int amount) {
-
- money.add(amount);
-
- /*
+ /* FIXME: Add broken check somewhere
* Check if the bank has broken. In some games <0 could apply, so this
* will become configurable.
- */
- if (money.value() <= 0 && !broken.booleanValue()) {
+ if (cash.value() <= 0 && !broken.booleanValue()) {
broken.set(true);
- money.setText(LocalText.getText("BROKEN"));
+ cash.setText(LocalText.getText("BROKEN"));
GameManager.getInstance().registerBrokenBank();
}
- }
+ */
/**
* @return Portfolio of stock in Bank Pool
@@ -176,19 +181,13 @@ public class Bank extends GameItem implements CashOwner, ConfigurableComponentI
return unavailable;
}
- /**
- * @param Set Bank's cash.
- */
- public void setCash(int i) {
- money.set(i);
- }
-
public String getId() {
return LocalText.getText("BANK");
}
- public String getFormattedCash() {
- return money.getText();
+ // CashOwner interface
+ public CashMoneyModel getCash() {
+ return cash;
}
public static String format(int amount) {
@@ -198,7 +197,7 @@ public class Bank extends GameItem implements CashOwner, ConfigurableComponentI
if (amount < 0) result = result.replaceFirst("(.+)-", "-$1");
return result;
}
- // start sfy 1889 for integerarrays
+
public static String formatIntegerArray(int[] amountList) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < amountList.length;++i) {
@@ -207,14 +206,5 @@ public class Bank extends GameItem implements CashOwner, ConfigurableComponentI
}
return result.toString();
}
- // end sfy 1889
-
- public int getCash() {
- return money.value();
- }
-
- public CashModel getCashModel() {
- return money;
- }
}
diff --git a/rails/game/BaseToken.java b/rails/game/BaseToken.java
index bba6edd..2c879b1 100644
--- a/rails/game/BaseToken.java
+++ b/rails/game/BaseToken.java
@@ -24,6 +24,7 @@ public class BaseToken extends Token {
this.company = company;
/* Initially. a BaseToken is always owned by a company. */
+ company.getBaseTokensModel().
this.moveTo(company);
}
diff --git a/rails/game/Company.java b/rails/game/Company.java
index b9175b4..2156e53 100644
--- a/rails/game/Company.java
+++ b/rails/game/Company.java
@@ -14,11 +14,11 @@ import rails.game.model.StorageModel;
import rails.game.model.PortfolioModel;
import rails.game.special.SpecialPropertyI;
import rails.game.state.BooleanState;
-import rails.game.state.GameItem;
+import rails.game.state.AbstractItem;
import rails.game.state.OwnableItem;
import rails.util.Util;
-public abstract class Company extends GameItem implements ConfigurableComponentI,
+public abstract class Company extends AbstractItem implements ConfigurableComponentI,
Cloneable, Comparable<Company> {
/** The name of the XML tag used to configure a company. */
diff --git a/rails/game/CompanyManager.java b/rails/game/CompanyManager.java
index 25f946a..5a00ee5 100644
--- a/rails/game/CompanyManager.java
+++ b/rails/game/CompanyManager.java
@@ -1 +1 @@
-package rails.game;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import rails.common.LocalText;
import rails.common.parser.ConfigurableComponentI;
import rails.common.parser.ConfigurationException;
import rails.common.parser.Tag;
import rails.game.state.GameItem;
public class CompanyManager extends GameItem implements CompanyManagerI, ConfigurableComponentI {
/** A List with all private companies */
private List<PrivateCompany> lPrivateCompanies =
new ArrayList<PrivateCompany>();
/** A List with all public companies */
private List<PublicCompany> lPublicCompanies =
new ArrayList<PublicCompany>();
/** A map with all private companies by name */
private Map<String, PrivateCompany> mPrivateCompanies =
new HashMap<String, PrivateCompany>();
/** A map with all public (i.e. non-private) companies by name */
private Map<String, PublicCompany> mPublicCompanies =
new HashMap<String, PublicCompany>();
/** A map of all type names to maps of companies of that type by name */
// TODO Redundant, current usage can be replaced.
private Map<String, Map<String, Company>> mCompaniesByTypeAndName =
new HashMap<String, Map<String, Company>>();
/** A list of all company types */
private List<CompanyTypeI> lCompanyTypes = new ArrayList<CompanyTypeI>();
/** A list of all start packets (usually one) */
private List<StartPacket> startPackets = new ArrayList<StartPacket>();
/** A map of all start packets, keyed by name. Default name is "Initial" */
private Map<String, StartPacket> startPacketMap
= new HashMap<String, StartPacket>();
/** A map to enable translating aliases to names */
protected Map<String, String> aliases = null;
private int numberOfPublicCompanies = 0;
protected static Logger log =
Logger.getLogger(CompanyManager.class.getPackage().getName());
protected Game |
|
From: Frederick W. <fre...@us...> - 2012-02-17 17:32:42
|
LocalisedText.properties | 17 +
data/Properties.xml | 1
data/profiles/default.profile | 2
data/profiles/root.profile | 1
images/icon/green_station.png |binary
images/icon/green_track.png |binary
images/icon/grey_station.png |binary
images/icon/grey_track.png |binary
images/icon/russet_station.png |binary
images/icon/russet_track.png |binary
images/icon/yellow_station.png |binary
images/icon/yellow_track.png |binary
rails/game/GameManager.java | 13 -
rails/ui/swing/AbstractReportWindow.java | 9
rails/ui/swing/ConfigWindow.java | 11
rails/ui/swing/GameSetupWindow.java | 63 +++--
rails/ui/swing/GameUIManager.java | 99 +++++++-
rails/ui/swing/ORWindow.java | 48 ++--
rails/ui/swing/SplashWindow.java | 356 ++++++++++++++++++++++++++++++
rails/ui/swing/StartRoundWindow.java | 10
rails/ui/swing/StatusWindow.java | 10
rails/ui/swing/StockChart.java | 10
rails/ui/swing/elements/DockingFrame.java | 6
rails/util/RunGame.java | 19 -
24 files changed, 582 insertions(+), 93 deletions(-)
New commits:
commit 0dd7547b2f850ea7e6e5b5c7ccf01c846ab5898c
Author: Frederick Weld <fre...@gm...>
Date: Fri Feb 17 18:30:28 2012 +0100
Added splash screen option to the root profile
Default is on. Prior behavior cannot be restored anyway as the option
only triggers whether the splash screen appears (and not whether
window popup is occurs prematurely).
diff --git a/data/profiles/root.profile b/data/profiles/root.profile
index a553e4c..3e08d4d 100644
--- a/data/profiles/root.profile
+++ b/data/profiles/root.profile
@@ -34,6 +34,7 @@ or.window.dockablePanels=no
report.window.type=dynamic
report.window.open=yes
report.window.editable=no
+splash.window.open=yes
stockchart.window.open=yes
### Panel Format
commit 2d3fd85bfff93e46f42125bdc6fafd13bfd11e6c
Author: Frederick Weld <fre...@gm...>
Date: Fri Feb 17 17:55:22 2012 +0100
Visualized game initializing progress (splash) by tile upgrades
Reused http://rails.sourceforge.net/ icons for this purpose.
diff --git a/images/icon/green_station.png b/images/icon/green_station.png
new file mode 100644
index 0000000..993e4f0
Binary files /dev/null and b/images/icon/green_station.png differ
diff --git a/images/icon/green_track.png b/images/icon/green_track.png
new file mode 100644
index 0000000..3d79ec5
Binary files /dev/null and b/images/icon/green_track.png differ
diff --git a/images/icon/grey_station.png b/images/icon/grey_station.png
new file mode 100644
index 0000000..9597307
Binary files /dev/null and b/images/icon/grey_station.png differ
diff --git a/images/icon/grey_track.png b/images/icon/grey_track.png
new file mode 100644
index 0000000..6c498f3
Binary files /dev/null and b/images/icon/grey_track.png differ
diff --git a/images/icon/russet_station.png b/images/icon/russet_station.png
new file mode 100644
index 0000000..625bcea
Binary files /dev/null and b/images/icon/russet_station.png differ
diff --git a/images/icon/russet_track.png b/images/icon/russet_track.png
new file mode 100644
index 0000000..acddde2
Binary files /dev/null and b/images/icon/russet_track.png differ
diff --git a/images/icon/yellow_station.png b/images/icon/yellow_station.png
new file mode 100644
index 0000000..0bc7f8c
Binary files /dev/null and b/images/icon/yellow_station.png differ
diff --git a/images/icon/yellow_track.png b/images/icon/yellow_track.png
new file mode 100644
index 0000000..1034612
Binary files /dev/null and b/images/icon/yellow_track.png differ
diff --git a/rails/ui/swing/SplashWindow.java b/rails/ui/swing/SplashWindow.java
index 618e677..8104a6d 100644
--- a/rails/ui/swing/SplashWindow.java
+++ b/rails/ui/swing/SplashWindow.java
@@ -11,6 +11,7 @@ import java.util.List;
import java.util.Set;
import javax.swing.BoxLayout;
+import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
@@ -38,33 +39,33 @@ public class SplashWindow {
/**
* in millisecs
*/
- private static long PROGRESS_UPDATE_INTERVAL = 200;
+ private final static long PROGRESS_UPDATE_INTERVAL = 200;
- private static String DUMMY_STEP_BEFORE_START = "-1";
- private static String DUMMY_STEP_START = "0";
- private static String DUMMY_STEP_END = "inf";
+ private final static String DUMMY_STEP_BEFORE_START = "-1";
+ private final static String DUMMY_STEP_START = "0";
+ private final static String DUMMY_STEP_END = "inf";
- public static String STEP_LOAD_GAME = "Splash.step.loadGame";
- public static String STEP_INIT_UI = "Splash.step.initUI";
- public static String STEP_STOCK_CHART = "Splash.step.stockChart";
- public static String STEP_REPORT_WINDOW = "Splash.step.reportWindow";
- public static String STEP_OR_INIT_DOCKING_FRAME = "Splash.step.or.initDockingFrame";
- public static String STEP_OR_INIT_PANELS = "Splash.step.or.initPanels";
- public static String STEP_OR_INIT_TILES = "Splash.step.or.initTiles";
- public static String STEP_OR_APPLY_DOCKING_FRAME = "Splash.step.or.applyDockingFrame";
- public static String STEP_STATUS_WINDOW = "Splash.step.statusWindow";
- public static String STEP_INIT_NEW_GAME = "Splash.step.initNewGame";
- public static String STEP_CONFIG_WINDOW = "Splash.step.configWindow";
- public static String STEP_INIT_SOUND = "Splash.step.initSound";
- public static String STEP_INIT_LOADED_GAME = "Splash.step.initLoadedGame";
- public static String STEP_FINALIZE = "Splash.step.finalize";
+ public final static String STEP_LOAD_GAME = "Splash.step.loadGame";
+ public final static String STEP_INIT_UI = "Splash.step.initUI";
+ public final static String STEP_STOCK_CHART = "Splash.step.stockChart";
+ public final static String STEP_REPORT_WINDOW = "Splash.step.reportWindow";
+ public final static String STEP_OR_INIT_DOCKING_FRAME = "Splash.step.or.initDockingFrame";
+ public final static String STEP_OR_INIT_PANELS = "Splash.step.or.initPanels";
+ public final static String STEP_OR_INIT_TILES = "Splash.step.or.initTiles";
+ public final static String STEP_OR_APPLY_DOCKING_FRAME = "Splash.step.or.applyDockingFrame";
+ public final static String STEP_STATUS_WINDOW = "Splash.step.statusWindow";
+ public final static String STEP_INIT_NEW_GAME = "Splash.step.initNewGame";
+ public final static String STEP_CONFIG_WINDOW = "Splash.step.configWindow";
+ public final static String STEP_INIT_SOUND = "Splash.step.initSound";
+ public final static String STEP_INIT_LOADED_GAME = "Splash.step.initLoadedGame";
+ public final static String STEP_FINALIZE = "Splash.step.finalize";
- private static List<String> STEP_GROUP_LOAD = Arrays.asList(new String[] {
+ private final static List<String> STEP_GROUP_LOAD = Arrays.asList(new String[] {
STEP_LOAD_GAME,
STEP_INIT_LOADED_GAME
});
- private static List<String> STEP_GROUP_DOCKING_LAYOUT = Arrays.asList(new String[] {
+ private final static List<String> STEP_GROUP_DOCKING_LAYOUT = Arrays.asList(new String[] {
STEP_OR_INIT_DOCKING_FRAME,
STEP_OR_INIT_TILES,
STEP_OR_APPLY_DOCKING_FRAME,
@@ -78,7 +79,7 @@ public class SplashWindow {
this.labelConfigKey = labelConfigKey;
}
}
- private static StepDuration[] stepDuration = {
+ private final static StepDuration[] stepDuration = {
new StepDuration ( 0, DUMMY_STEP_BEFORE_START), // used to facilitate array border handling
new StepDuration ( 0, DUMMY_STEP_START), // used to facilitate array border handling
new StepDuration ( 6000, STEP_LOAD_GAME ),
@@ -97,15 +98,22 @@ public class SplashWindow {
new StepDuration ( 1000, STEP_FINALIZE),
new StepDuration ( 0, DUMMY_STEP_END), // used to facilitate array border handling
};
-
+
private long totalDuration = 0;
private long[] cumulativeDuration = null;
private Set<JFrame> framesRegisteredAsVisible = new HashSet<JFrame>();
private List<JFrame> framesRegisteredToFront = new ArrayList<JFrame>();
- private static Dimension iconSize = new Dimension(90,78);
-
+ private final static String iconPath = "/images/icon/";
+
+ private final static String[][] icons = new String[][] {
+ { "yellow_track.png" , "yellow_station.png" },
+ { "green_track.png" , "green_station.png" },
+ { "russet_track.png" , "russet_station.png" },
+ { "grey_track.png" , "grey_station.png" }
+ };
+
private JWindow myWin = null;
private JLabel leftIcon = null;
private JLabel rightIcon = null;
@@ -114,7 +122,8 @@ public class SplashWindow {
private ProgressVisualizer progressVisualizer = null;
- private int currentStep = 1; //the start step
+ private int currentStep = 0;
+ private int currentIconIndex = 0;
public SplashWindow(boolean isLoad, String initDetailsText) {
//quit directly when no visualization required
@@ -139,16 +148,19 @@ public class SplashWindow {
myWin = new JWindow();
leftIcon = new JLabel();
- leftIcon.setPreferredSize(iconSize);
+ setIcon(leftIcon,icons[currentIconIndex][0]);
+ leftIcon.setBorder(new CompoundBorder(new EmptyBorder(5,5,5,5),new EtchedBorder()));
rightIcon = new JLabel();
- rightIcon.setPreferredSize(iconSize);
+ setIcon(rightIcon,icons[currentIconIndex][1]);
+ rightIcon.setBorder(new CompoundBorder(new EmptyBorder(5,5,5,5),new EtchedBorder()));
progressBar = new JProgressBar(0,(int)totalDuration);
progressBar.setStringPainted(true);
progressBar.setMinimum(0);
- stepLabel = new JLabel();
+ stepLabel = new JLabel(" "); // needed in order to allocate vertical space
stepLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+ stepLabel.setBorder(new EmptyBorder(5,5,5,5));
//set up static elements
@@ -160,7 +172,7 @@ public class SplashWindow {
String commandTextKey = isLoad ? "Splash.command.loadGame" : "Splash.command.newGame";
JLabel commandLabel = new JLabel(
LocalText.getText(commandTextKey,initDetailsText));
- commandLabel.setFont(commandLabel.getFont().deriveFont(Font.ITALIC));
+ commandLabel.setFont(commandLabel.getFont().deriveFont(Font.BOLD));
commandLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
//plug elements together and set up layout
@@ -169,12 +181,14 @@ public class SplashWindow {
railsCommandPanel.setLayout(new BoxLayout(railsCommandPanel, BoxLayout.Y_AXIS));
railsCommandPanel.add(railsLabel);
railsCommandPanel.add(commandLabel);
+ railsCommandPanel.setBorder(new EmptyBorder(3,3,3,3));
JPanel idPanel = new JPanel();
idPanel.setLayout(new BoxLayout(idPanel, BoxLayout.X_AXIS));
idPanel.add(leftIcon);
idPanel.add(railsCommandPanel);
idPanel.add(rightIcon);
+ idPanel.setBorder(new EmptyBorder(3,3,3,3));
JComponent contentPane = (JComponent)myWin.getContentPane();
contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
@@ -201,7 +215,7 @@ public class SplashWindow {
} catch (Exception e) {}
progressVisualizer = new ProgressVisualizer();
- progressVisualizer.setCurrentStep(currentStep);
+ notifyOfStep(DUMMY_STEP_START);
progressVisualizer.start();
}
@@ -218,10 +232,10 @@ public class SplashWindow {
}
/**
- * @param elapsedDuration Refers to a duration normalized based on the expected durations
+ * @param elapsedTime Refers to a duration normalized based on the expected durations
* of the process steps.
*/
- synchronized private void visualizeProgress(long elapsedDuration, int currentStep) {
+ synchronized private void visualizeProgress(long elapsedTime, int currentStep) {
//update current step (including description)
if (currentStep != this.currentStep) {
this.currentStep = currentStep;
@@ -232,13 +246,32 @@ public class SplashWindow {
}
}
+ //update icon
+ int newIconIndex = (int)(icons.length * elapsedTime / totalDuration);
+ newIconIndex = Math.max( Math.min(icons.length-1 , newIconIndex) , 0);
+ if (newIconIndex != currentIconIndex) {
+ currentIconIndex = newIconIndex;
+ setIcon(leftIcon,icons[newIconIndex][0]);
+ setIcon(rightIcon,icons[newIconIndex][1]);
+ }
+
//show progress
- progressBar.setValue((int)elapsedDuration);
+ progressBar.setValue((int)elapsedTime);
//ensure visibility of window
myWin.toFront();
}
+ private void setIcon(JLabel iconLabel, String iconFileName) {
+ String path = iconPath + iconFileName;
+ java.net.URL imgURL = getClass().getResource(path);
+ if (imgURL != null) {
+ iconLabel.setIcon(new ImageIcon(imgURL));
+ } else {
+ System.err.println("Couldn't find file: " + path);
+ }
+ }
+
/**
* Remembers that this frame is to be put to visible at the end of the splash process
*/
commit 682539e88405e444c60fc0bc8649ed43c7c40dbd
Author: Frederick Weld <fre...@gm...>
Date: Fri Feb 17 17:25:17 2012 +0100
Added texts for game init steps (displayed in progress bar)
diff --git a/LocalisedText.properties b/LocalisedText.properties
index d5f8f37..ac4899b 100644
--- a/LocalisedText.properties
+++ b/LocalisedText.properties
@@ -642,6 +642,20 @@ SoldOutNoRaise={0} is sold out, but price stays at {1}({2})
SPECIAL=Special
Splash.command.loadGame=Loading Game: {0}
Splash.command.newGame=Starting New Game: {0}
+Splash.step.loadGame=Replaying game...
+Splash.step.initUI=Initializing user interface...
+Splash.step.stockChart=Building stock chart...
+Splash.step.reportWindow=Building report window...
+Splash.step.or.initDockingFrame=Initializing docking framework for flexible panels...
+Splash.step.or.initPanels=Building operating round window...
+Splash.step.or.initTiles=Initializing tiles...
+Splash.step.or.applyDockingFrame=Applying docking framework to operating round window...
+Splash.step.statusWindow=Building status window...
+Splash.step.initNewGame=Initializing new game...
+Splash.step.configWindow=Building configuration window...
+Splash.step.initSound=Initializing sound...
+Splash.step.initLoadedGame=Initializing loaded game...
+Splash.step.finalize=Finalizing...
SPLIT=Split
SRHelpText=Stock round help text goes here.
START_COMPANY={0} starts {1} at {2}.
diff --git a/rails/ui/swing/ORWindow.java b/rails/ui/swing/ORWindow.java
index 68f2ce5..89d037f 100644
--- a/rails/ui/swing/ORWindow.java
+++ b/rails/ui/swing/ORWindow.java
@@ -191,10 +191,6 @@ public class ORWindow extends DockingFrame implements ActionPerformer {
if (isDockingFrameworkEnabled()) {
initLayout();
-
- //trigger early painting in order to parallelize OR window setup
- //with other setup activities
- repaint();
}
}
});
diff --git a/rails/ui/swing/SplashWindow.java b/rails/ui/swing/SplashWindow.java
index 0d6ebdb..618e677 100644
--- a/rails/ui/swing/SplashWindow.java
+++ b/rails/ui/swing/SplashWindow.java
@@ -88,7 +88,7 @@ public class SplashWindow {
new StepDuration ( 2600, STEP_OR_INIT_DOCKING_FRAME ),
new StepDuration ( 1650, STEP_OR_INIT_PANELS ),
new StepDuration ( 5000, STEP_OR_INIT_TILES ),
- new StepDuration ( 1000, STEP_OR_APPLY_DOCKING_FRAME ),
+ new StepDuration ( 3000, STEP_OR_APPLY_DOCKING_FRAME ),
new StepDuration ( 400, STEP_STATUS_WINDOW ),
new StepDuration ( 300, STEP_INIT_NEW_GAME ),
new StepDuration ( 1200, STEP_CONFIG_WINDOW ),
@@ -214,6 +214,7 @@ public class SplashWindow {
progressVisualizer.setCurrentStep(i);
}
}
+
}
/**
@@ -226,29 +227,19 @@ public class SplashWindow {
this.currentStep = currentStep;
//only display step description for non-dummy steps
if (stepDuration[currentStep].expectedDurationInMillis > 0) {
- stepLabel.setText(stepDuration[currentStep].labelConfigKey);
- enforeGUIUpdate(stepLabel);
+ stepLabel.setText(LocalText.getText(
+ stepDuration[currentStep].labelConfigKey));
}
}
//show progress
progressBar.setValue((int)elapsedDuration);
- enforeGUIUpdate(progressBar);
//ensure visibility of window
myWin.toFront();
}
/**
- * ensure that progress is updated even if EDT is very busy
- * CAUTION: paintImmediately is called outside of EDT
- * works but not guideline-conform
- */
- private void enforeGUIUpdate(JComponent c) {
- c.paintImmediately(c.getBounds());
- }
-
- /**
* Remembers that this frame is to be put to visible at the end of the splash process
*/
public void registerFrameForDeferredVisibility(JFrame frame,boolean setToVisible) {
commit 116db12ebbaceffb1e5f112bfb3bd9c55a2d96d2
Author: Frederick Weld <fre...@gm...>
Date: Fri Feb 17 17:13:01 2012 +0100
Added splash screen label for init operation
New label indicates "Starting New Game: xyz" or "Loading Game: xyz".
diff --git a/LocalisedText.properties b/LocalisedText.properties
index ee7f6f5..d5f8f37 100644
--- a/LocalisedText.properties
+++ b/LocalisedText.properties
@@ -640,6 +640,8 @@ SharesPutInTreasury=The remaining {0}% shares of {1} are put in its treasury
SoldOut={0} is sold out, price rises from {1}({2}) to {3}({4})
SoldOutNoRaise={0} is sold out, but price stays at {1}({2})
SPECIAL=Special
+Splash.command.loadGame=Loading Game: {0}
+Splash.command.newGame=Starting New Game: {0}
SPLIT=Split
SRHelpText=Stock round help text goes here.
START_COMPANY={0} starts {1} at {2}.
diff --git a/rails/ui/swing/GameSetupWindow.java b/rails/ui/swing/GameSetupWindow.java
index 6a633a9..4d7e73d 100644
--- a/rails/ui/swing/GameSetupWindow.java
+++ b/rails/ui/swing/GameSetupWindow.java
@@ -228,7 +228,7 @@ public class GameSetupWindow extends JDialog implements ActionListener {
*/
private void loadAndStartGame(String filePath, String saveDirectory) {
prepareGameUIInit();
- SplashWindow splashWindow = new SplashWindow(true);
+ SplashWindow splashWindow = new SplashWindow(true,filePath);
splashWindow.notifyOfStep(SplashWindow.STEP_LOAD_GAME);
if ((game = Game.load(filePath)) == null) {
JOptionPane.showMessageDialog(this,
@@ -500,7 +500,12 @@ public class GameSetupWindow extends JDialog implements ActionListener {
}
}
- game = new Game(this.getSelectedGameInfo().getName(), playerNames, selectedOptions);
+ String gameName = getSelectedGameInfo().getName();
+
+ SplashWindow splashWindow = new SplashWindow(false,gameName);
+
+ game = new Game(gameName, playerNames, selectedOptions);
+
if (!game.setup()) {
JOptionPane.showMessageDialog(this, DisplayBuffer.get(), "",
JOptionPane.ERROR_MESSAGE);
@@ -517,7 +522,6 @@ public class GameSetupWindow extends JDialog implements ActionListener {
System.exit(-1);
}
prepareGameUIInit();
- SplashWindow splashWindow = new SplashWindow(false);
startGameUIManager (game, false, splashWindow);
gameUIManager.gameUIInit(true); // true indicates new game
completeGameUIInit(splashWindow);
diff --git a/rails/ui/swing/SplashWindow.java b/rails/ui/swing/SplashWindow.java
index 1e1201e..0d6ebdb 100644
--- a/rails/ui/swing/SplashWindow.java
+++ b/rails/ui/swing/SplashWindow.java
@@ -2,6 +2,7 @@ package rails.ui.swing;
import java.awt.Component;
import java.awt.Dimension;
+import java.awt.Font;
import java.awt.Toolkit;
import java.util.ArrayList;
import java.util.Arrays;
@@ -21,6 +22,7 @@ import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.EtchedBorder;
+import rails.common.LocalText;
import rails.common.parser.Config;
import rails.game.Game;
@@ -114,7 +116,7 @@ public class SplashWindow {
private int currentStep = 1; //the start step
- public SplashWindow(boolean isLoad) {
+ public SplashWindow(boolean isLoad, String initDetailsText) {
//quit directly when no visualization required
//all visualization related attributes remain null then
if ("no".equals(Config.get("splash.window.open"))) return;
@@ -155,7 +157,10 @@ public class SplashWindow {
(float)2.0 * railsLabel.getFont().getSize()));
railsLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
- JLabel commandLabel = new JLabel("Setting up new game / loading game");
+ String commandTextKey = isLoad ? "Splash.command.loadGame" : "Splash.command.newGame";
+ JLabel commandLabel = new JLabel(
+ LocalText.getText(commandTextKey,initDetailsText));
+ commandLabel.setFont(commandLabel.getFont().deriveFont(Font.ITALIC));
commandLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
//plug elements together and set up layout
diff --git a/rails/util/RunGame.java b/rails/util/RunGame.java
index 8206c25..3c08442 100644
--- a/rails/util/RunGame.java
+++ b/rails/util/RunGame.java
@@ -49,11 +49,12 @@ public class RunGame {
static void loadGame (String[] args) {
- SplashWindow splashWindow = new SplashWindow(true);
- splashWindow.notifyOfStep(SplashWindow.STEP_LOAD_GAME);
-
Game game = null;
String filepath = args[0];
+
+ SplashWindow splashWindow = new SplashWindow(true,filepath);
+ splashWindow.notifyOfStep(SplashWindow.STEP_LOAD_GAME);
+
System.out.println("Starting game from saved file "+filepath);
if ((game = Game.load(filepath)) == null) {
System.err.println("Loading file "+filepath+" was unsuccessful");
commit b28efc90ce9a591119f83d6613d16df57990917a
Author: Frederick Weld <fre...@gm...>
Date: Fri Feb 17 16:27:15 2012 +0100
Laid out splash screen (incl. rails version, progress bar)
diff --git a/LocalisedText.properties b/LocalisedText.properties
index 9c1ccd7..ee7f6f5 100644
--- a/LocalisedText.properties
+++ b/LocalisedText.properties
@@ -213,7 +213,7 @@ Config.label.route.colour.1=Route color for first train
Config.label.route.colour.2=Route color for second train
Config.label.route.colour.3=Route color for third train
Config.label.route.colour.4=Route color for fourth train
-Config.label.splash.window.open=Splash window open
+Config.label.splash.window.open=Display splash screen
Config.label.sound.backgroundMusic=Background Music
Config.label.sound.backgroundMusic.endOfGameRound=End of Game
Config.label.sound.backgroundMusic.gameSetup=Initial Game Setup
diff --git a/rails/ui/swing/SplashWindow.java b/rails/ui/swing/SplashWindow.java
index edb8cad..1e1201e 100644
--- a/rails/ui/swing/SplashWindow.java
+++ b/rails/ui/swing/SplashWindow.java
@@ -1,18 +1,28 @@
package rails.ui.swing;
-import java.awt.Rectangle;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Toolkit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import javax.swing.BoxLayout;
+import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.EtchedBorder;
import rails.common.parser.Config;
+import rails.game.Game;
/**
* Splash window shown during setup of game UI components and game loading.
@@ -32,20 +42,20 @@ public class SplashWindow {
private static String DUMMY_STEP_START = "0";
private static String DUMMY_STEP_END = "inf";
- public static String STEP_LOAD_GAME = "1";
- public static String STEP_INIT_UI = "2";
- public static String STEP_STOCK_CHART = "3";
- public static String STEP_REPORT_WINDOW = "4";
- public static String STEP_OR_INIT_DOCKING_FRAME = "5A";
- public static String STEP_OR_INIT_PANELS = "5B";
- public static String STEP_OR_INIT_TILES = "5C";
- public static String STEP_OR_APPLY_DOCKING_FRAME = "5D";
- public static String STEP_STATUS_WINDOW = "6";
- public static String STEP_INIT_NEW_GAME = "7";
- public static String STEP_CONFIG_WINDOW = "8";
- public static String STEP_INIT_SOUND = "9";
- public static String STEP_INIT_LOADED_GAME = "10";
- public static String STEP_FINALIZE = "11";
+ public static String STEP_LOAD_GAME = "Splash.step.loadGame";
+ public static String STEP_INIT_UI = "Splash.step.initUI";
+ public static String STEP_STOCK_CHART = "Splash.step.stockChart";
+ public static String STEP_REPORT_WINDOW = "Splash.step.reportWindow";
+ public static String STEP_OR_INIT_DOCKING_FRAME = "Splash.step.or.initDockingFrame";
+ public static String STEP_OR_INIT_PANELS = "Splash.step.or.initPanels";
+ public static String STEP_OR_INIT_TILES = "Splash.step.or.initTiles";
+ public static String STEP_OR_APPLY_DOCKING_FRAME = "Splash.step.or.applyDockingFrame";
+ public static String STEP_STATUS_WINDOW = "Splash.step.statusWindow";
+ public static String STEP_INIT_NEW_GAME = "Splash.step.initNewGame";
+ public static String STEP_CONFIG_WINDOW = "Splash.step.configWindow";
+ public static String STEP_INIT_SOUND = "Splash.step.initSound";
+ public static String STEP_INIT_LOADED_GAME = "Splash.step.initLoadedGame";
+ public static String STEP_FINALIZE = "Splash.step.finalize";
private static List<String> STEP_GROUP_LOAD = Arrays.asList(new String[] {
STEP_LOAD_GAME,
@@ -92,11 +102,15 @@ public class SplashWindow {
private Set<JFrame> framesRegisteredAsVisible = new HashSet<JFrame>();
private List<JFrame> framesRegisteredToFront = new ArrayList<JFrame>();
+ private static Dimension iconSize = new Dimension(90,78);
+
private JWindow myWin = null;
- private ProgressVisualizer progressVisualizer = null;
+ private JLabel leftIcon = null;
+ private JLabel rightIcon = null;
+ private JProgressBar progressBar = null;
+ private JLabel stepLabel = null;
- //TODO remove temp label
- private JLabel tempL = null;
+ private ProgressVisualizer progressVisualizer = null;
private int currentStep = 1; //the start step
@@ -104,17 +118,7 @@ public class SplashWindow {
//quit directly when no visualization required
//all visualization related attributes remain null then
if ("no".equals(Config.get("splash.window.open"))) return;
-
- myWin = new JWindow();
- myWin.setBounds(new Rectangle(200,200,400,200));
-
- //TODO remove temp
- tempL = new JLabel("");
- myWin.getContentPane().add(tempL);
- tempL.setVisible(true);
- //TODO set up frame (incl. title, icons, bar, status text)
- myWin.setVisible(true);
-
+
//calculate estimated duration for the respective steps
cumulativeDuration = new long[stepDuration.length];
boolean isDockingLayout = "yes".equals(Config.get("or.window.dockablePanels"));
@@ -128,6 +132,69 @@ public class SplashWindow {
cumulativeDuration[i] = totalDuration;
}
+ //set up dynamic elements
+
+ myWin = new JWindow();
+
+ leftIcon = new JLabel();
+ leftIcon.setPreferredSize(iconSize);
+ rightIcon = new JLabel();
+ rightIcon.setPreferredSize(iconSize);
+
+ progressBar = new JProgressBar(0,(int)totalDuration);
+ progressBar.setStringPainted(true);
+ progressBar.setMinimum(0);
+
+ stepLabel = new JLabel();
+ stepLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ //set up static elements
+
+ JLabel railsLabel = new JLabel("Rails " + Game.getFullVersion());
+ railsLabel.setFont(railsLabel.getFont().deriveFont(
+ (float)2.0 * railsLabel.getFont().getSize()));
+ railsLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ JLabel commandLabel = new JLabel("Setting up new game / loading game");
+ commandLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ //plug elements together and set up layout
+
+ JPanel railsCommandPanel = new JPanel();
+ railsCommandPanel.setLayout(new BoxLayout(railsCommandPanel, BoxLayout.Y_AXIS));
+ railsCommandPanel.add(railsLabel);
+ railsCommandPanel.add(commandLabel);
+
+ JPanel idPanel = new JPanel();
+ idPanel.setLayout(new BoxLayout(idPanel, BoxLayout.X_AXIS));
+ idPanel.add(leftIcon);
+ idPanel.add(railsCommandPanel);
+ idPanel.add(rightIcon);
+
+ JComponent contentPane = (JComponent)myWin.getContentPane();
+ contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
+ contentPane.add(idPanel);
+ contentPane.add(progressBar);
+ contentPane.add(stepLabel);
+ contentPane.setBorder(new CompoundBorder(new EtchedBorder(),new EmptyBorder(5,5,5,5)));
+
+ //perform layout within the EDT
+ //blocking call as further initialization requires the layout to be frozen
+ try {
+ SwingUtilities.invokeAndWait(new Thread() {
+ @Override
+ public void run() {
+ myWin.pack();
+ Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
+ myWin.setLocation(
+ (dim.width - myWin.getSize().width) / 2,
+ (dim.height - myWin.getSize().height) / 2
+ );
+ myWin.setVisible(true);
+ }
+ });
+ } catch (Exception e) {}
+
progressVisualizer = new ProgressVisualizer();
progressVisualizer.setCurrentStep(currentStep);
progressVisualizer.start();
@@ -154,24 +221,29 @@ public class SplashWindow {
this.currentStep = currentStep;
//only display step description for non-dummy steps
if (stepDuration[currentStep].expectedDurationInMillis > 0) {
- //TODO
+ stepLabel.setText(stepDuration[currentStep].labelConfigKey);
+ enforeGUIUpdate(stepLabel);
}
}
//show progress
- double percentage = 100.0 * elapsedDuration / totalDuration;
- tempL.setText("<html>" + percentage + "<br>" + stepDuration[currentStep].labelConfigKey + "</html>");
+ progressBar.setValue((int)elapsedDuration);
+ enforeGUIUpdate(progressBar);
- //ensure that progress is updated even if EDT is very busy
- //CAUTION: paintImmediately is called outside of EDT
- // works but not guideline-conform
- tempL.paintImmediately(tempL.getBounds());
-
//ensure visibility of window
myWin.toFront();
}
/**
+ * ensure that progress is updated even if EDT is very busy
+ * CAUTION: paintImmediately is called outside of EDT
+ * works but not guideline-conform
+ */
+ private void enforeGUIUpdate(JComponent c) {
+ c.paintImmediately(c.getBounds());
+ }
+
+ /**
* Remembers that this frame is to be put to visible at the end of the splash process
*/
public void registerFrameForDeferredVisibility(JFrame frame,boolean setToVisible) {
commit 1aa89dfdc7568950f5f6b0b8833c0e12e25e1eee
Author: Frederick Weld <fre...@gm...>
Date: Fri Feb 17 06:19:19 2012 +0100
Added option to display splash screen (default yes)
Even if splash screen is not to be displayed, the init logic
(deferring setVisible/toFront, parallelization EDT and non-EDT) is
applied.
diff --git a/LocalisedText.properties b/LocalisedText.properties
index 087534b..9c1ccd7 100644
--- a/LocalisedText.properties
+++ b/LocalisedText.properties
@@ -213,6 +213,7 @@ Config.label.route.colour.1=Route color for first train
Config.label.route.colour.2=Route color for second train
Config.label.route.colour.3=Route color for third train
Config.label.route.colour.4=Route color for fourth train
+Config.label.splash.window.open=Splash window open
Config.label.sound.backgroundMusic=Background Music
Config.label.sound.backgroundMusic.endOfGameRound=End of Game
Config.label.sound.backgroundMusic.gameSetup=Initial Game Setup
diff --git a/data/Properties.xml b/data/Properties.xml
index 9399a9f..1e5c37e 100644
--- a/data/Properties.xml
+++ b/data/Properties.xml
@@ -41,6 +41,7 @@
<Property name="report.window.editable" type="BOOLEAN" />
<Property name="stockchart.window.open" type="BOOLEAN" />
<Property name="or.window.dockablePanels" type="BOOLEAN" />
+ <Property name="splash.window.open" type="BOOLEAN" />
</Section>
<Section name="Format">
<Property name="money_format" type="STRING" />
diff --git a/data/profiles/default.profile b/data/profiles/default.profile
index 03d7a58..122c1b7 100644
--- a/data/profiles/default.profile
+++ b/data/profiles/default.profile
@@ -1,2 +1,2 @@
### Default profile currently is identical to root.profile
-### so no change here
\ No newline at end of file
+### so no change here
diff --git a/rails/ui/swing/SplashWindow.java b/rails/ui/swing/SplashWindow.java
index 68fddda..edb8cad 100644
--- a/rails/ui/swing/SplashWindow.java
+++ b/rails/ui/swing/SplashWindow.java
@@ -87,20 +87,24 @@ public class SplashWindow {
};
private long totalDuration = 0;
- private long[] cumulativeDuration;
+ private long[] cumulativeDuration = null;
private Set<JFrame> framesRegisteredAsVisible = new HashSet<JFrame>();
private List<JFrame> framesRegisteredToFront = new ArrayList<JFrame>();
- private JWindow myWin;
- private ProgressVisualizer progressVisualizer;
+ private JWindow myWin = null;
+ private ProgressVisualizer progressVisualizer = null;
//TODO remove temp label
- private JLabel tempL;
+ private JLabel tempL = null;
private int currentStep = 1; //the start step
public SplashWindow(boolean isLoad) {
+ //quit directly when no visualization required
+ //all visualization related attributes remain null then
+ if ("no".equals(Config.get("splash.window.open"))) return;
+
myWin = new JWindow();
myWin.setBounds(new Rectangle(200,200,400,200));
@@ -130,6 +134,9 @@ public class SplashWindow {
}
public void notifyOfStep(String stepLabelConfigKey) {
+ //ignore if no visualization requested
+ if (myWin == null) return;
+
for (int i = 0 ; i < stepDuration.length ; i++) {
if (stepDuration[i].labelConfigKey.equals(stepLabelConfigKey)) {
progressVisualizer.setCurrentStep(i);
@@ -208,10 +215,11 @@ public class SplashWindow {
});
} catch (Exception e) {}
- progressVisualizer.interrupt();
-
- myWin.dispose();
-
+ //clean up visualization only if it was requested
+ if (myWin != null) {
+ progressVisualizer.interrupt();
+ myWin.dispose();
+ }
}
private class ProgressVisualizer extends Thread {
commit 2f2e71b6e7de9340e5c9e64388b1f10a097f5e41
Author: Frederick Weld <fre...@gm...>
Date: Thu Feb 16 19:59:37 2012 +0100
Added context dependent progress calculation (new/load, conv/docking)
Init time largely depend on whether
- new game is started or old game is loaded (latter lasts longer)
- conventional layout or docking layout is used (latter is longer)
Now, the splash window's heuristic takes into account this context
information for better display of the progress.
diff --git a/rails/ui/swing/GameSetupWindow.java b/rails/ui/swing/GameSetupWindow.java
index c7ebea1..6a633a9 100644
--- a/rails/ui/swing/GameSetupWindow.java
+++ b/rails/ui/swing/GameSetupWindow.java
@@ -228,7 +228,7 @@ public class GameSetupWindow extends JDialog implements ActionListener {
*/
private void loadAndStartGame(String filePath, String saveDirectory) {
prepareGameUIInit();
- SplashWindow splashWindow = new SplashWindow();
+ SplashWindow splashWindow = new SplashWindow(true);
splashWindow.notifyOfStep(SplashWindow.STEP_LOAD_GAME);
if ((game = Game.load(filePath)) == null) {
JOptionPane.showMessageDialog(this,
@@ -517,7 +517,7 @@ public class GameSetupWindow extends JDialog implements ActionListener {
System.exit(-1);
}
prepareGameUIInit();
- SplashWindow splashWindow = new SplashWindow();
+ SplashWindow splashWindow = new SplashWindow(false);
startGameUIManager (game, false, splashWindow);
gameUIManager.gameUIInit(true); // true indicates new game
completeGameUIInit(splashWindow);
diff --git a/rails/ui/swing/SplashWindow.java b/rails/ui/swing/SplashWindow.java
index 0f030a1..68fddda 100644
--- a/rails/ui/swing/SplashWindow.java
+++ b/rails/ui/swing/SplashWindow.java
@@ -2,6 +2,7 @@ package rails.ui.swing;
import java.awt.Rectangle;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -11,6 +12,8 @@ import javax.swing.JLabel;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;
+import rails.common.parser.Config;
+
/**
* Splash window shown during setup of game UI components and game loading.
* Provides for a progress bar, status bar, and ensures that frames only become visible
@@ -43,6 +46,17 @@ public class SplashWindow {
public static String STEP_INIT_SOUND = "9";
public static String STEP_INIT_LOADED_GAME = "10";
public static String STEP_FINALIZE = "11";
+
+ private static List<String> STEP_GROUP_LOAD = Arrays.asList(new String[] {
+ STEP_LOAD_GAME,
+ STEP_INIT_LOADED_GAME
+ });
+
+ private static List<String> STEP_GROUP_DOCKING_LAYOUT = Arrays.asList(new String[] {
+ STEP_OR_INIT_DOCKING_FRAME,
+ STEP_OR_INIT_TILES,
+ STEP_OR_APPLY_DOCKING_FRAME,
+ });
private static class StepDuration {
long expectedDurationInMillis;
@@ -62,7 +76,7 @@ public class SplashWindow {
new StepDuration ( 2600, STEP_OR_INIT_DOCKING_FRAME ),
new StepDuration ( 1650, STEP_OR_INIT_PANELS ),
new StepDuration ( 5000, STEP_OR_INIT_TILES ),
- new StepDuration ( 3000, STEP_OR_APPLY_DOCKING_FRAME ),
+ new StepDuration ( 1000, STEP_OR_APPLY_DOCKING_FRAME ),
new StepDuration ( 400, STEP_STATUS_WINDOW ),
new StepDuration ( 300, STEP_INIT_NEW_GAME ),
new StepDuration ( 1200, STEP_CONFIG_WINDOW ),
@@ -86,20 +100,27 @@ public class SplashWindow {
private int currentStep = 1; //the start step
- public SplashWindow() {
+ public SplashWindow(boolean isLoad) {
myWin = new JWindow();
myWin.setBounds(new Rectangle(200,200,400,200));
//TODO remove temp
- tempL = new JLabel("sghsghsghsfghws");
+ tempL = new JLabel("");
myWin.getContentPane().add(tempL);
tempL.setVisible(true);
//TODO set up frame (incl. title, icons, bar, status text)
myWin.setVisible(true);
+ //calculate estimated duration for the respective steps
cumulativeDuration = new long[stepDuration.length];
+ boolean isDockingLayout = "yes".equals(Config.get("or.window.dockablePanels"));
for (int i = 0 ; i < stepDuration.length ; i++) {
- totalDuration += stepDuration[i].expectedDurationInMillis;
+ //only consider step if relevant for this setup
+ if ( (isLoad || !STEP_GROUP_LOAD.contains(stepDuration[i].labelConfigKey))
+ &&
+ (isDockingLayout || !STEP_GROUP_DOCKING_LAYOUT.contains(stepDuration[i].labelConfigKey)) ) {
+ totalDuration += stepDuration[i].expectedDurationInMillis;
+ }
cumulativeDuration[i] = totalDuration;
}
diff --git a/rails/util/RunGame.java b/rails/util/RunGame.java
index 461035a..8206c25 100644
--- a/rails/util/RunGame.java
+++ b/rails/util/RunGame.java
@@ -49,7 +49,7 @@ public class RunGame {
static void loadGame (String[] args) {
- SplashWindow splashWindow = new SplashWindow();
+ SplashWindow splashWindow = new SplashWindow(true);
splashWindow.notifyOfStep(SplashWindow.STEP_LOAD_GAME);
Game game = null;
commit 88c68529a44f51f2a17bb7c9932b6b2eeff2f112
Author: Frederick Weld <fre...@gm...>
Date: Thu Feb 16 16:55:11 2012 +0100
Ensured that progress is visualized even if EDT is busy
diff --git a/rails/ui/swing/SplashWindow.java b/rails/ui/swing/SplashWindow.java
index b8ba47d..0f030a1 100644
--- a/rails/ui/swing/SplashWindow.java
+++ b/rails/ui/swing/SplashWindow.java
@@ -23,7 +23,7 @@ public class SplashWindow {
/**
* in millisecs
*/
- private static long PROGRESS_UPDATE_INTERVAL = 100;
+ private static long PROGRESS_UPDATE_INTERVAL = 200;
private static String DUMMY_STEP_BEFORE_START = "-1";
private static String DUMMY_STEP_START = "0";
@@ -133,6 +133,11 @@ public class SplashWindow {
//show progress
double percentage = 100.0 * elapsedDuration / totalDuration;
tempL.setText("<html>" + percentage + "<br>" + stepDuration[currentStep].labelConfigKey + "</html>");
+
+ //ensure that progress is updated even if EDT is very busy
+ //CAUTION: paintImmediately is called outside of EDT
+ // works but not guideline-conform
+ tempL.paintImmediately(tempL.getBounds());
//ensure visibility of window
myWin.toFront();
commit e75ec0326113597cb78ca5836c3017b47537ceb5
Author: Frederick Weld <fre...@gm...>
Date: Thu Feb 16 16:41:33 2012 +0100
Added support for setting frames in correct front-to-back order after init
diff --git a/rails/ui/swing/GameUIManager.java b/rails/ui/swing/GameUIManager.java
index 809dcf4..7e59194 100644
--- a/rails/ui/swing/GameUIManager.java
+++ b/rails/ui/swing/GameUIManager.java
@@ -475,7 +475,7 @@ public class GameUIManager implements DialogOwner {
setMeVisible(stockChart,stockChartVisibilityHint);
previousStockChartVisibilityHint = stockChartVisibilityHint;
}
- if (hint.getVisibility()) stockChart.toFront();
+ if (hint.getVisibility()) setMeToFront(stockChart);
break;
case STATUS:
boolean statusWindowVisibilityHint = hint.getVisibility();
@@ -483,7 +483,7 @@ public class GameUIManager implements DialogOwner {
setMeVisible(statusWindow,statusWindowVisibilityHint);
previousStatusWindowVisibilityHint = statusWindowVisibilityHint;
}
- if (statusWindowVisibilityHint) statusWindow.toFront();
+ if (statusWindowVisibilityHint) setMeToFront(statusWindow);
break;
case MAP:
boolean orWindowVisibilityHint = hint.getVisibility();
@@ -491,7 +491,7 @@ public class GameUIManager implements DialogOwner {
setMeVisible(orWindow,orWindowVisibilityHint);
previousORWindowVisibilityHint = orWindowVisibilityHint;
}
- if (orWindowVisibilityHint) orWindow.toFront();
+ if (orWindowVisibilityHint) setMeToFront(orWindow);
break;
case START_ROUND:
// Handled elsewhere
@@ -511,7 +511,7 @@ public class GameUIManager implements DialogOwner {
log.debug("Entering Start Round UI type");
activeWindow = startRoundWindow;
setMeVisible(startRoundWindow,true);
- startRoundWindow.toFront();
+ setMeToFront(startRoundWindow);
} else if (uiHints.getActivePanel() == GuiDef.Panel.STATUS || correctionOverride) {
@@ -519,14 +519,14 @@ public class GameUIManager implements DialogOwner {
activeWindow = statusWindow;
stockChart.setVisible(true);
setMeVisible(statusWindow,true);
- statusWindow.toFront();
+ setMeToFront(statusWindow);
} else if (uiHints.getActivePanel() == GuiDef.Panel.MAP && !correctionOverride) {
log.debug("Entering Operating Round UI type ");
activeWindow = orWindow;
setMeVisible(orWindow,true);
- orWindow.toFront();
+ setMeToFront(orWindow);
}
@@ -1146,6 +1146,19 @@ public class GameUIManager implements DialogOwner {
}
/**
+ * Only set frame directly to front if the splash phase is already over.
+ * Otherwise, the splash framework remembers this toFront request and
+ * postpones the toFront to the point in time where the splash is completed.
+ */
+ public void setMeToFront(JFrame frame) {
+ if (splashWindow == null) {
+ frame.toFront();
+ } else {
+ splashWindow.registerFrameForDeferredToFront(frame);
+ }
+ }
+
+ /**
* called when the splash process is completed
* (and visibility changes are not to be deferred any more)
*/
diff --git a/rails/ui/swing/SplashWindow.java b/rails/ui/swing/SplashWindow.java
index 8a279ce..b8ba47d 100644
--- a/rails/ui/swing/SplashWindow.java
+++ b/rails/ui/swing/SplashWindow.java
@@ -1,7 +1,9 @@
package rails.ui.swing;
import java.awt.Rectangle;
+import java.util.ArrayList;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import javax.swing.JFrame;
@@ -40,6 +42,7 @@ public class SplashWindow {
public static String STEP_CONFIG_WINDOW = "8";
public static String STEP_INIT_SOUND = "9";
public static String STEP_INIT_LOADED_GAME = "10";
+ public static String STEP_FINALIZE = "11";
private static class StepDuration {
long expectedDurationInMillis;
@@ -59,12 +62,13 @@ public class SplashWindow {
new StepDuration ( 2600, STEP_OR_INIT_DOCKING_FRAME ),
new StepDuration ( 1650, STEP_OR_INIT_PANELS ),
new StepDuration ( 5000, STEP_OR_INIT_TILES ),
- new StepDuration ( 2000, STEP_OR_APPLY_DOCKING_FRAME ),
+ new StepDuration ( 3000, STEP_OR_APPLY_DOCKING_FRAME ),
new StepDuration ( 400, STEP_STATUS_WINDOW ),
new StepDuration ( 300, STEP_INIT_NEW_GAME ),
new StepDuration ( 1200, STEP_CONFIG_WINDOW ),
new StepDuration ( 200, STEP_INIT_SOUND ),
new StepDuration ( 1000, STEP_INIT_LOADED_GAME ),
+ new StepDuration ( 1000, STEP_FINALIZE),
new StepDuration ( 0, DUMMY_STEP_END), // used to facilitate array border handling
};
@@ -72,6 +76,7 @@ public class SplashWindow {
private long[] cumulativeDuration;
private Set<JFrame> framesRegisteredAsVisible = new HashSet<JFrame>();
+ private List<JFrame> framesRegisteredToFront = new ArrayList<JFrame>();
private JWindow myWin;
private ProgressVisualizer progressVisualizer;
@@ -119,7 +124,8 @@ public class SplashWindow {
//update current step (including description)
if (currentStep != this.currentStep) {
this.currentStep = currentStep;
- if (currentStep != 0 && currentStep != stepDuration.length - 1) {
+ //only display step description for non-dummy steps
+ if (stepDuration[currentStep].expectedDurationInMillis > 0) {
//TODO
}
}
@@ -143,19 +149,38 @@ public class SplashWindow {
}
}
+ /**
+ * Remembers that this frame is to be put to front at the end of the splash process
+ * Handles the list of to front requests in order to
+ * - apply all requests in a FIFO manner
+ * - ensure that each frame is only sent to the front once (at the latest registered time)
+ */
+ public void registerFrameForDeferredToFront(JFrame frame) {
+ framesRegisteredToFront.remove(frame);
+ framesRegisteredToFront.add(frame);
+ }
+
public void finalizeGameInit() {
- progressVisualizer.setCurrentStep(stepDuration.length - 1);
+ notifyOfStep(STEP_FINALIZE);
- //finally restore visibility of registered frames
+ //finally restore visibility / toFront of registered frames
//only after EDT is ready (as window built-up could still be pending)
- SwingUtilities.invokeLater(new Thread() {
- @Override
- public void run() {
- for (JFrame frame : framesRegisteredAsVisible) {
- frame.setVisible(true);
+ //block any frame disposal to the point in time when this is through
+ try {
+ SwingUtilities.invokeAndWait(new Thread() {
+ @Override
+ public void run() {
+ //visibility
+ for (JFrame frame : framesRegisteredAsVisible) {
+ frame.setVisible(true);
+ }
+ //to front
+ for (JFrame frame : framesRegisteredToFront) {
+ frame.toFront();
+ }
}
- }
- });
+ });
+ } catch (Exception e) {}
progressVisualizer.interrupt();
@@ -164,24 +189,24 @@ public class SplashWindow {
}
private class ProgressVisualizer extends Thread {
- private long elapsedDuration = 0;
+ private long elapsedTime = 0;
private int currentStep = 0;
@Override
public void run() {
try {
while (!isInterrupted()) {
- visualizeProgress(elapsedDuration, currentStep);
+ visualizeProgress(elapsedTime, currentStep);
sleep(PROGRESS_UPDATE_INTERVAL);
//adjusted elapsed duration
synchronized (this) {
- elapsedDuration += PROGRESS_UPDATE_INTERVAL;
+ elapsedTime += PROGRESS_UPDATE_INTERVAL;
//elapsed duration must remain within the bounds of the estimated cumulative duration
//between the end of last step and the end of the current step
- elapsedDuration = Math.max (
+ elapsedTime = Math.max (
cumulativeDuration[currentStep-1],
- Math.min( elapsedDuration, cumulativeDuration[currentStep] )
+ Math.min( elapsedTime, cumulativeDuration[currentStep] )
);
}
}
@@ -190,6 +215,7 @@ public class SplashWindow {
synchronized private void setCurrentStep(int currentStep) {
this.currentStep = currentStep;
+ //System.out.println("Time: "+elapsedTime + " (Step: "+stepDuration[currentStep].labelConfigKey+")");
}
}
}
\ No newline at end of file
commit c71458876f4beb07d49543bbf6fdc74bae3c8ae8
Author: Frederick Weld <fre...@gm...>
Date: Thu Feb 16 16:16:10 2012 +0100
Removed multi-instance GameManager concept / set GameManager to singleton
diff --git a/rails/game/GameManager.java b/rails/game/GameManager.java
index c147924..15915f0 100644
--- a/rails/game/GameManager.java
+++ b/rails/game/GameManager.java
@@ -136,6 +136,12 @@ public class GameManager implements ConfigurableComponentI, GameManagerI {
new EnumMap<GuiDef.Parm, Boolean>(GuiDef.Parm.class);
/**
+ * Update:
+ * NDC concept has been replaced by the origin singleton one.
+ * Target design to be decided when distributed rails is being conceived
+ * and developed.
+ *
+ * Former design:
* Map of GameManager instances.
* Currently there can be only one instance, but in a possible
* future multi-game server there may be several instances
@@ -237,8 +243,8 @@ public class GameManager implements ConfigurableComponentI, GameManagerI {
public GameManager() {
gmName = GM_NAME;
gmKey = GM_KEY;
- NDC.clear();
- NDC.push (GM_KEY);
+ //NDC.clear();
+ //NDC.push (GM_KEY);
gameManagerMap.put(GM_KEY, this);
displayBuffer = new DisplayBuffer();
reportBuffer = new ReportBuffer();
@@ -633,7 +639,8 @@ public class GameManager implements ConfigurableComponentI, GameManagerI {
* @return instance of GameManager
*/
public static GameManagerI getInstance () {
- return gameManagerMap.get(NDC.peek());
+// return gameManagerMap.get(NDC.peek());
+ return gameManagerMap.get(GM_KEY);
}
/* (non-Javadoc)
commit 33e8c3cf880ee791cfd1c941eef6be64395394a4
Author: Frederick Weld <fre...@gm...>
Date: Thu Feb 16 16:11:36 2012 +0100
Removed game init by default from EDT / put pack explicitly into EDT
diff --git a/rails/ui/swing/ConfigWindow.java b/rails/ui/swing/ConfigWindow.java
index db03e10..e5fb185 100644
--- a/rails/ui/swing/ConfigWindow.java
+++ b/rails/ui/swing/ConfigWindow.java
@@ -8,6 +8,7 @@ import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
+import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
@@ -43,6 +44,7 @@ import javax.swing.JSpinner;
import javax.swing.JTabbedPane;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
+import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.border.Border;
@@ -105,8 +107,13 @@ class ConfigWindow extends JFrame {
setupProfilePanel();
setupConfigPane();
setupButtonPanel();
- this.pack();
- setSize(600,400);
+
+ SwingUtilities.invokeLater(new Thread() {
+ public void run() {
+ ConfigWindow.this.pack();
+ ConfigWindow.this.setSize(600,400);
+ }
+ });
}
private void setupProfilePanel() {
diff --git a/rails/ui/swing/ORWindow.java b/rails/ui/swing/ORWindow.java
index c67a23f..68f2ce5 100644
--- a/rails/ui/swing/ORWindow.java
+++ b/rails/ui/swing/ORWindow.java
@@ -189,7 +189,13 @@ public class ORWindow extends DockingFrame implements ActionPerformer {
if (bounds.width != -1 && bounds.height != -1) setSize(bounds.getSize());
ws.set(frame);
- if (isDockingFrameworkEnabled()) initLayout();
+ if (isDockingFrameworkEnabled()) {
+ initLayout();
+
+ //trigger early painting in order to parallelize OR window setup
+ //with other setup activities
+ repaint();
+ }
}
});
diff --git a/rails/ui/swing/SplashWindow.java b/rails/ui/swing/SplashWindow.java
index 406af02..8a279ce 100644
--- a/rails/ui/swing/SplashWindow.java
+++ b/rails/ui/swing/SplashWindow.java
@@ -104,7 +104,6 @@ public class SplashWindow {
}
public void notifyOfStep(String stepLabelConfigKey) {
- myWin.toFront();
for (int i = 0 ; i < stepDuration.length ; i++) {
if (stepDuration[i].labelConfigKey.equals(stepLabelConfigKey)) {
progressVisualizer.setCurrentStep(i);
@@ -128,6 +127,9 @@ public class SplashWindow {
//show progress
double percentage = 100.0 * elapsedDuration / totalDuration;
tempL.setText("<html>" + percentage + "<br>" + stepDuration[currentStep].labelConfigKey + "</html>");
+
+ //ensure visibility of window
+ myWin.toFront();
}
/**
diff --git a/rails/util/RunGame.java b/rails/util/RunGame.java
index 55e6fb5..461035a 100644
--- a/rails/util/RunGame.java
+++ b/rails/util/RunGame.java
@@ -39,14 +39,7 @@ public class RunGame {
static void loadGameOnEventQueue(final String[] args)
{
try {
- java.awt.EventQueue.invokeAndWait(
- new Runnable()
- {
- public void run() {
- loadGame(args);
- }
- }
- );
+ loadGame(args);
} catch (Exception e) {
System.err.println("Cannot load game: "+e.getMessage());
e.printStackTrace(System.err);
commit 8d63d4c97bf2847f79af079da18eb34e3a841656
Author: Frederick Weld <fre...@gm...>
Date: Thu Feb 16 16:00:06 2012 +0100
Added continuous visualization of init progress
Before, progress was updated upon the completion of a init step.
Now, progress is updated continuously based on a heuristic that gets
the expected duration of the init steps as an input parameter.
diff --git a/rails/ui/swing/SplashWindow.java b/rails/ui/swing/SplashWindow.java
index 439fba1..406af02 100644
--- a/rails/ui/swing/SplashWindow.java
+++ b/rails/ui/swing/SplashWindow.java
@@ -1,6 +1,3 @@
-/**
- *
- */
package rails.ui.swing;
import java.awt.Rectangle;
@@ -21,6 +18,15 @@ import javax.swing.SwingUtilities;
*/
public class SplashWindow {
+ /**
+ * in millisecs
+ */
+ private static long PROGRESS_UPDATE_INTERVAL = 100;
+
+ private static String DUMMY_STEP_BEFORE_START = "-1";
+ private static String DUMMY_STEP_START = "0";
+ private static String DUMMY_STEP_END = "inf";
+
public static String STEP_LOAD_GAME = "1";
public static String STEP_INIT_UI = "2";
public static String STEP_STOCK_CHART = "3";
@@ -36,15 +42,16 @@ public class SplashWindow {
public static String STEP_INIT_LOADED_GAME = "10";
private static class StepDuration {
- int expectedDurationInMillis;
+ long expectedDurationInMillis;
String labelConfigKey;
- StepDuration(int expDurationInMillis,String labelConfigKey) {
- this.expectedDurationInMillis = expDurationInMillis;
+ StepDuration(int expectedDurationInMillis,String labelConfigKey) {
+ this.expectedDurationInMillis = expectedDurationInMillis;
this.labelConfigKey = labelConfigKey;
}
}
private static StepDuration[] stepDuration = {
- new StepDuration ( 0, "Start"), // used to facilitate array border handling
+ new StepDuration ( 0, DUMMY_STEP_BEFORE_START), // used to facilitate array border handling
+ new StepDuration ( 0, DUMMY_STEP_START), // used to facilitate array border handling
new StepDuration ( 6000, STEP_LOAD_GAME ),
new StepDuration ( 500, STEP_INIT_UI ),
new StepDuration ( 230, STEP_STOCK_CHART ),
@@ -58,19 +65,22 @@ public class SplashWindow {
new StepDuration ( 1200, STEP_CONFIG_WINDOW ),
new StepDuration ( 200, STEP_INIT_SOUND ),
new StepDuration ( 1000, STEP_INIT_LOADED_GAME ),
- ...
[truncated message content] |
|
From: Stefan F. <ste...@us...> - 2012-02-17 13:44:40
|
data/profiles/ORDocking.profile | 3 +
data/profiles/default.profile | 61 ----------------------
data/profiles/default.profiles | 7 ++
data/profiles/prettyUI.profile | 9 +++
data/profiles/root.profile | 62 ++++++++++++++++++++++
data/profiles/test.profile | 110 ----------------------------------------
rails/common/parser/Config.java | 15 ++++-
7 files changed, 93 insertions(+), 174 deletions(-)
New commits:
commit 0e0a46edc14d03cf2a07bd12cde541f93af47a12
Author: Stefan Frey <ste...@we...>
Date: Fri Feb 17 14:43:51 2012 +0100
added new profiles and a 3-tier structure for the configuration profiles
diff --git a/data/profiles/ORDocking.profile b/data/profiles/ORDocking.profile
new file mode 100644
index 0000000..e5f8d80
--- /dev/null
+++ b/data/profiles/ORDocking.profile
@@ -0,0 +1,3 @@
+### ORDocking profile
+### activates the docking framework
+or.window.dockablePanels=yes
diff --git a/data/profiles/default.profile b/data/profiles/default.profile
index b4e4cb9..03d7a58 100644
--- a/data/profiles/default.profile
+++ b/data/profiles/default.profile
@@ -1,59 +1,2 @@
-### Panel General
-locale=en_US
-default_game=1830
-default_players=
-local.player.names=
-
-### Panel Save
-save.directory=
-save.filename.date_time_pattern=yyyyMMdd_HHmm
-save.filename.date_time_zone=UTC
-save.filename.suffix=NEXT_PLAYER
-save.filename.extension=rails
-save.recovery.active=no
-save.recovery.filepath=18xx_autosave.rails
-
-### Panel Font
-font.ui.scale=1
-font.ui.name=
-font.ui.style=bold
-
-### Panel Map
-map.autoscroll=yes
-map.defaultZoomFitOption=none
-map.displayCurrentRoutes=yes
-map.highlightHexes=yes
-map.image.display=no
-map.zoomstep=10
-
-### Panel Windows
-or.window.dockablePanels=no
-report.window.type=dynamic
-report.window.open=yes
-report.window.editable=no
-stockchart.window.open=yes
-
-### Panel Format
-money_format=
-or.number_format=composite
-
-### Panel Appearance
-button.iconText=text and icon
-button.iconSize=small
-button.iconPosition=left
-gridPanel.tableBorders=enabled
-route.colour.1=00ffff
-route.colour.2=ffc0cb
-route.colour.3=ffa500
-route.colour.4=808080
-
-### Panel Log
-#report.directory=log
-#report.filename.date_time_pattern=yyyyMMdd
-#report.filename.extension=log
-
-### Panel Music
-sound.backgroundMusic=disabled
-
-### Panel SFX
-sound.sfx=disabled
+### Default profile currently is identical to root.profile
+### so no change here
\ No newline at end of file
diff --git a/data/profiles/default.profiles b/data/profiles/default.profiles
index 66511a9..9cedd38 100644
--- a/data/profiles/default.profiles
+++ b/data/profiles/default.profiles
@@ -1,2 +1,7 @@
-default=data/profiles/default.profile
+### This is the list of (predefined) profiles and their file locations
+### A dot (".") before the profilename prevents displaying those to the user selection
+.root=data/profiles/root.profile
.test=data/profiles/test.profile
+default=data/profiles/default.profile
+prettyUI=data/profiles/prettyUI.profile
+ORDocking=data/profiles/ORDocking.profile
diff --git a/data/profiles/prettyUI.profile b/data/profiles/prettyUI.profile
new file mode 100644
index 0000000..a537864
--- /dev/null
+++ b/data/profiles/prettyUI.profile
@@ -0,0 +1,9 @@
+### prettyUI profile
+### activates the new UI options of Frederick
+button.iconPosition=left
+button.iconText=text and icon
+button.iconSize=small
+gridPanel.tableBorders=enabled
+map.image.display=yes
+map.displayCurrentRoutes=yes
+map.highlightHexes=yes
diff --git a/data/profiles/root.profile b/data/profiles/root.profile
new file mode 100644
index 0000000..a553e4c
--- /dev/null
+++ b/data/profiles/root.profile
@@ -0,0 +1,62 @@
+### Root profile defines the settings used for all (predefined) default profiles
+### All others define only deviations
+
+### Panel General
+locale=en_US
+default_game=1830
+default_players=
+local.player.names=
+
+### Panel Save
+save.directory=
+save.filename.date_time_pattern=yyyyMMdd_HHmm
+save.filename.date_time_zone=UTC
+save.filename.suffix=NEXT_PLAYER
+save.filename.extension=rails
+save.recovery.active=no
+save.recovery.filepath=18xx_autosave.rails
+
+### Panel Font
+font.ui.scale=1
+font.ui.name=
+font.ui.style=bold
+
+### Panel Map
+map.autoscroll=yes
+map.defaultZoomFitOption=none
+map.displayCurrentRoutes=no
+map.highlightHexes=no
+map.image.display=no
+map.zoomstep=10
+
+### Panel Windows
+or.window.dockablePanels=no
+report.window.type=dynamic
+report.window.open=yes
+report.window.editable=no
+stockchart.window.open=yes
+
+### Panel Format
+money_format=
+or.number_format=composite
+
+### Panel Appearance
+button.iconText=only text
+button.iconSize=small
+button.iconPosition=left
+gridPanel.tableBorder=disabled
+route.colour.1=00ffff
+route.colour.2=ffc0cb
+route.colour.3=ffa500
+route.colour.4=808080
+
+### Panel Log
+#report.directory=log
+#report.filename.date_time_pattern=yyyyMMdd
+#report.filename.extension=log
+
+### Panel Music
+sound.backgroundMusic=disabled
+
+### Panel SFX
+sound.sfx=disabled
diff --git a/data/profiles/test.profile b/data/profiles/test.profile
index 2b39565..897ee6d 100644
--- a/data/profiles/test.profile
+++ b/data/profiles/test.profile
@@ -3,123 +3,13 @@
# Those are the settings used for automated testing
#
########################################################################
-#
-# Preferred tile format.
-# The only currently supported format is svg. Anything else is ignored.
-#tile.format_preference=svg
-# Root directory for the tile images (just above directory 'tiles').
-# Not required if tile images are provided included in the Rails jar file.
-#tile.root_directory=
-
-### Locale ####
-# Language: two-letter ISO code (lower case; default is en=English).
-# Country: two-letter ISO code (upper case; specifies country
-# (implying a language variant of that country; no default).
-# Locale: concatenation of the above. If present, overrides any of the above.
-# Examples: en, en_US, en_UK, fr_FR, fr_CA.
locale=te_ST
-#language=
-#country=
-### Money display ###
-# Each game has a specific format for monetary amounts (e.g. $100, 100M).
# An overriding format can be specified here, but then applies to all games.
# The @ character must be present and is replaced by the amount.
# Example: �@ to specify a pound sign prefix: �100.
money_format=@
-### Save file directory
-# If the below entry exists, is not empty, and specifies an existing
-# directory, that directory is used as a starting point for any
-# file choosing action for the Save and Load commands.
-# The path may be relative or absolute.
save.directory=test/data
-# The default Save filename is <gamename>_<datetimepattern>.<extension>
-# This name will be initially proposed.
-# As soon as that proposal has been changed once in a Save action,
-# the last used name is always proposed in stead.
-# The default date/time pattern is yyyyMMdd_HHmm
-# The pattern codes are as defined in the Java class
-# SimpleDateFormat (just Google that name to find the codes).
-#save.filename.date_time_pattern=yyyyMMdd_HHmm
-# The default timezone is local time.
-# A specific timezone (such as UTC) can be set; the value must be a Java timezone ID
-#save.filename.date_time_zone=UTC
-# Optionally, a suffix (e.g. player name) can be added after the time stamp
-# with a preceding underscore (which is automatically added)
-# The special value NEXT_PLAYER puts the next moving player name into this spot.
-#save.filename.suffix=NEXT_PLAYER
-# The default extension is .rails
-save.filename.extension=rails
-
-### Game report directory
-# If the below entry exists, is not empty, and specifies an existing
-# directory, a copy of the Game Report (as displayed in the Report Window)
-# will be saved there. The path may be relative or absolute.
-#report.directory=log
-# The default file name includes the game name and the game start time:
-# 18XX_yyyymmdd_hhmm.txt where 18XX is the game name.
-# You can specify different values for the date/time part and teh extension here.
-# The date/time pattern must be as defined in the Java SimpleDateFormat class.
-#report.filename.date_time_pattern=yyyyMMdd
report.filename.extension=report
failed.filename.extension=failed
-
-### Windows
-## Report window visibility
-# By default the report window is hidden when starting or loading a game.
-# This property allows to open it automatically.
-# Valid values are yes and no (default).
-#report.window.open=yes
-## Report window editability
-# Specify if the report window is editable, so you can add your own comments.
-# Valid values are yes and no (default).
-#report.window.editable=yes
-## Stock Chart window visibility
-# By default the stock chart hides at the end of an SR.
-# By specifying "yes" here, the window will not be automatically hidden any more
-#stockchart.window.open=yes
-
-### Player info
-## Default players
-# Comma-separated list of player names.
-# Useful for game testing purposes.
-#default_players=Alice,Bob,Charlie
-#
-## Local player name
-# Useful for distributed usage (Internet, PBEM, cloud storage/dropbox)
-# Required for "request turn" facility with cloud storage (dropbox)
-#local.player.name=Alice
-
-### Default game
-# Name of game selected in the game selection window.
-# Useful for game testing purposes.
-#default_game=1830
-
-### Various options
-# Show simple (ORx) or composite (ORx.x) OR number.
-# Valid values: "simple" and "composite" (default)
-#or.number_format=simple
-
-####################### Log4J properties ##############################
-# For information on how to customise log4j logging, see for instance
-# http://www.vipan.com/htdocs/log4jhelp.html
-# It's a bit outdated: Category is now named Logger,
-# and Priority is now named Level.
-# But it's the best intro I know on how to configure Appenders. (EV)
-#######################################################################
-# Set root logger level to DEBUG and use appender F(file)
-#log4j.debug=true
-log4j.rootLogger=DEBUG, F
-
-# Define the Log file appender
-log4j.appender.F=org.apache.log4j.FileAppender
-
-# Log file properties
-log4j.appender.F.File=test/test.log
-log4j.appender.F.append=false
-
-# Log file layout
-log4j.appender.F.layout=org.apache.log4j.PatternLayout
-log4j.appender.F.layout.ConversionPattern=%-5p %m%n
-################## End of Log4J properties #############################
\ No newline at end of file
diff --git a/rails/common/parser/Config.java b/rails/common/parser/Config.java
index 107e888..296fcb3 100644
--- a/rails/common/parser/Config.java
+++ b/rails/common/parser/Config.java
@@ -55,6 +55,7 @@ public final class Config {
private static Properties userProfiles = new Properties();
private static boolean profilesLoaded = false;
private static String DEFAULT_PROFILE_SELECTION = "default"; // can be overwritten
+ private static final String ROOT_PROFILE_SELECTION = ".root"; // used for the 3-tier structure: ROOT-DEFAULT-USER
private static final String TEST_PROFILE_SELECTION = ".test"; // used as default profile for integration tests
private static final String STANDARD_PROFILE_SELECTION = "user";
private static final String DEFAULTPROFILE_PROPERTY = "default.profile";
@@ -65,7 +66,8 @@ public final class Config {
private static boolean legacyConfigFile;
/** properties storage. */
- private static Properties defaultProperties = new Properties();
+ private static Properties rootProperties = null;
+ private static Properties defaultProperties = null;
private static Properties userProperties = new Properties();
private static boolean propertiesLoaded = false;
@@ -191,6 +193,7 @@ public final class Config {
}
if (userProperties.containsKey(key)) return userProperties.getProperty(key).trim();
if (defaultProperties.containsKey(key)) return defaultProperties.getProperty(key).trim();
+ if (rootProperties.containsKey(key)) return rootProperties.getProperty(key).trim();
return defaultValue;
}
@@ -497,9 +500,8 @@ public final class Config {
* if not defined or loadable, creates a default user profile
*/
private static void loadProfile(String userProfile) {
- // reset properties
+ // reset user properties
userProperties = new Properties();
- defaultProperties = new Properties();
String userConfigFile = null;
if (Util.hasValue(userProfile)) {
@@ -524,7 +526,7 @@ public final class Config {
/**
* loads the associated default profile
- * if none is defined, uses standard default profile
+ * the default profile is defined as delta to the root profile
*/
private static void loadDefaultProfile() {
String defaultConfigFile = null;
@@ -536,6 +538,11 @@ public final class Config {
defaultConfigFile = defaultProfiles.getProperty(DEFAULT_PROFILE_SELECTION);
userProperties.setProperty(DEFAULTPROFILE_PROPERTY, DEFAULT_PROFILE_SELECTION);
}
+ if (rootProperties == null) {
+ rootProperties = new Properties();
+ loadPropertyFile(rootProperties, defaultProfiles.getProperty(ROOT_PROFILE_SELECTION), true);
+ }
+ defaultProperties = new Properties();
loadPropertyFile(defaultProperties, defaultConfigFile, true);
}
|
|
From: Erik V. <ev...@us...> - 2012-02-16 15:35:33
|
rails/game/GameManager.java | 7
rails/game/GameManagerI.java | 4
rails/game/specific/_1835/StartRound_1835.java | 16 -
test/data/test/1835_NatSingleShare.report | 339 +++++++++++++++++++---
test/data/test/1835_SwapPresForDoubleShare.report | 339 +++++++++++++++++++---
5 files changed, 629 insertions(+), 76 deletions(-)
New commits:
commit f311be5af549febd7e4d81cefaf2097c0d07c7e6
Merge: 190aa16 366e5cf
Author: Erik Vos <eri...@xs...>
Date: Thu Feb 16 16:35:19 2012 +0100
Merge branch 'master' of ssh://rails.git.sourceforge.net/gitroot/rails/rails
commit 190aa165b93f5a1ab9b4454d9906e6ddb1979e99
Author: Erik Vos <eri...@xs...>
Date: Thu Feb 16 16:32:58 2012 +0100
Fixed start round number management for 1835 JUnit testing.
The start round number has been moved from StartRound_1835 to GameManager and is now a generic feature, though it is only used yet in 1835.
It is no longer Java-static.
The same applies to the turn number, which stayed in StartRound_1835.
The NatDoubleShare test case now works.
The NatSingleShare and SwapPresForDoubleShare cases were wrong and have been replaced.
diff --git a/rails/game/GameManager.java b/rails/game/GameManager.java
index f35ed6a..c147924 100644
--- a/rails/game/GameManager.java
+++ b/rails/game/GameManager.java
@@ -110,6 +110,9 @@ public class GameManager implements ConfigurableComponentI, GameManagerI {
protected State currentRound = new State("CurrentRound", Round.class);
protected RoundI interruptedRound = null;
+ /** Number of the current start round. Currently only used in some 1835 variants. */
+ protected IntegerState startRoundNumber = new IntegerState ("StartRoundNumber", 0);
+
protected IntegerState srNumber = new IntegerState ("SRNumber");
protected IntegerState absoluteORNumber =
@@ -721,6 +724,7 @@ public class GameManager implements ConfigurableComponentI, GameManagerI {
System.exit(1);
}
StartRound startRound = createRound (startRoundClass);
+ startRoundNumber.add(1);
startRound.start ();
}
@@ -805,6 +809,9 @@ public class GameManager implements ConfigurableComponentI, GameManagerI {
return numOfORs.getText();
}
+ public int getStartRoundNumber () {
+ return startRoundNumber.intValue();
+ }
/* (non-Javadoc)
* @see rails.game.GameManagerI#getSRNumber()
*/
diff --git a/rails/game/GameManagerI.java b/rails/game/GameManagerI.java
index 06b404c..92f2a88 100644
--- a/rails/game/GameManagerI.java
+++ b/rails/game/GameManagerI.java
@@ -41,6 +41,8 @@ public interface GameManagerI extends MoveableHolder, ConfigurableComponentI {
public int getRelativeORNumber();
public int getAbsoluteORNumber ();
+ public int getStartRoundNumber ();
+
public abstract int getSRNumber();
public abstract void startShareSellingRound(Player player, int cashToRaise,
@@ -101,7 +103,7 @@ public interface GameManagerI extends MoveableHolder, ConfigurableComponentI {
public abstract RoundI getCurrentRound();
public abstract ModelObject getCurrentRoundModel();
-
+
public abstract ModelObject getCurrentPlayerModel();
/**
diff --git a/rails/game/specific/_1835/StartRound_1835.java b/rails/game/specific/_1835/StartRound_1835.java
index 0768fce..f0f6b98 100644
--- a/rails/game/specific/_1835/StartRound_1835.java
+++ b/rails/game/specific/_1835/StartRound_1835.java
@@ -16,10 +16,7 @@ import rails.game.state.IntegerState;
public class StartRound_1835 extends StartRound {
/* To control the player sequence in the Clemens and Snake variants */
- private static IntegerState turn = new IntegerState("TurnNumber", 0);
-
- private static IntegerState startRoundNumber =
- new IntegerState("StartRoundNumber", 0);
+ private IntegerState turn = new IntegerState("TurnNumber", 0);
/* Additional variants */
public static final String CLEMENS_VARIANT = "Clemens";
@@ -41,7 +38,6 @@ public class StartRound_1835 extends StartRound {
@Override
public void start() {
super.start();
- startRoundNumber.add(1);
if (variant.equalsIgnoreCase(CLEMENS_VARIANT)) {
setCurrentPlayerIndex (numPlayers-1);
@@ -173,7 +169,7 @@ public class StartRound_1835 extends StartRound {
/* Select the player that has the turn. */
- if (startRoundNumber.intValue() == 1) {
+ if (gameManager.getStartRoundNumber() == 1) {
/*
* Some variants have a reversed player order in the first or second
* cycle of the first round (a cycle spans one turn of all players).
@@ -203,9 +199,11 @@ public class StartRound_1835 extends StartRound {
setCurrentPlayerIndex(newIndex);
Player newPlayer = getCurrentPlayer();
log.debug("Game turn has moved from " + oldPlayer.getName()
- + " to " + newPlayer.getName() + " [startRound="
- + startRoundNumber + " cycle=" + cycleNumber + " turn="
- + turnNumber + " newIndex=" + newIndex + "]");
+ + " to " + newPlayer.getName()
+ + " [startRound=" + gameManager.getStartRoundNumber()
+ + " cycle=" + cycleNumber
+ + " turn=" + turnNumber
+ + " newIndex=" + newIndex + "]");
} else {
diff --git a/test/data/test/1835_NatSingleShare.report b/test/data/test/1835_NatSingleShare.report
index f1eadbb..a7d01c4 100644
--- a/test/data/test/1835_NatSingleShare.report
+++ b/test/data/test/1835_NatSingleShare.report
@@ -10,43 +10,43 @@ StartOfInitialRound
HasPriority,T1
BuysItemFor,T3,M5,80
FloatsWithCash,M5,80
-BuysItemFor,T1,M1,80
+BuysItemFor,T2,M1,80
FloatsWithCash,M1,80
-BuysItemFor,T2,M3,80
+BuysItemFor,T1,M3,80
FloatsWithCash,M3,80
-BuysItemFor,T3,M6,80
+BuysItemFor,T1,M6,80
FloatsWithCash,M6,80
-BuysItemFor,T1,M2,170
+BuysItemFor,T2,M2,170
FloatsWithCash,M2,170
-BuysItemFor,T2,PRES_CERT_NAME,BY,20,184
-BuysItemFor,T3,LD,190
-ALSO_GETS,T3,PRES_CERT_NAME,SX,20
-BuysItemFor,T1,HB,160
-BuysItemFor,T2,OBB,120
+BuysItemFor,T3,PRES_CERT_NAME,BY,20,184
+BuysItemFor,T1,LD,190
+ALSO_GETS,T1,PRES_CERT_NAME,SX,20
+BuysItemFor,T2,HB,160
+BuysItemFor,T3,OBB,120
+ALSO_GETS,T3,CERT_NAME,BY,10
+BuysItemFor,T1,BB,130
+BuysItemFor,T2,NF,100
ALSO_GETS,T2,CERT_NAME,BY,10
-BuysItemFor,T3,BB,130
-BuysItemFor,T1,NF,100
-ALSO_GETS,T1,CERT_NAME,BY,10
-BuysItemFor,T2,M4,160
+BuysItemFor,T3,M4,160
FloatsWithCash,M4,160
-CannotBuyAnything,T3
CannotBuyAnything,T1
CannotBuyAnything,T2
+CannotBuyAnything,T3
Has,M1,80
Has,M2,170
Has,M3,80
Has,M4,160
Has,M5,80
Has,M6,80
-Has,T1,90
-Has,T2,56
-Has,T3,120
+Has,T1,120
+Has,T2,90
+Has,T3,56
START_OR,0.0
-ReceivesFor,T1,5,NF
-ReceivesFor,T2,10,OBB
-ReceivesFor,T3,20,LD
-ReceivesFor,T3,25,BB
-ReceivesFor,T1,30,HB
+ReceivesFor,T2,5,NF
+ReceivesFor,T3,10,OBB
+ReceivesFor,T1,20,LD
+ReceivesFor,T1,25,BB
+ReceivesFor,T2,30,HB
ShortORExecuted
Has,M1,80
Has,M2,170
@@ -54,13 +54,14 @@ Has,M3,80
Has,M4,160
Has,M5,80
Has,M6,80
-Has,T1,125
-Has,T2,66
-Has,T3,165
+Has,T1,165
+Has,T2,125
+Has,T3,66
StartOfInitialRound
-HasPriority,T3
-BuysItemFor,T3,PfB,150
-ALSO_GETS,T3,CERT_NAME,BY,10
+HasPriority,T1
+CannotBuyAnything,T3
+BuysItemFor,T1,PfB,150
+ALSO_GETS,T1,CERT_NAME,BY,10
FloatsWithCash,BY,460
Has,M1,80
Has,M2,170
@@ -69,9 +70,281 @@ Has,M4,160
Has,M5,80
Has,M6,80
Has,BY,460
-Has,T1,125
-Has,T2,66
-Has,T3,15
+Has,T1,15
+Has,T2,125
+Has,T3,66
StartStockRound,1
-HasPriority,T1
-LoadInterrupted,13
+HasPriority,T2
+BUY_SHARE_LOG,T2,10,BY,IPO,92
+PriceIsPaidTo,92,BY
+PASSES,T3
+PASSES,T1
+PASSES,T2
+
+END_SR,1
+Has,M1,80
+Has,M2,170
+Has,M3,80
+Has,M4,160
+Has,M5,80
+Has,M6,80
+Has,BY,552
+Has,T1,15
+Has,T2,33
+Has,T3,66
+START_OR,1.1
+ReceivesFor,T2,5,NF
+ReceivesFor,T3,10,OBB
+ReceivesFor,T1,15,PfB
+ReceivesFor,T1,20,LD
+ReceivesFor,T1,25,BB
+ReceivesFor,T2,30,HB
+
+CompanyOperates,M1,T2
+LaysTileAt,M1,201,H2,SW
+CompanyDoesNotPayDividend,M1
+BuysTrain,M1,2,IPO,80
+FirstTrainBought,2
+
+CompanyOperates,M2,T2
+LaysTileAt,M2,8,E17,NW
+CompanyDoesNotPayDividend,M2
+BuysTrain,M2,2,IPO,80
+
+CompanyOperates,M3,T1
+LaysTileAt,M3,6,F14,NW
+CompanyDoesNotPayDividend,M3
+BuysTrain,M3,2,IPO,80
+
+CompanyOperates,M4,T3
+LaysTileAt,M4,57,G5,SW
+CompanyDoesNotPayDividend,M4
+BuysTrain,M4,2,IPO,80
+BuysTrain,M4,2,IPO,80
+
+CompanyOperates,M5,T3
+LaysTileAt,M5,8,D18,NE
+CompanyDoesNotPayDividend,M5
+BuysTrain,M5,2,IPO,80
+
+CompanyOperates,M6,T1
+LaysTileAt,M6,9,B10,NW
+CompanyDoesNotPayDividend,M6
+BuysTrain,M6,2,IPO,80
+
+CompanyOperates,BY,T3
+LaysTileAt,BY,202,O15,E
+LaysTileAt,BY,8,O13,NW
+CompanyDoesNotPayDividend,BY
+PRICE_MOVES_LOG,BY,92,C3,86,B3
+BuysTrain,BY,2,IPO,80
+BuysTrain,BY,2,IPO,80
+All 2-trains are sold out, 2+2-trains now available
+BuysTrain,BY,2+2,IPO,120
+FirstTrainBought,2+2
+
+EndOfOperatingRound,1.1
+ORWorthIncrease,T1,1.1,54
+ORWorthIncrease,T2,1.1,23
+ORWorthIncrease,T3,1.1,-8
+Has,M1,0
+Has,M2,90
+Has,M3,0
+Has,M4,0
+Has,M5,0
+Has,M6,0
+Has,BY,272
+Has,T1,75
+Has,T2,68
+Has,T3,76
+StartStockRound,2
+HasPriority,T3
+PASSES,T3
+PASSES,T1
+PASSES,T2
+
+END_SR,2
+Has,M1,0
+Has,M2,90
+Has,M3,0
+Has,M4,0
+Has,M5,0
+Has,M6,0
+Has,BY,272
+Has,T1,75
+Has,T2,68
+Has,T3,76
+START_OR,2.1
+ReceivesFor,T2,5,NF
+ReceivesFor,T3,10,OBB
+ReceivesFor,T1,15,PfB
+ReceivesFor,T1,20,LD
+ReceivesFor,T1,25,BB
+ReceivesFor,T2,30,HB
+
+CompanyOperates,M1,T2
+LaysTileAt,M1,9,J2,NW
+CompanyRevenue,M1,40
+CompanySplits,M1,40
+M1 receives 20
+Payout,T2,20,1,100
+
+CompanyOperates,M2,T2
+LaysTileAt,M2,8,D16,SE
+CompanyRevenue,M2,0
+CompanyDoesNotPayDividend,M2
+
+CompanyOperates,M3,T1
+LaysTileAt,M3,4,G15,NW
+CompanyRevenue,M3,40
+CompanySplits,M3,40
+M3 receives 20
+Payout,T1,20,1,100
+
+CompanyOperates,M4,T3
+LaysTileAt,M4,2,H4,NE
+CompanyRevenue,M4,30
+CompanySplits,M4,30
+M4 receives 15
+Payout,T3,15,1,100
+
+CompanyOperates,M5,T3
+LaysTileAt,M5,8,C19,E
+CompanyRevenue,M5,50
+CompanySplits,M5,50
+M5 receives 25
+Payout,T3,25,1,100
+
+CompanyOperates,M6,T1
+LaysTileAt,M6,6,A11,NW
+CompanyRevenue,M6,60
+CompanySplits,M6,60
+M6 receives 30
+Payout,T1,30,1,100
+
+CompanyOperates,BY,T3
+LaysTileAt,BY,8,N16,SW
+LaysTileAt,BY,4,M15,NW
+LaysTileAt,BY,6,N12,NW
+LAYS_TOKEN_ON,BY,L14,60
+CompanyRevenue,BY,130
+CompanyPaysOutFull,BY,130
+Payout,T1,13,1,10
+Payout,T2,26,2,10
+Payout,T3,39,3,10
+PRICE_MOVES_LOG,BY,86,B3,92,C3
+
+EndOfOperatingRound,2.1
+ORWorthIncrease,T1,2.1,129
+ORWorthIncrease,T2,2.1,93
+ORWorthIncrease,T3,2.1,107
+Has,M1,20
+Has,M2,90
+Has,M3,20
+Has,M4,15
+Has,M5,25
+Has,M6,30
+Has,BY,212
+Has,T1,198
+Has,T2,149
+Has,T3,165
+StartStockRound,3
+HasPriority,T3
+BUY_SHARE_LOG,T3,10,BY,IPO,92
+PriceIsPaidTo,92,BY
+BUY_SHARE_LOG,T1,10,BY,IPO,92
+PriceIsPaidTo,92,BY
+BUY_SHARE_LOG,T2,10,BY,IPO,92
+PriceIsPaidTo,92,BY
+PASSES,T3
+BUY_SHARE_LOG,T1,10,BY,IPO,92
+PriceIsPaidTo,92,BY
+SELL_SHARE_LOG,T1,10,BY,92
+PRICE_MOVES_LOG,BY,92,C3,88,C4
+PASSES,T2
+PASSES,T3
+SELL_SHARE_LOG,T1,10,BY,88
+PRICE_MOVES_LOG,BY,88,C4,86,C5
+BUY_SHARE_LOG,T1,10,SX,IPO,88
+PASSES,T2
+PASSES,T3
+SELL_SHARE_LOG,T1,10,BY,86
+PRICE_MOVES_LOG,BY,86,C5,82,C6
+BUY_SHARE_LOG,T1,10,SX,IPO,88
+PASSES,T2
+PASSES,T3
+BUY_SHARE_LOG,T1,10,SX,IPO,88
+FloatsWithCash,SX,440
+PASSES,T2
+PASSES,T3
+PASSES,T1
+
+END_SR,3
+Has,M1,20
+Has,M2,90
+Has,M3,20
+Has,M4,15
+Has,M5,25
+Has,M6,30
+Has,BY,580
+Has,SX,440
+Has,T1,16
+Has,T2,57
+Has,T3,73
+START_OR,3.1
+ReceivesFor,T2,5,NF
+ReceivesFor,T3,10,OBB
+ReceivesFor,T1,15,PfB
+ReceivesFor,T1,20,LD
+ReceivesFor,T1,25,BB
+ReceivesFor,T2,30,HB
+
+CompanyOperates,M1,T2
+LaysTileAt,M1,4,K3,NW
+CompanyRevenue,M1,40
+CompanySplits,M1,40
+M1 receives 20
+Payout,T2,20,1,100
+
+CompanyOperates,M2,T2
+LaysTileAtFor,M2,8,D14,NW,50
+CompanyRevenue,M2,70
+CompanySplits,M2,70
+M2 receives 35
+Payout,T2,35,1,100
+
+CompanyOperates,M3,T1
+LaysTileAt,M3,57,H16,NW
+CompanyRevenue,M3,40
+CompanySplits,M3,40
+M3 receives 20
+Payout,T1,20,1,100
+
+CompanyOperates,M4,T3
+LaysTileAt,M4,58,F6,E
+CompanyRevenue,M4,60
+CompanySplits,M4,60
+M4 receives 30
+Payout,T3,30,1,100
+
+CompanyOperates,M5,T3
+CompanyRevenue,M5,50
+CompanySplits,M5,50
+M5 receives 25
+Payout,T3,25,1,100
+
+CompanyOperates,M6,T1
+LaysTileAt,M6,58,B12,SW
+CompanyRevenue,M6,60
+CompanySplits,M6,60
+M6 receives 30
+Payout,T1,30,1,100
+
+CompanyOperates,SX,T1
+LaysTileAt,SX,56,I17,NE
+LaysTileAt,SX,202,H20,W
+CompanyDoesNotPayDividend,SX
+PRICE_MOVES_LOG,SX,88,C4,84,B4
+
+CompanyOperates,BY,T3
+LoadInterrupted,121
diff --git a/test/data/test/1835_SwapPresForDoubleShare.report b/test/data/test/1835_SwapPresForDoubleShare.report
index f1eadbb..a7d01c4 100644
--- a/test/data/test/1835_SwapPresForDoubleShare.report
+++ b/test/data/test/1835_SwapPresForDoubleShare.report
@@ -10,43 +10,43 @@ StartOfInitialRound
HasPriority,T1
BuysItemFor,T3,M5,80
FloatsWithCash,M5,80
-BuysItemFor,T1,M1,80
+BuysItemFor,T2,M1,80
FloatsWithCash,M1,80
-BuysItemFor,T2,M3,80
+BuysItemFor,T1,M3,80
FloatsWithCash,M3,80
-BuysItemFor,T3,M6,80
+BuysItemFor,T1,M6,80
FloatsWithCash,M6,80
-BuysItemFor,T1,M2,170
+BuysItemFor,T2,M2,170
FloatsWithCash,M2,170
-BuysItemFor,T2,PRES_CERT_NAME,BY,20,184
-BuysItemFor,T3,LD,190
-ALSO_GETS,T3,PRES_CERT_NAME,SX,20
-BuysItemFor,T1,HB,160
-BuysItemFor,T2,OBB,120
+BuysItemFor,T3,PRES_CERT_NAME,BY,20,184
+BuysItemFor,T1,LD,190
+ALSO_GETS,T1,PRES_CERT_NAME,SX,20
+BuysItemFor,T2,HB,160
+BuysItemFor,T3,OBB,120
+ALSO_GETS,T3,CERT_NAME,BY,10
+BuysItemFor,T1,BB,130
+BuysItemFor,T2,NF,100
ALSO_GETS,T2,CERT_NAME,BY,10
-BuysItemFor,T3,BB,130
-BuysItemFor,T1,NF,100
-ALSO_GETS,T1,CERT_NAME,BY,10
-BuysItemFor,T2,M4,160
+BuysItemFor,T3,M4,160
FloatsWithCash,M4,160
-CannotBuyAnything,T3
CannotBuyAnything,T1
CannotBuyAnything,T2
+CannotBuyAnything,T3
Has,M1,80
Has,M2,170
Has,M3,80
Has,M4,160
Has,M5,80
Has,M6,80
-Has,T1,90
-Has,T2,56
-Has,T3,120
+Has,T1,120
+Has,T2,90
+Has,T3,56
START_OR,0.0
-ReceivesFor,T1,5,NF
-ReceivesFor,T2,10,OBB
-ReceivesFor,T3,20,LD
-ReceivesFor,T3,25,BB
-ReceivesFor,T1,30,HB
+ReceivesFor,T2,5,NF
+ReceivesFor,T3,10,OBB
+ReceivesFor,T1,20,LD
+ReceivesFor,T1,25,BB
+ReceivesFor,T2,30,HB
ShortORExecuted
Has,M1,80
Has,M2,170
@@ -54,13 +54,14 @@ Has,M3,80
Has,M4,160
Has,M5,80
Has,M6,80
-Has,T1,125
-Has,T2,66
-Has,T3,165
+Has,T1,165
+Has,T2,125
+Has,T3,66
StartOfInitialRound
-HasPriority,T3
-BuysItemFor,T3,PfB,150
-ALSO_GETS,T3,CERT_NAME,BY,10
+HasPriority,T1
+CannotBuyAnything,T3
+BuysItemFor,T1,PfB,150
+ALSO_GETS,T1,CERT_NAME,BY,10
FloatsWithCash,BY,460
Has,M1,80
Has,M2,170
@@ -69,9 +70,281 @@ Has,M4,160
Has,M5,80
Has,M6,80
Has,BY,460
-Has,T1,125
-Has,T2,66
-Has,T3,15
+Has,T1,15
+Has,T2,125
+Has,T3,66
StartStockRound,1
-HasPriority,T1
-LoadInterrupted,13
+HasPriority,T2
+BUY_SHARE_LOG,T2,10,BY,IPO,92
+PriceIsPaidTo,92,BY
+PASSES,T3
+PASSES,T1
+PASSES,T2
+
+END_SR,1
+Has,M1,80
+Has,M2,170
+Has,M3,80
+Has,M4,160
+Has,M5,80
+Has,M6,80
+Has,BY,552
+Has,T1,15
+Has,T2,33
+Has,T3,66
+START_OR,1.1
+ReceivesFor,T2,5,NF
+ReceivesFor,T3,10,OBB
+ReceivesFor,T1,15,PfB
+ReceivesFor,T1,20,LD
+ReceivesFor,T1,25,BB
+ReceivesFor,T2,30,HB
+
+CompanyOperates,M1,T2
+LaysTileAt,M1,201,H2,SW
+CompanyDoesNotPayDividend,M1
+BuysTrain,M1,2,IPO,80
+FirstTrainBought,2
+
+CompanyOperates,M2,T2
+LaysTileAt,M2,8,E17,NW
+CompanyDoesNotPayDividend,M2
+BuysTrain,M2,2,IPO,80
+
+CompanyOperates,M3,T1
+LaysTileAt,M3,6,F14,NW
+CompanyDoesNotPayDividend,M3
+BuysTrain,M3,2,IPO,80
+
+CompanyOperates,M4,T3
+LaysTileAt,M4,57,G5,SW
+CompanyDoesNotPayDividend,M4
+BuysTrain,M4,2,IPO,80
+BuysTrain,M4,2,IPO,80
+
+CompanyOperates,M5,T3
+LaysTileAt,M5,8,D18,NE
+CompanyDoesNotPayDividend,M5
+BuysTrain,M5,2,IPO,80
+
+CompanyOperates,M6,T1
+LaysTileAt,M6,9,B10,NW
+CompanyDoesNotPayDividend,M6
+BuysTrain,M6,2,IPO,80
+
+CompanyOperates,BY,T3
+LaysTileAt,BY,202,O15,E
+LaysTileAt,BY,8,O13,NW
+CompanyDoesNotPayDividend,BY
+PRICE_MOVES_LOG,BY,92,C3,86,B3
+BuysTrain,BY,2,IPO,80
+BuysTrain,BY,2,IPO,80
+All 2-trains are sold out, 2+2-trains now available
+BuysTrain,BY,2+2,IPO,120
+FirstTrainBought,2+2
+
+EndOfOperatingRound,1.1
+ORWorthIncrease,T1,1.1,54
+ORWorthIncrease,T2,1.1,23
+ORWorthIncrease,T3,1.1,-8
+Has,M1,0
+Has,M2,90
+Has,M3,0
+Has,M4,0
+Has,M5,0
+Has,M6,0
+Has,BY,272
+Has,T1,75
+Has,T2,68
+Has,T3,76
+StartStockRound,2
+HasPriority,T3
+PASSES,T3
+PASSES,T1
+PASSES,T2
+
+END_SR,2
+Has,M1,0
+Has,M2,90
+Has,M3,0
+Has,M4,0
+Has,M5,0
+Has,M6,0
+Has,BY,272
+Has,T1,75
+Has,T2,68
+Has,T3,76
+START_OR,2.1
+ReceivesFor,T2,5,NF
+ReceivesFor,T3,10,OBB
+ReceivesFor,T1,15,PfB
+ReceivesFor,T1,20,LD
+ReceivesFor,T1,25,BB
+ReceivesFor,T2,30,HB
+
+CompanyOperates,M1,T2
+LaysTileAt,M1,9,J2,NW
+CompanyRevenue,M1,40
+CompanySplits,M1,40
+M1 receives 20
+Payout,T2,20,1,100
+
+CompanyOperates,M2,T2
+LaysTileAt,M2,8,D16,SE
+CompanyRevenue,M2,0
+CompanyDoesNotPayDividend,M2
+
+CompanyOperates,M3,T1
+LaysTileAt,M3,4,G15,NW
+CompanyRevenue,M3,40
+CompanySplits,M3,40
+M3 receives 20
+Payout,T1,20,1,100
+
+CompanyOperates,M4,T3
+LaysTileAt,M4,2,H4,NE
+CompanyRevenue,M4,30
+CompanySplits,M4,30
+M4 receives 15
+Payout,T3,15,1,100
+
+CompanyOperates,M5,T3
+LaysTileAt,M5,8,C19,E
+CompanyRevenue,M5,50
+CompanySplits,M5,50
+M5 receives 25
+Payout,T3,25,1,100
+
+CompanyOperates,M6,T1
+LaysTileAt,M6,6,A11,NW
+CompanyRevenue,M6,60
+CompanySplits,M6,60
+M6 receives 30
+Payout,T1,30,1,100
+
+CompanyOperates,BY,T3
+LaysTileAt,BY,8,N16,SW
+LaysTileAt,BY,4,M15,NW
+LaysTileAt,BY,6,N12,NW
+LAYS_TOKEN_ON,BY,L14,60
+CompanyRevenue,BY,130
+CompanyPaysOutFull,BY,130
+Payout,T1,13,1,10
+Payout,T2,26,2,10
+Payout,T3,39,3,10
+PRICE_MOVES_LOG,BY,86,B3,92,C3
+
+EndOfOperatingRound,2.1
+ORWorthIncrease,T1,2.1,129
+ORWorthIncrease,T2,2.1,93
+ORWorthIncrease,T3,2.1,107
+Has,M1,20
+Has,M2,90
+Has,M3,20
+Has,M4,15
+Has,M5,25
+Has,M6,30
+Has,BY,212
+Has,T1,198
+Has,T2,149
+Has,T3,165
+StartStockRound,3
+HasPriority,T3
+BUY_SHARE_LOG,T3,10,BY,IPO,92
+PriceIsPaidTo,92,BY
+BUY_SHARE_LOG,T1,10,BY,IPO,92
+PriceIsPaidTo,92,BY
+BUY_SHARE_LOG,T2,10,BY,IPO,92
+PriceIsPaidTo,92,BY
+PASSES,T3
+BUY_SHARE_LOG,T1,10,BY,IPO,92
+PriceIsPaidTo,92,BY
+SELL_SHARE_LOG,T1,10,BY,92
+PRICE_MOVES_LOG,BY,92,C3,88,C4
+PASSES,T2
+PASSES,T3
+SELL_SHARE_LOG,T1,10,BY,88
+PRICE_MOVES_LOG,BY,88,C4,86,C5
+BUY_SHARE_LOG,T1,10,SX,IPO,88
+PASSES,T2
+PASSES,T3
+SELL_SHARE_LOG,T1,10,BY,86
+PRICE_MOVES_LOG,BY,86,C5,82,C6
+BUY_SHARE_LOG,T1,10,SX,IPO,88
+PASSES,T2
+PASSES,T3
+BUY_SHARE_LOG,T1,10,SX,IPO,88
+FloatsWithCash,SX,440
+PASSES,T2
+PASSES,T3
+PASSES,T1
+
+END_SR,3
+Has,M1,20
+Has,M2,90
+Has,M3,20
+Has,M4,15
+Has,M5,25
+Has,M6,30
+Has,BY,580
+Has,SX,440
+Has,T1,16
+Has,T2,57
+Has,T3,73
+START_OR,3.1
+ReceivesFor,T2,5,NF
+ReceivesFor,T3,10,OBB
+ReceivesFor,T1,15,PfB
+ReceivesFor,T1,20,LD
+ReceivesFor,T1,25,BB
+ReceivesFor,T2,30,HB
+
+CompanyOperates,M1,T2
+LaysTileAt,M1,4,K3,NW
+CompanyRevenue,M1,40
+CompanySplits,M1,40
+M1 receives 20
+Payout,T2,20,1,100
+
+CompanyOperates,M2,T2
+LaysTileAtFor,M2,8,D14,NW,50
+CompanyRevenue,M2,70
+CompanySplits,M2,70
+M2 receives 35
+Payout,T2,35,1,100
+
+CompanyOperates,M3,T1
+LaysTileAt,M3,57,H16,NW
+CompanyRevenue,M3,40
+CompanySplits,M3,40
+M3 receives 20
+Payout,T1,20,1,100
+
+CompanyOperates,M4,T3
+LaysTileAt,M4,58,F6,E
+CompanyRevenue,M4,60
+CompanySplits,M4,60
+M4 receives 30
+Payout,T3,30,1,100
+
+CompanyOperates,M5,T3
+CompanyRevenue,M5,50
+CompanySplits,M5,50
+M5 receives 25
+Payout,T3,25,1,100
+
+CompanyOperates,M6,T1
+LaysTileAt,M6,58,B12,SW
+CompanyRevenue,M6,60
+CompanySplits,M6,60
+M6 receives 30
+Payout,T1,30,1,100
+
+CompanyOperates,SX,T1
+LaysTileAt,SX,56,I17,NE
+LaysTileAt,SX,202,H20,W
+CompanyDoesNotPayDividend,SX
+PRICE_MOVES_LOG,SX,88,C4,84,B4
+
+CompanyOperates,BY,T3
+LoadInterrupted,121
|
|
From: Frederick W. <fre...@us...> - 2012-02-15 19:16:37
|
data/profiles/default.profile | 28 +++++++++++++++++++++++-----
1 file changed, 23 insertions(+), 5 deletions(-)
New commits:
commit 366e5cfc52cdc0df0627a5854984389d17b90be5
Author: Frederick Weld <fre...@gm...>
Date: Wed Feb 15 20:14:14 2012 +0100
Updated default profile with all recent config changes
diff --git a/data/profiles/default.profile b/data/profiles/default.profile
index 250611d..b4e4cb9 100644
--- a/data/profiles/default.profile
+++ b/data/profiles/default.profile
@@ -13,23 +13,35 @@ save.filename.extension=rails
save.recovery.active=no
save.recovery.filepath=18xx_autosave.rails
-### Panel UI
-report.window.type=dynamic
-report.window.open=yes
-report.window.editable=no
-stockchart.window.open=yes
+### Panel Font
font.ui.scale=1
font.ui.name=
font.ui.style=bold
### Panel Map
map.autoscroll=yes
+map.defaultZoomFitOption=none
+map.displayCurrentRoutes=yes
+map.highlightHexes=yes
map.image.display=no
map.zoomstep=10
+### Panel Windows
+or.window.dockablePanels=no
+report.window.type=dynamic
+report.window.open=yes
+report.window.editable=no
+stockchart.window.open=yes
+
### Panel Format
money_format=
or.number_format=composite
+
+### Panel Appearance
+button.iconText=text and icon
+button.iconSize=small
+button.iconPosition=left
+gridPanel.tableBorders=enabled
route.colour.1=00ffff
route.colour.2=ffc0cb
route.colour.3=ffa500
@@ -39,3 +51,9 @@ route.colour.4=808080
#report.directory=log
#report.filename.date_time_pattern=yyyyMMdd
#report.filename.extension=log
+
+### Panel Music
+sound.backgroundMusic=disabled
+
+### Panel SFX
+sound.sfx=disabled
|
|
From: Stefan F. <ste...@us...> - 2012-02-13 22:26:59
|
data/1856/TileSet.xml | 14 ++---
test/data/bugs/1835_changePresidentAtStart.rails |binary
test/data/bugs/1835_changePresidentAtStart.report | 54 ++++++++++++++++++++++
3 files changed, 61 insertions(+), 7 deletions(-)
New commits:
commit 6ae9b3b88d0ed1ffb3ed0f55eebd04da6b208d23
Author: Bill Rosgen <ro...@gm...>
Date: Tue Feb 7 11:32:44 2012 +0800
1856: fix dit upgrade phases
Signed-off-by: Stefan Frey <ste...@we...>
(cherry picked from commit ebdd8eb314e14eacc48e60bdcd7dc3a63be73812)
diff --git a/data/1856/TileSet.xml b/data/1856/TileSet.xml
index cf36367..f926f6f 100644
--- a/data/1856/TileSet.xml
+++ b/data/1856/TileSet.xml
@@ -28,16 +28,16 @@
<!-- Yellow tiles -->
<Tile id="1" quantity="1">
- <Upgrade id="14" phase="5,6"/>
+ <Upgrade id="14" phase="6,D"/>
</Tile>
<Tile id="2" quantity="1">
- <Upgrade id="15" phase="5,6"/>
+ <Upgrade id="15" phase="6,D"/>
</Tile>
<Tile id="3" quantity="3">
- <Upgrade id="5,7" phase="5,6"/>
+ <Upgrade id="5,7" phase="6,D"/>
</Tile>
<Tile id="4" quantity="3">
- <Upgrade id="57,9" phase="5,6"/>
+ <Upgrade id="57,9" phase="6,D"/>
</Tile>
<Tile id="5" quantity="2">
<Upgrade id="14,15" />
@@ -55,16 +55,16 @@
<Upgrade id="18,19,20,23,24,26,27" />
</Tile>
<Tile id="55" quantity="1">
- <Upgrade id="14" phase="5,6"/>
+ <Upgrade id="14" phase="6,D"/>
</Tile>
<Tile id="56" quantity="1">
- <Upgrade id="15" phase="5,6"/>
+ <Upgrade id="15" phase="6,D"/>
</Tile>
<Tile id="57" quantity="4">
<Upgrade id="14,15" />
</Tile>
<Tile id="58" quantity="3">
- <Upgrade id="6,8" phase="5,6"/>
+ <Upgrade id="6,8" phase="6,D"/>
</Tile>
<Tile id="69" quantity="1" />
commit 89dc9dd5a93ce245a31bc6b836f0497ef92e13f3
Author: Stefan Frey <ste...@we...>
Date: Mon Feb 13 23:25:17 2012 +0100
added 1835 test case that checks that presidency changes during StartRound
diff --git a/test/data/bugs/1835_changePresidentAtStart.rails b/test/data/bugs/1835_changePresidentAtStart.rails
new file mode 100644
index 0000000..a1d91f0
Binary files /dev/null and b/test/data/bugs/1835_changePresidentAtStart.rails differ
diff --git a/test/data/bugs/1835_changePresidentAtStart.report b/test/data/bugs/1835_changePresidentAtStart.report
new file mode 100644
index 0000000..4af4eb4
--- /dev/null
+++ b/test/data/bugs/1835_changePresidentAtStart.report
@@ -0,0 +1,54 @@
+GameIs,1835
+PlayerIs,1,Klaus-Jürgen
+PlayerIs,2,Jupp
+PlayerIs,3,Sven K.
+PlayerIs,4,Volker S.
+PlayerCash,475
+BankHas,10100
+StartOfPhase,2
+BankSizeIs,10100
+StartOfInitialRound
+HasPriority,Klaus-Jürgen
+BuysItemFor,Volker S.,M3,80
+FloatsWithCash,M3,80
+BuysItemFor,Sven K.,M2,170
+FloatsWithCash,M2,170
+BuysItemFor,Jupp,M5,80
+FloatsWithCash,M5,80
+BuysItemFor,Klaus-Jürgen,M1,80
+FloatsWithCash,M1,80
+BuysItemFor,Klaus-Jürgen,M6,80
+FloatsWithCash,M6,80
+BuysItemFor,Jupp,LD,190
+ALSO_GETS,Jupp,PRES_CERT_NAME,SX,20
+BuysItemFor,Sven K.,M4,160
+FloatsWithCash,M4,160
+BuysItemFor,Volker S.,NF,100
+ALSO_GETS,Volker S.,CERT_NAME,BY,10
+BuysItemFor,Klaus-Jürgen,BB,130
+BuysItemFor,Jupp,HB,160
+PASSES,Sven K.
+BuysItemFor,Volker S.,OBB,120
+ALSO_GETS,Volker S.,CERT_NAME,BY,10
+BuysItemFor,Klaus-Jürgen,PRES_CERT_NAME,BY,20,184
+CannotBuyAnything,Jupp
+CannotBuyAnything,Sven K.
+BuysItemFor,Volker S.,PfB,150
+ALSO_GETS,Volker S.,CERT_NAME,BY,10
+FloatsWithCash,BY,460
+IS_NOW_PRES_OF,Volker S.,BY
+Has,M1,80
+Has,M2,170
+Has,M3,80
+Has,M4,160
+Has,M5,80
+Has,M6,80
+Has,BY,460
+Has,Klaus-Jürgen,1
+Has,Jupp,45
+Has,Sven K.,145
+Has,Volker S.,25
+StartStockRound,1
+HasPriority,Klaus-Jürgen
+PASSES,Klaus-Jürgen
+PASSES,Jupp
|
|
From: Stefan F. <ste...@us...> - 2012-02-13 21:52:59
|
dev/null |binary
rails/ui/images/train.png |binary
2 files changed
New commits:
commit 7f69d992ea2f4a1d019748b147f9b44840ae8276
Author: Stefan Frey <ste...@we...>
Date: Mon Feb 13 22:31:25 2012 +0100
fixed type in filename of train.png
diff --git a/rails/ui/images/Train.png b/rails/ui/images/Train.png
deleted file mode 100644
index 0957b13..0000000
Binary files a/rails/ui/images/Train.png and /dev/null differ
diff --git a/rails/ui/images/train.png b/rails/ui/images/train.png
new file mode 100644
index 0000000..0957b13
Binary files /dev/null and b/rails/ui/images/train.png differ
|
|
From: Frederick W. <fre...@us...> - 2012-02-12 17:53:12
|
LocalisedText.properties | 1 +
data/Properties.xml | 2 ++
rails/ui/swing/elements/RailsIconButton.java | 18 ++++++++++++++++++
3 files changed, 21 insertions(+)
New commits:
commit d9c6cff3c38f8348c2725f91699e9be931bd7fc6
Author: Frederick Weld <fre...@gm...>
Date: Sun Feb 12 18:51:42 2012 +0100
Added option to display button icons above icon texts
Motivation: Putting icons above is probably the preferred option if
large icons and small fonts are used.
Further advantage: Icons are horizontally aligned in case of vertical
stacking of command buttons.
diff --git a/LocalisedText.properties b/LocalisedText.properties
index eac4de9..087534b 100644
--- a/LocalisedText.properties
+++ b/LocalisedText.properties
@@ -184,6 +184,7 @@ Config.infoText.sound.sfx.or.buyTrain=<html>Enter assignment of sound effect fil
Config.infoText.sound.sfx.or.setRevenue=<html><ul><li>Only the latter portion of this file is played.<ul><li>For an average revenue, the last third is played.</ul><li>The higher the company's revenue the longer this file is played.<ul><li>But the file is at most played once as a whole.</li></ul></html>
Config.infoText.sound.sfx.sr.newPresident=This also includes becoming the president when buying the president share.
Config.label.button.iconText=Button display type
+Config.label.button.iconPosition=Button icon position relative to text
Config.label.button.iconSize=Button icon size
Config.label.default_game=Default game
Config.label.default_players=Default players
diff --git a/data/Properties.xml b/data/Properties.xml
index c207cbc..9399a9f 100644
--- a/data/Properties.xml
+++ b/data/Properties.xml
@@ -52,6 +52,8 @@
initClass="rails.ui.swing.elements.RailsIconButton" initMethod="resetRailsIcons" initParameter="no" />
<Property name="button.iconSize" type="LIST" values="small,large"
initClass="rails.ui.swing.elements.RailsIconButton" initMethod="resetRailsIcons" initParameter="no" />
+ <Property name="button.iconPosition" type="LIST" values="left,above"
+ initClass="rails.ui.swing.elements.RailsIconButton" initMethod="resetRailsIcons" initParameter="no" />
<Property name="route.colour.1" type="COLOR"
initClass="rails.ui.swing.hexmap.HexMap" initMethod="setRouteColours" />
<Property name="route.colour.2" type="COLOR"
diff --git a/rails/ui/swing/elements/RailsIconButton.java b/rails/ui/swing/elements/RailsIconButton.java
index 3f6d628..fd1d165 100644
--- a/rails/ui/swing/elements/RailsIconButton.java
+++ b/rails/ui/swing/elements/RailsIconButton.java
@@ -9,6 +9,7 @@ import java.util.HashSet;
import java.util.Set;
import javax.swing.JButton;
+import javax.swing.SwingConstants;
import rails.common.parser.Config;
@@ -65,11 +66,23 @@ public class RailsIconButton extends JButton {
*/
private void showRailsIcon() {
if (railsIcon != null) {
+ //set icon/text positioning
+ if (isIconAboveText()) {
+ setVerticalTextPosition(SwingConstants.BOTTOM);
+ setHorizontalTextPosition(SwingConstants.CENTER);
+ } else {
+ setVerticalTextPosition(SwingConstants.CENTER);
+ setHorizontalTextPosition(SwingConstants.TRAILING);
+ }
+
+ //set text
if (isTextEnabled() || railsIcon.largeIcon == null) {
super.setText(railsIcon.description);
} else {
super.setText(null);
}
+
+ //set icon and tool tip text
if (isIconEnabled() || railsIcon.description == null) {
if (isIconSizeSmall()) {
super.setIcon(railsIcon.smallIcon);
@@ -97,6 +110,11 @@ public class RailsIconButton extends JButton {
//small is default
return !"large".equals(Config.get("button.iconSize"));
}
+
+ private boolean isIconAboveText() {
+ //left of text is default
+ return "above".equals(Config.get("button.iconPosition"));
+ }
/**
* Should only be used if an arbitrary text is to displayed without icon.
|
|
From: Frederick W. <fre...@us...> - 2012-02-12 09:39:03
|
rails/ui/swing/ORPanel.java | 20 +++++++++++
rails/ui/swing/ORWindow.java | 6 ++-
rails/ui/swing/UpgradesPanel.java | 64 +++++++++++++++++++++++++++++---------
3 files changed, 74 insertions(+), 16 deletions(-)
New commits:
commit 223e9fc1754a08fd2eca8aba99b63fb9aeb1bd45
Author: Frederick Weld <fre...@gm...>
Date: Sun Feb 12 10:37:37 2012 +0100
Moved upgrade panel buttons to ORPanel button panel (dockable layout only)
diff --git a/rails/ui/swing/ORPanel.java b/rails/ui/swing/ORPanel.java
index 0dd18ce..58d4967 100644
--- a/rails/ui/swing/ORPanel.java
+++ b/rails/ui/swing/ORPanel.java
@@ -1366,4 +1366,24 @@ implements ActionListener, KeyListener, RevenueListener {
public JMenuBar getMenuBar() {
return menuBar;
}
+
+ /**
+ * Adds buttons to the button panel (adjusting their size to the standard size)
+ * @param index The position where to add the buttons
+ */
+ public void addToButtonPanel(RailsIconButton[] buttons, int index) {
+ //get standard size
+ Dimension standardSize = null;
+ Component[] existingButtons = buttonPanel.getComponents();
+ if (existingButtons != null && existingButtons.length > 0) {
+ standardSize = existingButtons[0].getPreferredSize();
+ }
+
+ //apply sizing to new buttons
+ //add buttons to the panel
+ for (int i=buttons.length-1 ; i >= 0 ; i--) {
+ buttons[i].setPreferredSize(standardSize);
+ buttonPanel.add(buttons[i],index);
+ }
+ }
}
diff --git a/rails/ui/swing/ORWindow.java b/rails/ui/swing/ORWindow.java
index 9b049a5..6fc127a 100644
--- a/rails/ui/swing/ORWindow.java
+++ b/rails/ui/swing/ORWindow.java
@@ -66,7 +66,7 @@ public class ORWindow extends DockingFrame implements ActionPerformer {
JScrollPane messagePanelSlider = new JScrollPane(messagePanel);
messagePanel.setParentSlider(messagePanelSlider);
- upgradePanel = new UpgradesPanel(orUIManager);
+ upgradePanel = new UpgradesPanel(orUIManager,isDockingFrameworkEnabled());
addMouseListener(upgradePanel);
mapPanel = new MapPanel(gameUIManager);
@@ -76,6 +76,10 @@ public class ORWindow extends DockingFrame implements ActionPerformer {
//create docking / conventional layout
if (isDockingFrameworkEnabled()) {
+ //set up the button panel (which is separated from its OR panel parent)
+ //adding upgrade panel buttons on top
+ orPanel.addToButtonPanel(upgradePanel.getButtons(),0);
+
//initialize remaining tile panel as it is no optional part in the docking layout
JScrollPane remainingTilesPanelSlider =
new RemainingTilesWindow(this).getScrollPane();
diff --git a/rails/ui/swing/UpgradesPanel.java b/rails/ui/swing/UpgradesPanel.java
index c1a9df7..a471004 100644
--- a/rails/ui/swing/UpgradesPanel.java
+++ b/rails/ui/swing/UpgradesPanel.java
@@ -50,6 +50,13 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener
private RailsIconButton doneButton = new RailsIconButton(RailsIcon.LAY_TILE);
private HexMap hexMap;
+ /**
+ * If set, done/cancel buttons are not added to the pane. Instead, the
+ * visibility property of these buttons are handled such that they are set to
+ * visible if they normally would be added to the pane.
+ */
+ private boolean omitButtons;
+
//list of tiles with an attached reason why it would represent an invalid upgrade
private Map<TileI,String> invalidTileUpgrades = null;
private static final String invalidUpgradeNoTilesLeft = "NoTilesLeft";
@@ -58,10 +65,11 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener
protected static Logger log =
Logger.getLogger(UpgradesPanel.class.getPackage().getName());
- public UpgradesPanel(ORUIManager orUIManager) {
+ public UpgradesPanel(ORUIManager orUIManager,boolean omitButtons) {
super(BoxLayout.Y_AXIS);
this.orUIManager = orUIManager;
+ this.omitButtons = omitButtons;
preferredSize = new Dimension((int)Math.round(110 * (2 + Scale.getFontScale())/3), 200);
setSize(preferredSize);
@@ -85,6 +93,11 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener
cancelButton.setActionCommand("Cancel");
cancelButton.setMnemonic(KeyEvent.VK_C);
cancelButton.addActionListener(this);
+
+ if (omitButtons) {
+ doneButton.setVisible(false);
+ cancelButton.setVisible(false);
+ }
add(scrollPane);
}
@@ -136,7 +149,7 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener
}
public void showUpgrades() {
- upgradePanel.removeAll();
+ clearPanel();
// reset to the number of elements
GridLayout panelLayout = (GridLayout)upgradePanel.getLayout();
@@ -214,9 +227,8 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener
}
}
- upgradePanel.add(doneButton);
- upgradePanel.add(cancelButton);
-
+ addButtons();
+
//repaint();
revalidate();
}
@@ -269,7 +281,7 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener
tokenMode = false;
// activate upgrade panel
- upgradePanel.removeAll();
+ clearPanel();
GridLayout panelLayout = (GridLayout)upgradePanel.getLayout();
List<TileI> tiles = orUIManager.tileUpgrades;
@@ -304,8 +316,7 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener
}
}
- upgradePanel.add(doneButton);
- upgradePanel.add(cancelButton);
+ addButtons();
// repaint();
revalidate();
@@ -318,7 +329,7 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener
tokenMode = false;
// activate upgrade panel
- upgradePanel.removeAll();
+ clearPanel();
GridLayout panelLayout = (GridLayout)upgradePanel.getLayout();
List<? extends TokenI> tokens = orUIManager.tokenLays;
@@ -357,8 +368,8 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener
}
}
- upgradePanel.add(doneButton);
- upgradePanel.add(cancelButton);
+
+ addButtons();
// repaint();
revalidate();
@@ -366,9 +377,8 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener
}
public void clear() {
- upgradePanel.removeAll();
- upgradePanel.add(doneButton);
- upgradePanel.add(cancelButton);
+ clearPanel();
+ addButtons();
upgradePanel.repaint();
}
@@ -537,7 +547,31 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener
setDoneEnabled(false);
setCancelEnabled(false);
}
-
+
+ private void clearPanel() {
+ upgradePanel.removeAll();
+ if (omitButtons) {
+ doneButton.setVisible(false);
+ cancelButton.setVisible(false);
+ }
+ }
+
+ private void addButtons() {
+ if (omitButtons) {
+ //only set externally managed buttons to visible if at least
+ //one of them is enabled
+ boolean isVisible = doneButton.isEnabled() || cancelButton.isEnabled();
+ doneButton.setVisible(isVisible);
+ cancelButton.setVisible(isVisible);
+ } else {
+ upgradePanel.add(doneButton);
+ upgradePanel.add(cancelButton);
+ }
+ }
+
+ public RailsIconButton[] getButtons() {
+ return new RailsIconButton[] {doneButton, cancelButton};
+ }
/** ActionLabel extension that allows to attach the token */
private class CorrectionTokenLabel extends ActionLabel {
|
|
From: Frederick W. <fre...@us...> - 2012-02-12 06:31:18
|
LocalisedText.properties | 4
data/Properties.xml | 8 -
rails/ui/images/add.png |binary
rails/ui/images/cancel.png |binary
rails/ui/swing/UpgradesPanel.java | 13 +-
rails/ui/swing/elements/ActionButton.java | 102 ----------------------
rails/ui/swing/elements/NonModalDialog.java | 7 -
rails/ui/swing/elements/RailsIcon.java | 9 +-
rails/ui/swing/elements/RailsIconButton.java | 121 +++++++++++++++++++++++++++
9 files changed, 146 insertions(+), 118 deletions(-)
New commits:
commit 827a52602ab7f82c1831d8a64648b5e37300bc0c
Author: Frederick Weld <fre...@gm...>
Date: Sun Feb 12 07:29:44 2012 +0100
Applied rails icon functionality to upgrade panel buttons
diff --git a/rails/ui/images/add.png b/rails/ui/images/add.png
new file mode 100644
index 0000000..60a7a29
Binary files /dev/null and b/rails/ui/images/add.png differ
diff --git a/rails/ui/swing/UpgradesPanel.java b/rails/ui/swing/UpgradesPanel.java
index edf24a2..c1a9df7 100644
--- a/rails/ui/swing/UpgradesPanel.java
+++ b/rails/ui/swing/UpgradesPanel.java
@@ -18,6 +18,8 @@ import rails.game.*;
import rails.game.action.*;
import rails.game.correct.MapCorrectionAction;
import rails.ui.swing.elements.ActionLabel;
+import rails.ui.swing.elements.RailsIcon;
+import rails.ui.swing.elements.RailsIconButton;
import rails.ui.swing.hexmap.GUIHex;
import rails.ui.swing.hexmap.GUITile;
import rails.ui.swing.hexmap.HexHighlightMouseListener;
@@ -42,13 +44,10 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener
private JScrollPane scrollPane;
private Dimension preferredSize;
private Border border = new EtchedBorder();
- private final String INIT_CANCEL_TEXT = "NoTile";
- private final String INIT_DONE_TEXT = "LayTile";
private boolean tokenMode = false;
private boolean correctionTokenMode = false;
- private JButton cancelButton =
- new JButton(LocalText.getText(INIT_CANCEL_TEXT));
- private JButton doneButton = new JButton(LocalText.getText(INIT_DONE_TEXT));
+ private RailsIconButton cancelButton = new RailsIconButton(RailsIcon.NO_TILE);
+ private RailsIconButton doneButton = new RailsIconButton(RailsIcon.LAY_TILE);
private HexMap hexMap;
//list of tiles with an attached reason why it would represent an invalid upgrade
@@ -452,11 +451,11 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener
}
public void setCancelText(String text) {
- cancelButton.setText(LocalText.getText(text));
+ cancelButton.setRailsIcon(RailsIcon.getByConfigKey(text));
}
public void setDoneText(String text) {
- doneButton.setText(LocalText.getText(text));
+ doneButton.setRailsIcon(RailsIcon.getByConfigKey(text));
}
public void setDoneEnabled(boolean enabled) {
commit 29e2d4953062a95616a3a1333b7930091f7be8e9
Author: Frederick Weld <fre...@gm...>
Date: Sun Feb 12 07:23:02 2012 +0100
Applied rails icon functionality to non modal dialogs
Model dialogs will stay unaffected as they don't provide for an
easy way to customize the option buttons.
diff --git a/rails/ui/images/cancel.png b/rails/ui/images/cancel.png
new file mode 100644
index 0000000..1b20ae0
Binary files /dev/null and b/rails/ui/images/cancel.png differ
diff --git a/rails/ui/swing/elements/NonModalDialog.java b/rails/ui/swing/elements/NonModalDialog.java
index 72718d2..36d8581 100644
--- a/rails/ui/swing/elements/NonModalDialog.java
+++ b/rails/ui/swing/elements/NonModalDialog.java
@@ -7,7 +7,6 @@ import javax.swing.*;
import org.apache.log4j.Logger;
-import rails.common.LocalText;
import rails.util.Util;
public abstract class NonModalDialog extends JDialog implements ActionListener {
@@ -22,7 +21,7 @@ public abstract class NonModalDialog extends JDialog implements ActionListener {
GridBagConstraints gc;
JPanel optionsPane, buttonPane;
- JButton okButton, cancelButton;
+ RailsIconButton okButton, cancelButton;
String okTextKey = "OK";
String cancelTextKey = "Cancel";
@@ -58,13 +57,13 @@ public abstract class NonModalDialog extends JDialog implements ActionListener {
optionsPane = new JPanel();
buttonPane = new JPanel();
- okButton = new JButton(LocalText.getText(okTextKey));
+ okButton = new RailsIconButton(RailsIcon.getByConfigKey(okTextKey));
okButton.setMnemonic(okTextKey.startsWith("Y") ? KeyEvent.VK_Y : KeyEvent.VK_O);
okButton.addActionListener(this);
buttonPane.add(okButton);
if (hasCancelButton) {
- cancelButton = new JButton(LocalText.getText(cancelTextKey));
+ cancelButton = new RailsIconButton(RailsIcon.getByConfigKey(cancelTextKey));
cancelButton.setMnemonic(cancelTextKey.startsWith("N") ? KeyEvent.VK_N : KeyEvent.VK_C);
cancelButton.addActionListener(this);
buttonPane.add(cancelButton);
diff --git a/rails/ui/swing/elements/RailsIcon.java b/rails/ui/swing/elements/RailsIcon.java
index bc420b0..90db59c 100644
--- a/rails/ui/swing/elements/RailsIcon.java
+++ b/rails/ui/swing/elements/RailsIcon.java
@@ -20,9 +20,15 @@ public enum RailsIcon {
BID ("money_add.png","BID"),
BUY_PRIVATE ("money_bag.png","BUY_PRIVATE"),
BUY_TRAIN ("train.png","BUY_TRAIN"),
+ CANCEL ("cancel.png","CANCEL"),
DONE ("accept.png","Done"),
INFO ("information.png","Info"),
- LAY_TILE ("rails32.png","LayTile"),
+ LAY_TILE ("add.png","LayTile"),
+ LAY_TOKEN ("add.png","LayToken"),
+ NO ("cancel.png","No"),
+ NO_TILE ("control_play_blue.png","NoTile"),
+ NO_TOKEN ("control_play_blue.png","NoToken"),
+ OK ("accept.png","OK"),
PANEL_OR ("participation_rate.png","Dockable.orWindow.orPanel"),
PANEL_OR_BUTTONS ("button.png","Dockable.orWindow.buttonPanel"),
PANEL_MAP ("globe_model.png","Dockable.orWindow.mapPanel"),
@@ -40,6 +46,7 @@ public enum RailsIcon {
SPLIT ("traffic_lights_yellow.png","SPLIT"),
UNDO ("arrow_undo.png","UNDO"),
WITHHOLD ("traffic_lights_red.png","WITHHOLD"),
+ YES ("accept.png","Yes"),
//no icons by purpose
END_OF_GAME_CLOSE_ALL_WINDOWS ("","END_OF_GAME_CLOSE_ALL_WINDOWS"),
commit 484cea4cbdc5d083c3f4587a682c624d0dc835a5
Author: Frederick Weld <fre...@gm...>
Date: Sun Feb 12 06:57:46 2012 +0100
Extracted icon functionality from ActionButton to generic superclass
Needed in order to prepare for using the same icon functionality
on non-action buttons.
diff --git a/LocalisedText.properties b/LocalisedText.properties
index a6f24f6..eac4de9 100644
--- a/LocalisedText.properties
+++ b/LocalisedText.properties
@@ -183,8 +183,8 @@ Config.infoText.sound.sfx.gen.newCurrentPlayer=<html>Enter assignment of sound e
Config.infoText.sound.sfx.or.buyTrain=<html>Enter assignment of sound effect files to train types.<ul><li>Separate the assignments by commas.<li>Each assignment has the syntax trainName=complete file path<li>Default sound effect is defined by omitting "trainName=" in the assignment.</ul><strong>Examples:</strong><ul><li>Set default sound effect: <br><code>c:\BuyTrain-default.mp3</code><li>Set train-dependent sound effect and a default (for trains above 6): <br><code>2=c:\BuyTrain-2.mp3,3=c:\BuyTrain-3.mp3,4=c:\BuyTrain-4.mp3,5=c:\BuyTrain-5.mp3,6=c:\BuyTrain-6.mp3,c:\BuyTrain-D.mp3</code></ul> </html>
Config.infoText.sound.sfx.or.setRevenue=<html><ul><li>Only the latter portion of this file is played.<ul><li>For an average revenue, the last third is played.</ul><li>The higher the company's revenue the longer this file is played.<ul><li>But the file is at most played once as a whole.</li></ul></html>
Config.infoText.sound.sfx.sr.newPresident=This also includes becoming the president when buying the president share.
-Config.label.actionButton.iconText=Button display type
-Config.label.actionButton.iconSize=Icon size
+Config.label.button.iconText=Button display type
+Config.label.button.iconSize=Button icon size
Config.label.default_game=Default game
Config.label.default_players=Default players
Config.label.font.ui.name=Font selection
diff --git a/data/Properties.xml b/data/Properties.xml
index b78d097..c207cbc 100644
--- a/data/Properties.xml
+++ b/data/Properties.xml
@@ -48,10 +48,10 @@
</Section>
<Section name="Appearance">
<Property name="gridPanel.tableBorders" type="LIST" values="disabled,enabled"/>
- <Property name="actionButton.iconText" type="LIST" values="text and icon,only text,only icon"
- initClass="rails.ui.swing.elements.ActionButton" initMethod="resetRailsIcons" initParameter="no" />
- <Property name="actionButton.iconSize" type="LIST" values="small,large"
- initClass="rails.ui.swing.elements.ActionButton" initMethod="resetRailsIcons" initParameter="no" />
+ <Property name="button.iconText" type="LIST" values="text and icon,only text,only icon"
+ initClass="rails.ui.swing.elements.RailsIconButton" initMethod="resetRailsIcons" initParameter="no" />
+ <Property name="button.iconSize" type="LIST" values="small,large"
+ initClass="rails.ui.swing.elements.RailsIconButton" initMethod="resetRailsIcons" initParameter="no" />
<Property name="route.colour.1" type="COLOR"
initClass="rails.ui.swing.hexmap.HexMap" initMethod="setRouteColours" />
<Property name="route.colour.2" type="COLOR"
diff --git a/rails/ui/swing/elements/ActionButton.java b/rails/ui/swing/elements/ActionButton.java
index d07bbba..b591fd3 100644
--- a/rails/ui/swing/elements/ActionButton.java
+++ b/rails/ui/swing/elements/ActionButton.java
@@ -1,16 +1,9 @@
/* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/ui/swing/elements/ActionButton.java,v 1.5 2008/06/04 19:00:38 evos Exp $*/
package rails.ui.swing.elements;
-import java.awt.Insets;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
-import javax.swing.JButton;
-
-import rails.common.parser.Config;
import rails.game.action.ActionTaker;
import rails.game.action.PossibleAction;
@@ -19,38 +12,14 @@ import rails.game.action.PossibleAction;
*
* @see ClickField
*/
-public class ActionButton extends JButton implements ActionTaker {
+public class ActionButton extends RailsIconButton implements ActionTaker {
private static final long serialVersionUID = 1L;
- private static final Set<String> KEYS_TEXT_DISPLAY = new HashSet<String>
- (Arrays.asList( new String[] {
- "text and icon",
- "only text",
- "",
- null
- }));
- private static final Set<String> KEYS_ICON_DISPLAY = new HashSet<String>
- (Arrays.asList( new String[] {
- "text and icon",
- "only icon"
- }));
-
- private static Set<ActionButton> actionButtons = new HashSet<ActionButton>();
-
private List<PossibleAction> actions = new ArrayList<PossibleAction>(1);
- /**
- * null value means that the action button is not set up by an appropriate
- * RailsIcon (eg., by calling setText directly).
- */
- private RailsIcon railsIcon = null;
-
public ActionButton(RailsIcon railsIcon) {
- super();
- setRailsIcon(railsIcon);
- this.setMargin(new Insets(2,2,2,2));
- actionButtons.add(this);
+ super(railsIcon);
}
public void addPossibleAction(PossibleAction o) {
@@ -70,71 +39,4 @@ public class ActionButton extends JButton implements ActionTaker {
addPossibleAction(action);
}
- public void setRailsIcon(RailsIcon railsIcon) {
- if (railsIcon == null) railsIcon = RailsIcon.NULL;
- this.railsIcon = railsIcon;
- showRailsIcon();
- }
-
- /**
- * Display according to configuration.
- * If no text/icon is attached, then icon/text is displayed as fallback
- * (irrespective of configuration).
- * Text becomes the tool tip text in case of icon-only display.
- */
- private void showRailsIcon() {
- if (railsIcon != null) {
- if (isTextEnabled() || railsIcon.largeIcon == null) {
- super.setText(railsIcon.description);
- } else {
- super.setText(null);
- }
- if (isIconEnabled() || railsIcon.description == null) {
- if (isIconSizeSmall()) {
- super.setIcon(railsIcon.smallIcon);
- } else {
- super.setIcon(railsIcon.largeIcon);
- }
- if (!isTextEnabled()) {
- super.setToolTipText(railsIcon.description);
- }
- } else {
- super.setIcon(null);
- }
- }
- }
-
- private boolean isTextEnabled() {
- return KEYS_TEXT_DISPLAY.contains(Config.get("actionButton.iconText",""));
- }
-
- private boolean isIconEnabled() {
- return KEYS_ICON_DISPLAY.contains(Config.get("actionButton.iconText",""));
- }
-
- private boolean isIconSizeSmall() {
- //small is default
- return !"large".equals(Config.get("actionButton.iconSize"));
- }
-
- /**
- * Should only be used if an arbitrary text is to displayed without icon.
- * In any other case, setRailsIcon should be used.
- */
- @Override
- public void setText(String text) {
- super.setText(text);
- setIcon(null);
- railsIcon = null;
- }
-
- /**
- * To be called upon change of button display type
- */
- public static void resetRailsIcons() {
- for (ActionButton ab : actionButtons) {
- ab.showRailsIcon();
- }
- }
-
}
diff --git a/rails/ui/swing/elements/RailsIconButton.java b/rails/ui/swing/elements/RailsIconButton.java
new file mode 100644
index 0000000..3f6d628
--- /dev/null
+++ b/rails/ui/swing/elements/RailsIconButton.java
@@ -0,0 +1,121 @@
+/**
+ *
+ */
+package rails.ui.swing.elements;
+
+import java.awt.Insets;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.swing.JButton;
+
+import rails.common.parser.Config;
+
+/**
+ * A JButton which is able to hold/manage a RailsIcon (specifying what
+ * text / icon is to be displayed)
+ *
+ * @author Frederick Weld
+ *
+ */
+public class RailsIconButton extends JButton {
+
+ private static final long serialVersionUID = 1L;
+
+ private static final Set<String> KEYS_TEXT_DISPLAY = new HashSet<String>
+ (Arrays.asList( new String[] {
+ "text and icon",
+ "only text",
+ "",
+ null
+ }));
+ private static final Set<String> KEYS_ICON_DISPLAY = new HashSet<String>
+ (Arrays.asList( new String[] {
+ "text and icon",
+ "only icon"
+ }));
+
+ private static Set<RailsIconButton> railsIconButtons = new HashSet<RailsIconButton>();
+
+ /**
+ * null value means that the button is not set up by an appropriate
+ * RailsIcon (eg., by calling setText directly).
+ */
+ private RailsIcon railsIcon = null;
+
+ public RailsIconButton(RailsIcon railsIcon) {
+ super();
+ setRailsIcon(railsIcon);
+ this.setMargin(new Insets(2,2,2,2));
+ railsIconButtons.add(this);
+ }
+
+ public void setRailsIcon(RailsIcon railsIcon) {
+ if (railsIcon == null) railsIcon = RailsIcon.NULL;
+ this.railsIcon = railsIcon;
+ showRailsIcon();
+ }
+
+ /**
+ * Display according to configuration.
+ * If no text/icon is attached, then icon/text is displayed as fallback
+ * (irrespective of configuration).
+ * Text becomes the tool tip text in case of icon-only display.
+ */
+ private void showRailsIcon() {
+ if (railsIcon != null) {
+ if (isTextEnabled() || railsIcon.largeIcon == null) {
+ super.setText(railsIcon.description);
+ } else {
+ super.setText(null);
+ }
+ if (isIconEnabled() || railsIcon.description == null) {
+ if (isIconSizeSmall()) {
+ super.setIcon(railsIcon.smallIcon);
+ } else {
+ super.setIcon(railsIcon.largeIcon);
+ }
+ if (!isTextEnabled()) {
+ super.setToolTipText(railsIcon.description);
+ }
+ } else {
+ super.setIcon(null);
+ }
+ }
+ }
+
+ private boolean isTextEnabled() {
+ return KEYS_TEXT_DISPLAY.contains(Config.get("button.iconText",""));
+ }
+
+ private boolean isIconEnabled() {
+ return KEYS_ICON_DISPLAY.contains(Config.get("button.iconText",""));
+ }
+
+ private boolean isIconSizeSmall() {
+ //small is default
+ return !"large".equals(Config.get("button.iconSize"));
+ }
+
+ /**
+ * Should only be used if an arbitrary text is to displayed without icon.
+ * In any other case, setRailsIcon should be used.
+ */
+ @Override
+ public void setText(String text) {
+ super.setText(text);
+ setIcon(null);
+ railsIcon = null;
+ }
+
+ /**
+ * To be called upon change of button display type
+ */
+ public static void resetRailsIcons() {
+ for (RailsIconButton rib : railsIconButtons) {
+ rib.showRailsIcon();
+ }
+ }
+
+}
|
|
From: Frederick W. <fre...@us...> - 2012-02-11 18:42:22
|
LocalisedText.properties | 2
data/GamesList.xml | 63 +++++++-------
data/Properties.xml | 4
rails/ui/images/Train.png |binary
rails/ui/images/accept.png |binary
rails/ui/images/arrow_redo.png |binary
rails/ui/images/arrow_undo.png |binary
rails/ui/images/auction_hammer_gavel.png |binary
rails/ui/images/bricks.png |binary
rails/ui/images/button.png |binary
rails/ui/images/cash_stack.png |binary
rails/ui/images/clock_add.png |binary
rails/ui/images/clock_delete.png |binary
rails/ui/images/coins_in_hand.png |binary
rails/ui/images/control_fastforward_blue.png |binary
rails/ui/images/control_play_blue.png |binary
rails/ui/images/globe_model.png |binary
rails/ui/images/hand_property.png |binary
rails/ui/images/information.png |binary
rails/ui/images/money_add.png |binary
rails/ui/images/money_bag.png |binary
rails/ui/images/participation_rate.png |binary
rails/ui/images/rails32.png |binary
rails/ui/images/script.png |binary
rails/ui/images/traffic_lights_green.png |binary
rails/ui/images/traffic_lights_red.png |binary
rails/ui/images/traffic_lights_yellow.png |binary
rails/ui/swing/ConfigWindow.java | 2
rails/ui/swing/GameSetupWindow.java | 2
rails/ui/swing/ORPanel.java | 28 +++---
rails/ui/swing/ORWindow.java | 12 +-
rails/ui/swing/ReportWindowDynamic.java | 5 -
rails/ui/swing/StartRoundWindow.java | 12 +-
rails/ui/swing/StatusWindow.java | 14 +--
rails/ui/swing/elements/ActionButton.java | 100 ++++++++++++++++++++++
rails/ui/swing/elements/DockingFrame.java | 5 -
rails/ui/swing/elements/RailsIcon.java | 119 +++++++++++++++++++++++++--
37 files changed, 290 insertions(+), 78 deletions(-)
New commits:
commit b7e95f18296f06fcce810682b89a542608ce5b71
Author: Frederick Weld <fre...@gm...>
Date: Sat Feb 11 19:39:51 2012 +0100
Included and pre-configured icon set for action buttons and dockables
Attribution now part of the credits.
diff --git a/data/GamesList.xml b/data/GamesList.xml
index 10d120d..3b6b2c5 100644
--- a/data/GamesList.xml
+++ b/data/GamesList.xml
@@ -315,33 +315,38 @@ Known Issues:
</Game>
- <Credits>Rails is a computer implementation of a number of board games.
- These games all have a railroad theme. They are collectively known as "18xx"
- games due to the naming scheme used by many games in the genre.
-
-Contributors:
- Erik Vos
- Stefan Frey
- Freek Dijkstra
- Scott Peterson
- Adam Badura
- Phil Davies
- Bill Rosgen
- Martin Brumm
- Chris Shaffer
- Brett Lentz
-
-All rights reserved by the respective owners of the original games
-(see the Game Notes per game for specific acknowledgements).
-
-No challenge to the original author's or publisher's rights, licensing, or status is intended.
-
-Rails is intended as a play aid for owners of each respective boardgame.
-
-The Rails application and source code are distributed under
-version 2 of the GNU Public License (GPL).
-
-A copy of the GPL should have been shipped with the game files and is also available here:
- http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
- </Credits>
+ <Credits><html>Rails is a computer implementation of a number of board games.<br>
+ These games all have a railroad theme. They are collectively known as "18xx" <br>
+ games due to the naming scheme used by many games in the genre. <br>
+ <br>
+Contributors: <br>
+ Erik Vos<br>
+ Stefan Frey<br>
+ Freek Dijkstra<br>
+ Scott Peterson<br>
+ Adam Badura<br>
+ Phil Davies<br>
+ Bill Rosgen<br>
+ Martin Brumm<br>
+ Chris Shaffer <br>
+ Brett Lentz<br>
+<br>
+All rights reserved by the respective owners of the original games<br>
+(see the Game Notes per game for specific acknowledgements).<br>
+<br>
+No challenge to the original author's or publisher's rights, licensing, or status is intended.<br>
+<br>
+Rails is intended as a play aid for owners of each respective boardgame.<br>
+<br>
+The Rails application and source code are distributed under<br>
+version 2 of the GNU Public License (GPL).<br>
+<br>
+A copy of the GPL should have been shipped with the game files and is also available here:<br>
+ <a href="http://www.gnu.org/licenses/old-licenses/gpl-2.0.html">http://www.gnu.org/licenses/old-licenses/gpl-2.0.html</a><br>
+<br>
+Icon sets are taken from the following sites:<ul>
+ <li><a href="http://www.fatcow.com/">http://www.fatcow.com/</a><br>
+ under a Creative Commons Attribution 3.0 License (<a href="http://creativecommons.org/licenses/by/3.0/us/">http://creativecommons.org/licenses/by/3.0/us/</a>)
+ </ul>
+ </html></Credits>
</GamesList>
diff --git a/rails/ui/images/Train.png b/rails/ui/images/Train.png
new file mode 100644
index 0000000..0957b13
Binary files /dev/null and b/rails/ui/images/Train.png differ
diff --git a/rails/ui/images/accept.png b/rails/ui/images/accept.png
new file mode 100644
index 0000000..7786ac7
Binary files /dev/null and b/rails/ui/images/accept.png differ
diff --git a/rails/ui/images/arrow_redo.png b/rails/ui/images/arrow_redo.png
new file mode 100644
index 0000000..c80608a
Binary files /dev/null and b/rails/ui/images/arrow_redo.png differ
diff --git a/rails/ui/images/arrow_undo.png b/rails/ui/images/arrow_undo.png
new file mode 100644
index 0000000..be4f8e9
Binary files /dev/null and b/rails/ui/images/arrow_undo.png differ
diff --git a/rails/ui/images/auction_hammer_gavel.png b/rails/ui/images/auction_hammer_gavel.png
new file mode 100644
index 0000000..c27c3f5
Binary files /dev/null and b/rails/ui/images/auction_hammer_gavel.png differ
diff --git a/rails/ui/images/bricks.png b/rails/ui/images/bricks.png
new file mode 100644
index 0000000..a453ca0
Binary files /dev/null and b/rails/ui/images/bricks.png differ
diff --git a/rails/ui/images/button.png b/rails/ui/images/button.png
new file mode 100644
index 0000000..4b1eb80
Binary files /dev/null and b/rails/ui/images/button.png differ
diff --git a/rails/ui/images/cash_stack.png b/rails/ui/images/cash_stack.png
new file mode 100644
index 0000000..ee8e307
Binary files /dev/null and b/rails/ui/images/cash_stack.png differ
diff --git a/rails/ui/images/clock_add.png b/rails/ui/images/clock_add.png
new file mode 100644
index 0000000..c61c062
Binary files /dev/null and b/rails/ui/images/clock_add.png differ
diff --git a/rails/ui/images/clock_delete.png b/rails/ui/images/clock_delete.png
new file mode 100644
index 0000000..2f8ffb8
Binary files /dev/null and b/rails/ui/images/clock_delete.png differ
diff --git a/rails/ui/images/coins_in_hand.png b/rails/ui/images/coins_in_hand.png
new file mode 100644
index 0000000..aaceea1
Binary files /dev/null and b/rails/ui/images/coins_in_hand.png differ
diff --git a/rails/ui/images/control_fastforward_blue.png b/rails/ui/images/control_fastforward_blue.png
new file mode 100644
index 0000000..e348959
Binary files /dev/null and b/rails/ui/images/control_fastforward_blue.png differ
diff --git a/rails/ui/images/control_play_blue.png b/rails/ui/images/control_play_blue.png
new file mode 100644
index 0000000..a1f7345
Binary files /dev/null and b/rails/ui/images/control_play_blue.png differ
diff --git a/rails/ui/images/globe_model.png b/rails/ui/images/globe_model.png
new file mode 100644
index 0000000..66a5c0b
Binary files /dev/null and b/rails/ui/images/globe_model.png differ
diff --git a/rails/ui/images/hand_property.png b/rails/ui/images/hand_property.png
new file mode 100644
index 0000000..fe4725e
Binary files /dev/null and b/rails/ui/images/hand_property.png differ
diff --git a/rails/ui/images/information.png b/rails/ui/images/information.png
new file mode 100644
index 0000000..93c67f2
Binary files /dev/null and b/rails/ui/images/information.png differ
diff --git a/rails/ui/images/money_add.png b/rails/ui/images/money_add.png
new file mode 100644
index 0000000..62154f3
Binary files /dev/null and b/rails/ui/images/money_add.png differ
diff --git a/rails/ui/images/money_bag.png b/rails/ui/images/money_bag.png
new file mode 100644
index 0000000..24a1a06
Binary files /dev/null and b/rails/ui/images/money_bag.png differ
diff --git a/rails/ui/images/participation_rate.png b/rails/ui/images/participation_rate.png
new file mode 100644
index 0000000..1c30d07
Binary files /dev/null and b/rails/ui/images/participation_rate.png differ
diff --git a/rails/ui/images/rails32.png b/rails/ui/images/rails32.png
new file mode 100644
index 0000000..c62e18c
Binary files /dev/null and b/rails/ui/images/rails32.png differ
diff --git a/rails/ui/images/script.png b/rails/ui/images/script.png
new file mode 100644
index 0000000..8755c17
Binary files /dev/null and b/rails/ui/images/script.png differ
diff --git a/rails/ui/images/traffic_lights_green.png b/rails/ui/images/traffic_lights_green.png
new file mode 100644
index 0000000..bd53d89
Binary files /dev/null and b/rails/ui/images/traffic_lights_green.png differ
diff --git a/rails/ui/images/traffic_lights_red.png b/rails/ui/images/traffic_lights_red.png
new file mode 100644
index 0000000..fd00be2
Binary files /dev/null and b/rails/ui/images/traffic_lights_red.png differ
diff --git a/rails/ui/images/traffic_lights_yellow.png b/rails/ui/images/traffic_lights_yellow.png
new file mode 100644
index 0000000..54034fc
Binary files /dev/null and b/rails/ui/images/traffic_lights_yellow.png differ
diff --git a/rails/ui/swing/StartRoundWindow.java b/rails/ui/swing/StartRoundWindow.java
index 4011121..a6ea8d6 100644
--- a/rails/ui/swing/StartRoundWindow.java
+++ b/rails/ui/swing/StartRoundWindow.java
@@ -134,7 +134,7 @@ implements ActionListener, KeyListener, ActionPerformer, DialogOwner {
buttonPanel = new JPanel();
- buyButton = new ActionButton(RailsIcon.BUY);
+ buyButton = new ActionButton(RailsIcon.AUCTION_BUY);
buyButton.setMnemonic(KeyEvent.VK_B);
buyButton.addActionListener(this);
buyButton.setEnabled(false);
diff --git a/rails/ui/swing/elements/RailsIcon.java b/rails/ui/swing/elements/RailsIcon.java
index eed61ff..bc420b0 100644
--- a/rails/ui/swing/elements/RailsIcon.java
+++ b/rails/ui/swing/elements/RailsIcon.java
@@ -15,27 +15,35 @@ import rails.common.LocalText;
public enum RailsIcon {
// in parentheses the image file
- AUTOPASS ("","Autopass"),
- BID ("","BID"),
- BUY ("","BUY"),
- BUY_PRIVATE ("","BUY_PRIVATE"),
- BUY_TRAIN ("","BUY_TRAIN"),
- DONE ("","Done"),
+ AUCTION_BUY ("auction_hammer_gavel.png","BUY"),
+ AUTOPASS ("control_fastforward_blue.png","Autopass"),
+ BID ("money_add.png","BID"),
+ BUY_PRIVATE ("money_bag.png","BUY_PRIVATE"),
+ BUY_TRAIN ("train.png","BUY_TRAIN"),
+ DONE ("accept.png","Done"),
+ INFO ("information.png","Info"),
+ LAY_TILE ("rails32.png","LayTile"),
+ PANEL_OR ("participation_rate.png","Dockable.orWindow.orPanel"),
+ PANEL_OR_BUTTONS ("button.png","Dockable.orWindow.buttonPanel"),
+ PANEL_MAP ("globe_model.png","Dockable.orWindow.mapPanel"),
+ PANEL_MESSAGE ("script.png","Dockable.orWindow.messagePanel"),
+ PANEL_REMAINING_TILES ("rails32.png","Dockable.orWindow.remainingTilesPanel"),
+ PANEL_UPGRADE ("bricks.png","Dockable.orWindow.upgradePanel"),
+ PASS ("control_play_blue.png","PASS"),
+ PAYOUT ("traffic_lights_green.png","PAYOUT"),
+ REDO ("arrow_redo.png","REDO"),
+ REPAY_LOANS ("cash_stack.png","RepayLoans"),
+ REPORT_MOVE_BACKWARD ("clock_delete.png","REPORT_MOVE_BACKWARD"),
+ REPORT_MOVE_FORWARD ("clock_add.png","REPORT_MOVE_FORWARD"),
+ SELECT_NO_BID ("hand_property.png","SelectNoBid"),
+ SET_REVENUE ("coins_in_hand.png","SET_REVENUE"),
+ SPLIT ("traffic_lights_yellow.png","SPLIT"),
+ UNDO ("arrow_undo.png","UNDO"),
+ WITHHOLD ("traffic_lights_red.png","WITHHOLD"),
+
+ //no icons by purpose
END_OF_GAME_CLOSE_ALL_WINDOWS ("","END_OF_GAME_CLOSE_ALL_WINDOWS"),
- INFO ("Inform.gif","Info"),
- LAY_TILE ("","LayTile"),
OPERATING_COST ("","OCButtonLabel"),
- PASS ("","PASS"),
- PAYOUT ("","PAYOUT"),
- REDO ("","REDO"),
- REPAY_LOANS ("","RepayLoans"),
- REPORT_MOVE_BACKWARD ("","REPORT_MOVE_BACKWARD"),
- REPORT_MOVE_FORWARD ("","REPORT_MOVE_FORWARD"),
- SELECT_NO_BID ("","SelectNoBid"),
- SET_REVENUE ("","SET_REVENUE"),
- SPLIT ("","SPLIT"),
- UNDO ("","UNDO"),
- WITHOLD ("","WITHHOLD"),
//null meaning all public fields are null
NULL ();
commit d0d630d07e4b5b7edd5764ee1b6b125fc806df49
Author: Frederick Weld <fre...@gm...>
Date: Sat Feb 11 17:30:59 2012 +0100
Added support for icons in dockable panels / further refactoring
As a result, add dockable now also gets the config key in order
to be able to map the dockable to the respective icon.
diff --git a/rails/ui/swing/ConfigWindow.java b/rails/ui/swing/ConfigWindow.java
index 4d25293..db03e10 100644
--- a/rails/ui/swing/ConfigWindow.java
+++ b/rails/ui/swing/ConfigWindow.java
@@ -419,7 +419,7 @@ class ConfigWindow extends JFrame {
}
// add info icon for infoText
if (infoText != null) {
- JLabel infoIcon = new JLabel(RailsIcon.INFO.largeIcon);
+ JLabel infoIcon = new JLabel(RailsIcon.INFO.smallIcon);
infoIcon.addMouseListener(new MouseListener() {
public void mousePressed(MouseEvent e) {
final JDialog dialog = new JDialog(ConfigWindow.this, false);
diff --git a/rails/ui/swing/GameSetupWindow.java b/rails/ui/swing/GameSetupWindow.java
index e91880d..4e69739 100644
--- a/rails/ui/swing/GameSetupWindow.java
+++ b/rails/ui/swing/GameSetupWindow.java
@@ -324,7 +324,7 @@ public class GameSetupWindow extends JDialog implements ActionListener {
System.exit(0);
} else if (arg0.getSource().equals(creditsButton)) {
JOptionPane.showMessageDialog(this,
- credits,
+ new JLabel(credits), //enable html rendering
LocalText.getText("CREDITS"),
JOptionPane.INFORMATION_MESSAGE);
} else if (arg0.getSource().equals(gameNameBox)) {
diff --git a/rails/ui/swing/ORPanel.java b/rails/ui/swing/ORPanel.java
index ec8c7ec..0dd18ce 100644
--- a/rails/ui/swing/ORPanel.java
+++ b/rails/ui/swing/ORPanel.java
@@ -1183,7 +1183,7 @@ implements ActionListener, KeyListener, RevenueListener {
setSelect(revenue[orCompIndex], revenueSelect[orCompIndex], false);
if (withhold) {
- button1.setRailsIcon(RailsIcon.WITHOLD);
+ button1.setRailsIcon(RailsIcon.WITHHOLD);
button1.setActionCommand(WITHHOLD_CMD);
clonedAction = (SetDividend) action.clone();
clonedAction.setRevenueAllocation(SetDividend.WITHHOLD);
diff --git a/rails/ui/swing/ORWindow.java b/rails/ui/swing/ORWindow.java
index acee3e9..9b049a5 100644
--- a/rails/ui/swing/ORWindow.java
+++ b/rails/ui/swing/ORWindow.java
@@ -82,22 +82,22 @@ public class ORWindow extends DockingFrame implements ActionPerformer {
//generate layout
addDockable ( messagePanelSlider,
- LocalText.getText("Dockable.orWindow.messagePanel"),
+ "Dockable.orWindow.messagePanel",
0, 0, 100, 10, DockableProperty.closeable);
addDockable ( upgradePanel,
- LocalText.getText("Dockable.orWindow.upgradePanel"),
+ "Dockable.orWindow.upgradePanel",
0, 10, 20, 70, DockableProperty.standard);
addDockable ( mapPanel,
- LocalText.getText("Dockable.orWindow.mapPanel"),
+ "Dockable.orWindow.mapPanel",
20, 10, 80, 70, DockableProperty.standard);
addDockable ( remainingTilesPanelSlider,
- LocalText.getText("Dockable.orWindow.remainingTilesPanel"),
+ "Dockable.orWindow.remainingTilesPanel",
100, 0, 120, 100, DockableProperty.initially_hidden);
addDockable ( orPanel,
- LocalText.getText("Dockable.orWindow.orPanel"),
+ "Dockable.orWindow.orPanel",
0, 80, 100, 15, DockableProperty.standard);
addDockable ( orPanel.getButtonPanel(),
- LocalText.getText("Dockable.orWindow.buttonPanel"),
+ "Dockable.orWindow.buttonPanel",
0, 95, 100, 5, DockableProperty.standard);
deployDockables();
diff --git a/rails/ui/swing/StartRoundWindow.java b/rails/ui/swing/StartRoundWindow.java
index a2c83eb..4011121 100644
--- a/rails/ui/swing/StartRoundWindow.java
+++ b/rails/ui/swing/StartRoundWindow.java
@@ -797,7 +797,7 @@ implements ActionListener, KeyListener, ActionPerformer, DialogOwner {
}
private ImageIcon createInfoIcon() {
- return RailsIcon.INFO.largeIcon;
+ return RailsIcon.INFO.smallIcon;
}
public void keyPressed(KeyEvent e) {
diff --git a/rails/ui/swing/elements/ActionButton.java b/rails/ui/swing/elements/ActionButton.java
index 2594741..d07bbba 100644
--- a/rails/ui/swing/elements/ActionButton.java
+++ b/rails/ui/swing/elements/ActionButton.java
@@ -113,7 +113,8 @@ public class ActionButton extends JButton implements ActionTaker {
}
private boolean isIconSizeSmall() {
- return "small".equals(Config.get("actionButton.iconSize"));
+ //small is default
+ return !"large".equals(Config.get("actionButton.iconSize"));
}
/**
diff --git a/rails/ui/swing/elements/DockingFrame.java b/rails/ui/swing/elements/DockingFrame.java
index 78edec1..82c0ea6 100644
--- a/rails/ui/swing/elements/DockingFrame.java
+++ b/rails/ui/swing/elements/DockingFrame.java
@@ -114,13 +114,14 @@ public abstract class DockingFrame extends JFrame {
* The dockable is only deployed to the frame if deployDockables is called.
*/
protected void addDockable(JComponent c,
- String dockableTitle,
+ String dockableConfigKey,
int x, int y, int width, int height,
DockableProperty dockableProperty) {
+ String dockableTitle = LocalText.getText(dockableConfigKey);
DefaultSingleCDockable d = new DefaultSingleCDockable(
dockableTitle, dockableTitle );
d.add( c, BorderLayout.CENTER );
- d.setTitleIcon(null);
+ d.setTitleIcon(RailsIcon.getByConfigKey(dockableConfigKey).smallIcon);
d.setCloseable(
( dockableProperty == DockableProperty.closeable
|| dockableProperty == DockableProperty.initially_hidden )
commit 9ee0450b4dfce30542923740000d050bbe7b8cd1
Author: Frederick Weld <fre...@gm...>
Date: Sat Feb 11 15:28:21 2012 +0100
Added framework for managing/displaying icons on ActionButtons
RailsIcon and ActionButton have undergone rework / extensions.
ActionButton's construction and setText is not based on label text
any more. Instead RailsIcon enum instances are used for this purpose.
Added two options (display text/icon/both and small/large icons).
diff --git a/LocalisedText.properties b/LocalisedText.properties
index a0f256f..a6f24f6 100644
--- a/LocalisedText.properties
+++ b/LocalisedText.properties
@@ -183,6 +183,8 @@ Config.infoText.sound.sfx.gen.newCurrentPlayer=<html>Enter assignment of sound e
Config.infoText.sound.sfx.or.buyTrain=<html>Enter assignment of sound effect files to train types.<ul><li>Separate the assignments by commas.<li>Each assignment has the syntax trainName=complete file path<li>Default sound effect is defined by omitting "trainName=" in the assignment.</ul><strong>Examples:</strong><ul><li>Set default sound effect: <br><code>c:\BuyTrain-default.mp3</code><li>Set train-dependent sound effect and a default (for trains above 6): <br><code>2=c:\BuyTrain-2.mp3,3=c:\BuyTrain-3.mp3,4=c:\BuyTrain-4.mp3,5=c:\BuyTrain-5.mp3,6=c:\BuyTrain-6.mp3,c:\BuyTrain-D.mp3</code></ul> </html>
Config.infoText.sound.sfx.or.setRevenue=<html><ul><li>Only the latter portion of this file is played.<ul><li>For an average revenue, the last third is played.</ul><li>The higher the company's revenue the longer this file is played.<ul><li>But the file is at most played once as a whole.</li></ul></html>
Config.infoText.sound.sfx.sr.newPresident=This also includes becoming the president when buying the president share.
+Config.label.actionButton.iconText=Button display type
+Config.label.actionButton.iconSize=Icon size
Config.label.default_game=Default game
Config.label.default_players=Default players
Config.label.font.ui.name=Font selection
diff --git a/data/Properties.xml b/data/Properties.xml
index da62099..b78d097 100644
--- a/data/Properties.xml
+++ b/data/Properties.xml
@@ -48,6 +48,10 @@
</Section>
<Section name="Appearance">
<Property name="gridPanel.tableBorders" type="LIST" values="disabled,enabled"/>
+ <Property name="actionButton.iconText" type="LIST" values="text and icon,only text,only icon"
+ initClass="rails.ui.swing.elements.ActionButton" initMethod="resetRailsIcons" initParameter="no" />
+ <Property name="actionButton.iconSize" type="LIST" values="small,large"
+ initClass="rails.ui.swing.elements.ActionButton" initMethod="resetRailsIcons" initParameter="no" />
<Property name="route.colour.1" type="COLOR"
initClass="rails.ui.swing.hexmap.HexMap" initMethod="setRouteColours" />
<Property name="route.colour.2" type="COLOR"
diff --git a/rails/ui/swing/ConfigWindow.java b/rails/ui/swing/ConfigWindow.java
index 8c9e7e8..4d25293 100644
--- a/rails/ui/swing/ConfigWindow.java
+++ b/rails/ui/swing/ConfigWindow.java
@@ -419,7 +419,7 @@ class ConfigWindow extends JFrame {
}
// add info icon for infoText
if (infoText != null) {
- JLabel infoIcon = new JLabel(RailsIcon.INFO.icon);
+ JLabel infoIcon = new JLabel(RailsIcon.INFO.largeIcon);
infoIcon.addMouseListener(new MouseListener() {
public void mousePressed(MouseEvent e) {
final JDialog dialog = new JDialog(ConfigWindow.this, false);
diff --git a/rails/ui/swing/ORPanel.java b/rails/ui/swing/ORPanel.java
index 280ef18..ec8c7ec 100644
--- a/rails/ui/swing/ORPanel.java
+++ b/rails/ui/swing/ORPanel.java
@@ -285,39 +285,39 @@ implements ActionListener, KeyListener, RevenueListener {
private void initButtonPanel() {
// sfy: operatingcosts button
- buttonOC = new ActionButton(LocalText.getText("OCButtonLabel"));
+ buttonOC = new ActionButton(RailsIcon.OPERATING_COST);
buttonOC.setActionCommand(OPERATING_COST_CMD);
buttonOC.setMnemonic(KeyEvent.VK_O);
buttonOC.addActionListener(this);
buttonOC.setEnabled(false);
buttonOC.setVisible(false);
- button1 = new ActionButton(LocalText.getText("LayTile"));
+ button1 = new ActionButton(RailsIcon.LAY_TILE);
button1.setActionCommand(LAY_TILE_CMD);
button1.setMnemonic(KeyEvent.VK_T);
button1.addActionListener(this);
button1.setEnabled(false);
- button2 = new ActionButton(LocalText.getText("BUY_PRIVATE"));
+ button2 = new ActionButton(RailsIcon.BUY_PRIVATE);
button2.setActionCommand(BUY_PRIVATE_CMD);
button2.setMnemonic(KeyEvent.VK_V);
button2.addActionListener(this);
button2.setEnabled(false);
button2.setVisible(false);
- button3 = new ActionButton(LocalText.getText("Done"));
+ button3 = new ActionButton(RailsIcon.DONE);
button3.setActionCommand(DONE_CMD);
button3.setMnemonic(KeyEvent.VK_D);
button3.addActionListener(this);
button3.setEnabled(false);
- undoButton = new ActionButton(LocalText.getText("UNDO"));
+ undoButton = new ActionButton(RailsIcon.UNDO);
undoButton.setActionCommand(UNDO_CMD);
undoButton.setMnemonic(KeyEvent.VK_U);
undoButton.addActionListener(this);
undoButton.setEnabled(false);
- redoButton = new ActionButton(LocalText.getText("REDO"));
+ redoButton = new ActionButton(RailsIcon.REDO);
redoButton.setActionCommand(REDO_CMD);
redoButton.setMnemonic(KeyEvent.VK_R);
redoButton.addActionListener(this);
@@ -1134,7 +1134,7 @@ implements ActionListener, KeyListener, RevenueListener {
setSelect(revenue[orCompIndex], revenueSelect[orCompIndex], true);
- button1.setText(LocalText.getText("SET_REVENUE"));
+ button1.setRailsIcon(RailsIcon.SET_REVENUE);
button1.setActionCommand(SET_REVENUE_CMD);
button1.setPossibleAction(action);
button1.setMnemonic(KeyEvent.VK_R);
@@ -1183,7 +1183,7 @@ implements ActionListener, KeyListener, RevenueListener {
setSelect(revenue[orCompIndex], revenueSelect[orCompIndex], false);
if (withhold) {
- button1.setText(LocalText.getText("WITHHOLD"));
+ button1.setRailsIcon(RailsIcon.WITHOLD);
button1.setActionCommand(WITHHOLD_CMD);
clonedAction = (SetDividend) action.clone();
clonedAction.setRevenueAllocation(SetDividend.WITHHOLD);
@@ -1196,7 +1196,7 @@ implements ActionListener, KeyListener, RevenueListener {
}
if (split) {
- button2.setText(LocalText.getText("SPLIT"));
+ button2.setRailsIcon(RailsIcon.SPLIT);
button2.setActionCommand(SPLIT_CMD);
clonedAction = (SetDividend) action.clone();
clonedAction.setRevenueAllocation(SetDividend.SPLIT);
@@ -1209,7 +1209,7 @@ implements ActionListener, KeyListener, RevenueListener {
}
if (payout) {
- button3.setText(LocalText.getText("PAYOUT"));
+ button3.setRailsIcon(RailsIcon.PAYOUT);
button3.setActionCommand(PAYOUT_CMD);
clonedAction = (SetDividend) action.clone();
clonedAction.setRevenueAllocation(SetDividend.PAYOUT);
@@ -1227,7 +1227,7 @@ implements ActionListener, KeyListener, RevenueListener {
setHighlight(trains[orCompIndex],true);
setHighlight(newTrainCost[orCompIndex],true);
- button1.setText(LocalText.getText("BUY_TRAIN"));
+ button1.setRailsIcon(RailsIcon.BUY_TRAIN);
button1.setActionCommand(BUY_TRAIN_CMD);
button1.setMnemonic(KeyEvent.VK_T);
button1.setEnabled(enabled);
@@ -1248,7 +1248,7 @@ implements ActionListener, KeyListener, RevenueListener {
if (privatesCanBeBought) {
if (enabled) {
- button2.setText(LocalText.getText("BUY_PRIVATE"));
+ button2.setRailsIcon(RailsIcon.BUY_PRIVATE);
button2.setActionCommand(BUY_PRIVATE_CMD);
button2.setMnemonic(KeyEvent.VK_V);
}
@@ -1280,7 +1280,7 @@ implements ActionListener, KeyListener, RevenueListener {
public void enableDone(NullAction action) {
- button3.setText(LocalText.getText("Done"));
+ button3.setRailsIcon(RailsIcon.DONE);
button3.setActionCommand(DONE_CMD);
button3.setMnemonic(KeyEvent.VK_D);
button3.setPossibleAction(action);
@@ -1310,7 +1310,7 @@ implements ActionListener, KeyListener, RevenueListener {
loansCaption.setHighlight(true);
setHighlight(compLoans[orCompIndex],true);
- button1.setText(LocalText.getText("RepayLoans"));
+ button1.setRailsIcon(RailsIcon.REPAY_LOANS);
button1.setActionCommand(REPAY_LOANS_CMD);
button1.setPossibleAction(action);
button1.setMnemonic(KeyEvent.VK_R);
diff --git a/rails/ui/swing/ReportWindowDynamic.java b/rails/ui/swing/ReportWindowDynamic.java
index a5c6128..00daad2 100644
--- a/rails/ui/swing/ReportWindowDynamic.java
+++ b/rails/ui/swing/ReportWindowDynamic.java
@@ -22,6 +22,7 @@ import rails.game.action.PossibleActions;
import rails.game.move.MoveStack;
import rails.sound.SoundManager;
import rails.ui.swing.elements.ActionButton;
+import rails.ui.swing.elements.RailsIcon;
/**
* Dynamic Report window that acts as linked game history
@@ -109,11 +110,11 @@ public class ReportWindowDynamic extends AbstractReportWindow implements Action
buttonPanel = new JPanel();
add(buttonPanel, "South");
- backwardButton = new ActionButton(LocalText.getText("REPORT_MOVE_BACKWARD"));
+ backwardButton = new ActionButton(RailsIcon.REPORT_MOVE_BACKWARD);
backwardButton.addActionListener(this);
buttonPanel.add(backwardButton);
- forwardButton = new ActionButton(LocalText.getText("REPORT_MOVE_FORWARD"));
+ forwardButton = new ActionButton(RailsIcon.REPORT_MOVE_FORWARD);
forwardButton.addActionListener(this);
buttonPanel.add(forwardButton);
diff --git a/rails/ui/swing/StartRoundWindow.java b/rails/ui/swing/StartRoundWindow.java
index 1ff36cd..a2c83eb 100644
--- a/rails/ui/swing/StartRoundWindow.java
+++ b/rails/ui/swing/StartRoundWindow.java
@@ -134,14 +134,14 @@ implements ActionListener, KeyListener, ActionPerformer, DialogOwner {
buttonPanel = new JPanel();
- buyButton = new ActionButton(LocalText.getText("BUY"));
+ buyButton = new ActionButton(RailsIcon.BUY);
buyButton.setMnemonic(KeyEvent.VK_B);
buyButton.addActionListener(this);
buyButton.setEnabled(false);
buttonPanel.add(buyButton);
if (includeBidding) {
- bidButton = new ActionButton(LocalText.getText("BID") + ":");
+ bidButton = new ActionButton(RailsIcon.BID);
bidButton.setMnemonic(KeyEvent.VK_D);
bidButton.addActionListener(this);
bidButton.setEnabled(false);
@@ -156,7 +156,7 @@ implements ActionListener, KeyListener, ActionPerformer, DialogOwner {
buttonPanel.add(bidAmount);
}
- passButton = new ActionButton(LocalText.getText("PASS"));
+ passButton = new ActionButton(RailsIcon.PASS);
passButton.setMnemonic(KeyEvent.VK_P);
passButton.addActionListener(this);
passButton.setEnabled(false);
@@ -518,7 +518,7 @@ implements ActionListener, KeyListener, ActionPerformer, DialogOwner {
// only one NullAction is allowed
NullAction na = inactiveItems.get(0);
// nullActions differ in text to display
- passButton.setText(LocalText.getText(na.toString()));
+ passButton.setRailsIcon(RailsIcon.getByConfigKey(na.toString()));
passAllowed = true;
passButton.setPossibleAction(na);
passButton.setMnemonic(KeyEvent.VK_P);
@@ -586,7 +586,7 @@ implements ActionListener, KeyListener, ActionPerformer, DialogOwner {
// In this case, "Pass" becomes "Select, don't buy"
passButton.setPossibleAction(currentActiveItem);
passButton.setEnabled(true);
- passButton.setText(LocalText.getText("SelectNoBid"));
+ passButton.setRailsIcon(RailsIcon.SELECT_NO_BID);
passButton.setVisible(true);
// if (!repacked) {
pack();
@@ -797,7 +797,7 @@ implements ActionListener, KeyListener, ActionPerformer, DialogOwner {
}
private ImageIcon createInfoIcon() {
- return RailsIcon.INFO.icon;
+ return RailsIcon.INFO.largeIcon;
}
public void keyPressed(KeyEvent e) {
diff --git a/rails/ui/swing/StatusWindow.java b/rails/ui/swing/StatusWindow.java
index 77db336..6271180 100644
--- a/rails/ui/swing/StatusWindow.java
+++ b/rails/ui/swing/StatusWindow.java
@@ -285,13 +285,13 @@ KeyListener, ActionPerformer {
buttonPanel = new JPanel();
- passButton = new ActionButton(LocalText.getText("PASS"));
+ passButton = new ActionButton(RailsIcon.PASS);
passButton.setMnemonic(KeyEvent.VK_P);
buttonPanel.add(passButton);
passButton.setActionCommand(DONE_CMD);
passButton.addActionListener(this);
- autopassButton = new ActionButton(LocalText.getText("Autopass"));
+ autopassButton = new ActionButton(RailsIcon.AUTOPASS);
autopassButton.setMnemonic(KeyEvent.VK_A);
buttonPanel.add(autopassButton);
autopassButton.setActionCommand(AUTOPASS_CMD);
@@ -547,14 +547,14 @@ KeyListener, ActionPerformer {
for (NullAction na : inactiveItems) {
switch (na.getMode()) {
case NullAction.PASS:
- passButton.setText(LocalText.getText("PASS"));
+ passButton.setRailsIcon(RailsIcon.PASS);
passButton.setEnabled(true);
passButton.setActionCommand(PASS_CMD);
passButton.setMnemonic(KeyEvent.VK_P);
passButton.setPossibleAction(na);
break;
case NullAction.DONE:
- passButton.setText(LocalText.getText("Done"));
+ passButton.setRailsIcon(RailsIcon.DONE);
passButton.setEnabled(true);
passButton.setActionCommand(DONE_CMD);
passButton.setMnemonic(KeyEvent.VK_D);
@@ -698,9 +698,9 @@ KeyListener, ActionPerformer {
if (action != null) {
int mode = action.getMode();
if (mode == NullAction.PASS) {
- passButton.setText(LocalText.getText("PASS"));
+ passButton.setRailsIcon(RailsIcon.PASS);
} else if (mode == NullAction.DONE) {
- passButton.setText(LocalText.getText("Done"));
+ passButton.setRailsIcon(RailsIcon.DONE);
}
passButton.setEnabled(true);
passButton.setVisible(true);
@@ -750,7 +750,7 @@ KeyListener, ActionPerformer {
// Enable Passbutton
passButton.setEnabled(true);
- passButton.setText(LocalText.getText("END_OF_GAME_CLOSE_ALL_WINDOWS"));
+ passButton.setRailsIcon(RailsIcon.END_OF_GAME_CLOSE_ALL_WINDOWS);
gameUIManager.orWindow.finish();
}
diff --git a/rails/ui/swing/elements/ActionButton.java b/rails/ui/swing/elements/ActionButton.java
index b2c06aa..2594741 100644
--- a/rails/ui/swing/elements/ActionButton.java
+++ b/rails/ui/swing/elements/ActionButton.java
@@ -1,11 +1,16 @@
/* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/ui/swing/elements/ActionButton.java,v 1.5 2008/06/04 19:00:38 evos Exp $*/
package rails.ui.swing.elements;
+import java.awt.Insets;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import javax.swing.JButton;
+import rails.common.parser.Config;
import rails.game.action.ActionTaker;
import rails.game.action.PossibleAction;
@@ -18,10 +23,34 @@ public class ActionButton extends JButton implements ActionTaker {
private static final long serialVersionUID = 1L;
+ private static final Set<String> KEYS_TEXT_DISPLAY = new HashSet<String>
+ (Arrays.asList( new String[] {
+ "text and icon",
+ "only text",
+ "",
+ null
+ }));
+ private static final Set<String> KEYS_ICON_DISPLAY = new HashSet<String>
+ (Arrays.asList( new String[] {
+ "text and icon",
+ "only icon"
+ }));
+
+ private static Set<ActionButton> actionButtons = new HashSet<ActionButton>();
+
private List<PossibleAction> actions = new ArrayList<PossibleAction>(1);
- public ActionButton(String text) {
- super(text);
+ /**
+ * null value means that the action button is not set up by an appropriate
+ * RailsIcon (eg., by calling setText directly).
+ */
+ private RailsIcon railsIcon = null;
+
+ public ActionButton(RailsIcon railsIcon) {
+ super();
+ setRailsIcon(railsIcon);
+ this.setMargin(new Insets(2,2,2,2));
+ actionButtons.add(this);
}
public void addPossibleAction(PossibleAction o) {
@@ -41,4 +70,70 @@ public class ActionButton extends JButton implements ActionTaker {
addPossibleAction(action);
}
+ public void setRailsIcon(RailsIcon railsIcon) {
+ if (railsIcon == null) railsIcon = RailsIcon.NULL;
+ this.railsIcon = railsIcon;
+ showRailsIcon();
+ }
+
+ /**
+ * Display according to configuration.
+ * If no text/icon is attached, then icon/text is displayed as fallback
+ * (irrespective of configuration).
+ * Text becomes the tool tip text in case of icon-only display.
+ */
+ private void showRailsIcon() {
+ if (railsIcon != null) {
+ if (isTextEnabled() || railsIcon.largeIcon == null) {
+ super.setText(railsIcon.description);
+ } else {
+ super.setText(null);
+ }
+ if (isIconEnabled() || railsIcon.description == null) {
+ if (isIconSizeSmall()) {
+ super.setIcon(railsIcon.smallIcon);
+ } else {
+ super.setIcon(railsIcon.largeIcon);
+ }
+ if (!isTextEnabled()) {
+ super.setToolTipText(railsIcon.description);
+ }
+ } else {
+ super.setIcon(null);
+ }
+ }
+ }
+
+ private boolean isTextEnabled() {
+ return KEYS_TEXT_DISPLAY.contains(Config.get("actionButton.iconText",""));
+ }
+
+ private boolean isIconEnabled() {
+ return KEYS_ICON_DISPLAY.contains(Config.get("actionButton.iconText",""));
+ }
+
+ private boolean isIconSizeSmall() {
+ return "small".equals(Config.get("actionButton.iconSize"));
+ }
+
+ /**
+ * Should only be used if an arbitrary text is to displayed without icon.
+ * In any other case, setRailsIcon should be used.
+ */
+ @Override
+ public void setText(String text) {
+ super.setText(text);
+ setIcon(null);
+ railsIcon = null;
+ }
+
+ /**
+ * To be called upon change of button display type
+ */
+ public static void resetRailsIcons() {
+ for (ActionButton ab : actionButtons) {
+ ab.showRailsIcon();
+ }
+ }
+
}
diff --git a/rails/ui/swing/elements/RailsIcon.java b/rails/ui/swing/elements/RailsIcon.java
index 0eaba36..eed61ff 100644
--- a/rails/ui/swing/elements/RailsIcon.java
+++ b/rails/ui/swing/elements/RailsIcon.java
@@ -1,30 +1,125 @@
package rails.ui.swing.elements;
+import java.awt.Image;
+
import javax.swing.ImageIcon;
+import rails.common.LocalText;
+
/**
* Enumeration that provides a specific ImageIcon
- * Simply use RailsIcon.{IconName}.create
+ * Simply use RailsIcon.{IconName}.icon/description
* @author freystef
*/
public enum RailsIcon {
// in parentheses the image file
- INFO ("Inform.gif");
-
- private final static String IMAGE_PATH = "/rails/ui/images/";
- public final ImageIcon icon;
+ AUTOPASS ("","Autopass"),
+ BID ("","BID"),
+ BUY ("","BUY"),
+ BUY_PRIVATE ("","BUY_PRIVATE"),
+ BUY_TRAIN ("","BUY_TRAIN"),
+ DONE ("","Done"),
+ END_OF_GAME_CLOSE_ALL_WINDOWS ("","END_OF_GAME_CLOSE_ALL_WINDOWS"),
+ INFO ("Inform.gif","Info"),
+ LAY_TILE ("","LayTile"),
+ OPERATING_COST ("","OCButtonLabel"),
+ PASS ("","PASS"),
+ PAYOUT ("","PAYOUT"),
+ REDO ("","REDO"),
+ REPAY_LOANS ("","RepayLoans"),
+ REPORT_MOVE_BACKWARD ("","REPORT_MOVE_BACKWARD"),
+ REPORT_MOVE_FORWARD ("","REPORT_MOVE_FORWARD"),
+ SELECT_NO_BID ("","SelectNoBid"),
+ SET_REVENUE ("","SET_REVENUE"),
+ SPLIT ("","SPLIT"),
+ UNDO ("","UNDO"),
+ WITHOLD ("","WITHHOLD"),
+
+ //null meaning all public fields are null
+ NULL ();
+
+ private final static String IMAGE_PATH = "/rails/ui/images/";
+ private final static int SMALL_IMAGE_WIDTH = 16;
+ private final static int SMALL_IMAGE_HEIGHT = 16;
+ private final String configKey;
+ /**
+ * icon in original resolution
+ */
+ public final ImageIcon largeIcon;
+ /**
+ * icon in restricted / small resolution
+ */
+ public final ImageIcon smallIcon;
+ public final String description;
+
+ private RailsIcon() {
+ configKey = null;
+ largeIcon = null;
+ smallIcon = null;
+ description = null;
+ }
+
+ private RailsIcon(String fileName,String configKey) {
+ this.configKey = configKey;
+ this.description = LocalText.getText(configKey);
+ largeIcon = createIcon(fileName,description);
+ smallIcon = createSmallIcon(largeIcon);
+ }
- private RailsIcon(String fileName) {
+ private ImageIcon createIcon(String fileName, String description) {
+ //check whether icon is expected to be found
+ //don't write error messages if icon not expected to be found
+ if (fileName == null || fileName.equals("")) {
+ return null;
+ }
+
+ //get icon
String path = IMAGE_PATH + fileName;
java.net.URL imgURL = getClass().getResource(path);
if (imgURL != null) {
- icon = new ImageIcon(imgURL, "Info");
+ return new ImageIcon(imgURL, description);
} else {
System.err.println("Couldn't find file: " + path);
- icon = null;
+ return null;
+ }
+ }
+
+ private ImageIcon createSmallIcon(ImageIcon originalIcon) {
+ ImageIcon smallIcon = null;
+ if (originalIcon != null) {
+ Image img = originalIcon.getImage();
+ if (img != null) {
+ smallIcon = new ImageIcon(
+ img.getScaledInstance(
+ SMALL_IMAGE_WIDTH,
+ SMALL_IMAGE_HEIGHT,
+ Image.SCALE_SMOOTH
+ ),
+ originalIcon.getDescription()
+ );
+ }
+ }
+ return smallIcon;
+ }
+
+ /**
+ * @return The Rails icon associated with the key or, if nothing is found,
+ * RailsConfig.NULL
+ */
+ public static RailsIcon getByConfigKey(String configKey) {
+ if (configKey == null) return RailsIcon.NULL;
+
+ RailsIcon ri = null;
+ for (RailsIcon r : RailsIcon.values()) {
+ //ignore case necessary as both Pass and PASS are used by consumers
+ if (configKey.equalsIgnoreCase(r.configKey)) ri = r;
+ }
+ if (ri == null) {
+ ri = RailsIcon.NULL;
}
+ return ri;
}
}
|
|
From: Frederick W. <fre...@us...> - 2012-02-10 17:58:59
|
LocalisedText.properties | 1
rails/ui/swing/ORPanel.java | 18 +++--
rails/ui/swing/ORWindow.java | 39 +++++++----
rails/ui/swing/RemainingTilesWindow.java | 80 +++++++++++++++++++-----
rails/ui/swing/elements/DockingFrame.java | 98 ++++++++++++++++++++++++------
5 files changed, 184 insertions(+), 52 deletions(-)
New commits:
commit feb1ae94d3506dcd676c09e9b439e8df894c2d6a
Author: Frederick Weld <fre...@gm...>
Date: Fri Feb 10 18:25:48 2012 +0100
Included "Remaining Tiles" into docking layout (as a dockable)
Change only applies to the docking layout.
Now, the remaining tiles panel is part of the ORWindow. Its
activation/positioning is done in the context of the docking
framework instead of the ORPanel menu and the JFrame.
Additionally, docking framework handles the tiles / messages window
as closable dockables. A dedicated menu option is available for
toggling the visibility.
diff --git a/LocalisedText.properties b/LocalisedText.properties
index 4f344b2..a0f256f 100644
--- a/LocalisedText.properties
+++ b/LocalisedText.properties
@@ -295,6 +295,7 @@ Dockable.orWindow.buttonPanel = Commands
Dockable.orWindow.mapPanel = Map
Dockable.orWindow.messagePanel = Messages
Dockable.orWindow.orPanel = Companies
+Dockable.orWindow.remainingTilesPanel = Tiles
Dockable.orWindow.upgradePanel = Upgrades
DockingFrame.menu.layout = Layout
DockingFrame.menu.layout.applyFrom = Apply From...
diff --git a/rails/ui/swing/ORPanel.java b/rails/ui/swing/ORPanel.java
index bd3ea58..280ef18 100644
--- a/rails/ui/swing/ORPanel.java
+++ b/rails/ui/swing/ORPanel.java
@@ -171,11 +171,17 @@ implements ActionListener, KeyListener, RevenueListener {
infoMenu = new JMenu(LocalText.getText("Info"));
infoMenu.setEnabled(true);
- remainingTilesMenuItem =
- new JMenuItem(LocalText.getText("RemainingTiles"));
- remainingTilesMenuItem.addActionListener(this);
- remainingTilesMenuItem.setActionCommand(REM_TILES_CMD);
- infoMenu.add(remainingTilesMenuItem);
+
+ //only add remaining tiles display option for conventional layout
+ //as this is always included as a dockable panel in the docking frame layout
+ if (!parent.isDockingFrameworkEnabled()) {
+ remainingTilesMenuItem =
+ new JMenuItem(LocalText.getText("RemainingTiles"));
+ remainingTilesMenuItem.addActionListener(this);
+ remainingTilesMenuItem.setActionCommand(REM_TILES_CMD);
+ infoMenu.add(remainingTilesMenuItem);
+ }
+
menuBar.add(infoMenu);
addCompanyInfo();
@@ -1360,4 +1366,4 @@ implements ActionListener, KeyListener, RevenueListener {
public JMenuBar getMenuBar() {
return menuBar;
}
-}
\ No newline at end of file
+}
diff --git a/rails/ui/swing/ORWindow.java b/rails/ui/swing/ORWindow.java
index 278e9b0..acee3e9 100644
--- a/rails/ui/swing/ORWindow.java
+++ b/rails/ui/swing/ORWindow.java
@@ -63,8 +63,8 @@ public class ORWindow extends DockingFrame implements ActionPerformer {
orUIManager.setGameUIManager(gameUIManager);
messagePanel = new MessagePanel();
- JScrollPane slider = new JScrollPane(messagePanel);
- messagePanel.setParentSlider(slider);
+ JScrollPane messagePanelSlider = new JScrollPane(messagePanel);
+ messagePanel.setParentSlider(messagePanelSlider);
upgradePanel = new UpgradesPanel(orUIManager);
addMouseListener(upgradePanel);
@@ -72,22 +72,33 @@ public class ORWindow extends DockingFrame implements ActionPerformer {
mapPanel = new MapPanel(gameUIManager);
orPanel = new ORPanel(this, orUIManager);
-
+
//create docking / conventional layout
if (isDockingFrameworkEnabled()) {
+
+ //initialize remaining tile panel as it is no optional part in the docking layout
+ JScrollPane remainingTilesPanelSlider =
+ new RemainingTilesWindow(this).getScrollPane();
//generate layout
- addDockable ( slider, LocalText.getText("Dockable.orWindow.messagePanel"),
- 0, 0, 100, 10);
- addDockable ( upgradePanel, LocalText.getText("Dockable.orWindow.upgradePanel"),
- 0, 10, 20, 70);
- addDockable ( mapPanel, LocalText.getText("Dockable.orWindow.mapPanel"),
- 20, 10, 80, 70);
- addDockable ( orPanel, LocalText.getText("Dockable.orWindow.orPanel"),
- 0, 80, 100, 15);
+ addDockable ( messagePanelSlider,
+ LocalText.getText("Dockable.orWindow.messagePanel"),
+ 0, 0, 100, 10, DockableProperty.closeable);
+ addDockable ( upgradePanel,
+ LocalText.getText("Dockable.orWindow.upgradePanel"),
+ 0, 10, 20, 70, DockableProperty.standard);
+ addDockable ( mapPanel,
+ LocalText.getText("Dockable.orWindow.mapPanel"),
+ 20, 10, 80, 70, DockableProperty.standard);
+ addDockable ( remainingTilesPanelSlider,
+ LocalText.getText("Dockable.orWindow.remainingTilesPanel"),
+ 100, 0, 120, 100, DockableProperty.initially_hidden);
+ addDockable ( orPanel,
+ LocalText.getText("Dockable.orWindow.orPanel"),
+ 0, 80, 100, 15, DockableProperty.standard);
addDockable ( orPanel.getButtonPanel(),
LocalText.getText("Dockable.orWindow.buttonPanel"),
- 0, 95, 100, 5);
+ 0, 95, 100, 5, DockableProperty.standard);
deployDockables();
//take over or panel's menu bar as the frame menu bar
@@ -99,7 +110,7 @@ public class ORWindow extends DockingFrame implements ActionPerformer {
// CONVENTIONAL LAYOUT
getContentPane().setLayout(new BorderLayout());
- getContentPane().add(slider, BorderLayout.NORTH);
+ getContentPane().add(messagePanelSlider, BorderLayout.NORTH);
getContentPane().add(mapPanel, BorderLayout.CENTER);
getContentPane().add(upgradePanel, BorderLayout.WEST);
getContentPane().add(orPanel, BorderLayout.SOUTH);
@@ -268,4 +279,4 @@ public class ORWindow extends DockingFrame implements ActionPerformer {
+ gameUIManager.getGameManager().getGameName() ;
}
-}
\ No newline at end of file
+}
diff --git a/rails/ui/swing/RemainingTilesWindow.java b/rails/ui/swing/RemainingTilesWindow.java
index f969505..0c3924f 100644
--- a/rails/ui/swing/RemainingTilesWindow.java
+++ b/rails/ui/swing/RemainingTilesWindow.java
@@ -44,6 +44,7 @@ public class RemainingTilesWindow extends JFrame implements WindowListener,
tilePanel = new AlignedWidthPanel();
slider = new JScrollPane(tilePanel);
slider.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
+ slider.setPreferredSize(new Dimension(200,200));
tilePanel.setParentSlider(slider);
//use flow layout as it provides for necessary line breaks
@@ -53,7 +54,7 @@ public class RemainingTilesWindow extends JFrame implements WindowListener,
//setup the JFrame and assign the contents (slider containing tilePane)
//only for conventional layout as this is a dockable pane for the docking layout
- if (true || !orWindow.isDockingFrameworkEnabled()) {
+ if (!orWindow.isDockingFrameworkEnabled()) {
setTitle("Rails: Remaining Tiles");
setVisible(false);
setContentPane(slider);
diff --git a/rails/ui/swing/elements/DockingFrame.java b/rails/ui/swing/elements/DockingFrame.java
index 8cc1203..78edec1 100644
--- a/rails/ui/swing/elements/DockingFrame.java
+++ b/rails/ui/swing/elements/DockingFrame.java
@@ -4,6 +4,8 @@ import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Locale;
import javax.swing.JComponent;
@@ -30,14 +32,17 @@ import bibliothek.gui.dock.common.action.predefined.CBlank;
import bibliothek.gui.dock.common.event.CDockableStateListener;
import bibliothek.gui.dock.common.intern.CDockable;
import bibliothek.gui.dock.common.intern.DefaultCDockable;
+import bibliothek.gui.dock.common.intern.DefaultCommonDockable;
import bibliothek.gui.dock.common.intern.ui.CSingleParentRemover;
import bibliothek.gui.dock.common.menu.CThemeMenuPiece;
+import bibliothek.gui.dock.common.menu.SingleCDockableListMenuPiece;
import bibliothek.gui.dock.common.mode.ExtendedMode;
import bibliothek.gui.dock.common.theme.ThemeMap;
import bibliothek.gui.dock.event.DockStationAdapter;
import bibliothek.gui.dock.facile.menu.RootMenuPiece;
import bibliothek.gui.dock.facile.menu.SubmenuPiece;
import bibliothek.gui.dock.station.LayoutLocked;
+import bibliothek.gui.dock.support.menu.SeparatingMenuPiece;
import org.apache.log4j.Logger;
@@ -53,6 +58,7 @@ import org.apache.log4j.Logger;
*
*/
public abstract class DockingFrame extends JFrame {
+ public static enum DockableProperty { standard, closeable, initially_hidden };
private static final long serialVersionUID = 1L;
private static final String layoutDirectoryName = "DockableLayout";
private static final String layoutFileSuffix = "_layout.rails_ini";
@@ -64,7 +70,13 @@ public abstract class DockingFrame extends JFrame {
private boolean isDockingFrameworkEnabled;
private CControl control = null;
private CGrid gridLayout = null;
-
+
+ /**
+ * All dockables under the control (currently only single dockables)
+ */
+ List<DefaultSingleCDockable> dockables = new ArrayList<DefaultSingleCDockable>();
+ List<DefaultSingleCDockable> dockables_initiallyHidden = new ArrayList<DefaultSingleCDockable>();
+
/**
* Decision whether docking framework should be activated for a frame
* has to be done at the beginning as later switching is not supported
@@ -101,19 +113,34 @@ public abstract class DockingFrame extends JFrame {
* Registers a component that is to become a dockable.
* The dockable is only deployed to the frame if deployDockables is called.
*/
- protected void addDockable(JComponent c, String dockableTitle, int x, int y, int width, int height) {
+ protected void addDockable(JComponent c,
+ String dockableTitle,
+ int x, int y, int width, int height,
+ DockableProperty dockableProperty) {
DefaultSingleCDockable d = new DefaultSingleCDockable(
dockableTitle, dockableTitle );
d.add( c, BorderLayout.CENTER );
- d.setCloseable( false );
+ d.setTitleIcon(null);
+ d.setCloseable(
+ ( dockableProperty == DockableProperty.closeable
+ || dockableProperty == DockableProperty.initially_hidden )
+ );
gridLayout.add( x, y, width, height, d );
+ dockables.add(d);
+ if (dockableProperty == DockableProperty.initially_hidden) {
+ dockables_initiallyHidden.add(d);
+ }
}
/**
- * Deploys to the frame all dockables that have been added before
+ * Deploys to the frame all dockables that have been added before.
+ * Dockables are initially set to invisible if this is as specified
*/
protected void deployDockables() {
control.getContentArea().deploy( gridLayout );
+ for (CDockable d : dockables_initiallyHidden) {
+ if (d.isCloseable()) d.setVisible(false);
+ }
}
/**
@@ -123,12 +150,26 @@ public abstract class DockingFrame extends JFrame {
RootMenuPiece layoutMenu = new RootMenuPiece(
LocalText.getText("DockingFrame.menu.layout"),
false);
+
layoutMenu.add( new SubmenuPiece(
LocalText.getText("DockingFrame.menu.layout.theme"),
false,
new CThemeMenuPiece( control )
));
- layoutMenu.getMenu().addSeparator();
+
+ SingleCDockableListMenuPiece closeableDockableMenuPiece =
+ new SingleCDockableListMenuPiece(control) {
+ @Override
+ protected void show(Dockable dockable) {
+ super.show(dockable);
+ //ensure that, if the dockable is externalized, the max button is disabled
+ if (dockable instanceof DefaultCommonDockable) {
+ adjustExternalizedActions((DefaultCommonDockable)dockable);
+ }
+ }
+ };
+ layoutMenu.add(new SeparatingMenuPiece(closeableDockableMenuPiece,true,true,true));
+
JMenuItem resetMenuItem = new JMenuItem (
LocalText.getText("DockingFrame.menu.layout.reset"));
resetMenuItem.addActionListener(new ActionListener() {
@@ -224,22 +265,42 @@ public abstract class DockingFrame extends JFrame {
return;
}
- //ensure that all dockables that are externalized according to layout
- //information don't have the default maximize button (as it won't work
- //for the adjusted externalization setup)
- for (int i = 0 ; i < control.getCDockableCount() ; i++ ) {
- CDockable d = control.getCDockable(i);
- if (d instanceof DefaultCDockable) {
- DefaultCDockable dd = (DefaultCDockable)d;
- if (ExtendedMode.EXTERNALIZED.equals(d.getExtendedMode())) {
- dd.putAction( CDockable.ACTION_KEY_MAXIMIZE, CBlank.BLANK );
- } else {
- dd.putAction( CDockable.ACTION_KEY_MAXIMIZE, null );
- }
+ adjustExternalizedActions();
+ }
+
+ /**
+ * Ensures for all dockables that, if they are externalized, they do not have
+ * the default maximize button
+ * (as it won't work for the adjusted externalization setup).
+ */
+ private void adjustExternalizedActions() {
+ for (CDockable d : dockables) {
+ adjustExternalizedActions(d);
+ }
+ }
+
+ /**
+ * Ensure that externalized dockable does not have default maximize button
+ * (as it won't work for the adjusted externalization setup).
+ * @param d Dockable for which the actions are to be adjusted
+ */
+ private void adjustExternalizedActions(CDockable d) {
+ if (d instanceof DefaultSingleCDockable) {
+ DefaultSingleCDockable sd = (DefaultSingleCDockable)d;
+ if (ExtendedMode.EXTERNALIZED.equals(sd.getExtendedMode())) {
+ sd.putAction( CDockable.ACTION_KEY_MAXIMIZE, CBlank.BLANK );
+ } else {
+ sd.putAction( CDockable.ACTION_KEY_MAXIMIZE, null );
}
}
}
+ private void adjustExternalizedActions(Dockable d) {
+ if (d instanceof DefaultCommonDockable) {
+ adjustExternalizedActions(((DefaultCommonDockable)d).getDockable());
+ }
+ }
+
/**
* Lets user choose a layout in a file chooser popup and then loads/applies it
*/
@@ -340,6 +401,9 @@ public abstract class DockingFrame extends JFrame {
// and enable events after we finished
controller.meltLayout();
}
+
+ //ensure the correct availability of the maximize button
+ adjustExternalizedActions(dockable);
}
}
commit e2fd3ff42eea4edeee1d7a97f579e750af729d84
Author: Frederick Weld <fre...@gm...>
Date: Thu Feb 9 20:13:41 2012 +0100
Enabled variable layout of "Remaining Tiles" incl. vertical scroll bar
diff --git a/rails/ui/swing/RemainingTilesWindow.java b/rails/ui/swing/RemainingTilesWindow.java
index 9c9d2ff..f969505 100644
--- a/rails/ui/swing/RemainingTilesWindow.java
+++ b/rails/ui/swing/RemainingTilesWindow.java
@@ -1,7 +1,9 @@
/* $Header: /Users/blentz/rails_rcs/cvs/18xx/rails/ui/swing/RemainingTilesWindow.java,v 1.8 2009/12/15 18:56:11 evos Exp $*/
package rails.ui.swing;
-import java.awt.GridLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
import java.awt.Image;
import java.awt.event.*;
import java.awt.image.BufferedImage;
@@ -20,39 +22,49 @@ import rails.ui.swing.elements.Field;
import rails.ui.swing.hexmap.GUIHex;
/**
- * This Window displays the available operations that may be performed during an
- * Operating Round. This window also contains the Game Map.
+ * This Window displays the availability of tiles.
*/
public class RemainingTilesWindow extends JFrame implements WindowListener,
ActionListener {
private static final long serialVersionUID = 1L;
private GameUIManager gameUIManager;
private ORUIManager orUIManager;
+ private AlignedWidthPanel tilePanel;
+ private JScrollPane slider;
private List<Field> labels = new ArrayList<Field>();
private List<TileI> shownTiles = new ArrayList<TileI>();
- private final static int COLUMNS = 10;
-
protected static Logger log =
Logger.getLogger(RemainingTilesWindow.class.getPackage().getName());
public RemainingTilesWindow(ORWindow orWindow) {
super();
- getContentPane().setLayout(new GridLayout(0, COLUMNS, 5, 5));
+ tilePanel = new AlignedWidthPanel();
+ slider = new JScrollPane(tilePanel);
+ slider.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
+ tilePanel.setParentSlider(slider);
- setTitle("Rails: Remaining Tiles");
- setVisible(false);
- setSize(800, 600);
- addWindowListener(this);
+ //use flow layout as it provides for necessary line breaks
+ tilePanel.setLayout(new FlowLayout(FlowLayout.LEFT));
init(orWindow.getGameUIManager());
- this.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
- this.setLocationRelativeTo(orWindow);
- pack();
- setVisible(true);
+ //setup the JFrame and assign the contents (slider containing tilePane)
+ //only for conventional layout as this is a dockable pane for the docking layout
+ if (true || !orWindow.isDockingFrameworkEnabled()) {
+ setTitle("Rails: Remaining Tiles");
+ setVisible(false);
+ setContentPane(slider);
+ setSize(800, 600);
+ addWindowListener(this);
+
+ this.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
+ this.setLocationRelativeTo(orWindow);
+
+ setVisible(true);
+ }
}
private void init(GameUIManager gameUIManager) {
@@ -87,7 +99,7 @@ public class RemainingTilesWindow extends JFrame implements WindowListener,
label.setHorizontalTextPosition(Field.CENTER);
label.setVisible(true);
- getContentPane().add(label);
+ tilePanel.add(label);
shownTiles.add(tile);
labels.add(label);
@@ -134,4 +146,41 @@ public class RemainingTilesWindow extends JFrame implements WindowListener,
*
*/
public void finish() {}
+
+ /**
+ * @return The scroll pane which holds as child the tile panel
+ */
+ public JScrollPane getScrollPane() {
+ return slider;
+ }
+
+ /**
+ * custom content pane that will align its width with the parent scroll pane
+ * needed to ensure only vertical scroll bar is used
+ */
+ private static class AlignedWidthPanel extends JPanel {
+ private static final long serialVersionUID = 1L;
+ private JScrollPane parentSlider = null;
+ @Override
+ public Dimension getPreferredSize() {
+ //width based on parent slider
+ int width = parentSlider.getSize().width
+ - parentSlider.getVerticalScrollBar().getWidth()
+ - 5;
+ if (width <= 0) width = 1;
+
+ //height based on contained components
+ //(no need to take into account width discrepancies since
+ // method is invoked several times)
+ int height = 1; //minimum height
+ for (Component c : this.getComponents()) {
+ height = Math.max(height, c.getY() + c.getHeight());
+ }
+ return new Dimension (width , height);
+ }
+ public void setParentSlider(JScrollPane parentSlider) {
+ this.parentSlider = parentSlider;
+ }
+ }
+
}
|
|
From: Frederick W. <fre...@us...> - 2012-02-08 18:31:46
|
rails/ui/swing/MessagePanel.java | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
New commits:
commit f9839fa2ddce01e0b850d384fa10613f7de51812
Author: Frederick Weld <fre...@gm...>
Date: Wed Feb 8 19:29:33 2012 +0100
Allowed for dynamic line breaks and vertical centering of message panel
Main motivation for rework is that the dockable message text might
be put in a vertical alignment (of narrow width).
For the message panel, new behavior is that
- no horizontal scroll bar is used
- if panel's width inferior to message label's native width, a line
break is inserted into the label text
- technically done by using a layout manager and basing the panel's
preferred width on the parent scrollpane's one
An additional benefit of using the layout manager is that, for the
first time since having added the scrollbar to the panel, messages
are vertically centered.
diff --git a/rails/ui/swing/MessagePanel.java b/rails/ui/swing/MessagePanel.java
index 3b3d2cc..ed785de 100644
--- a/rails/ui/swing/MessagePanel.java
+++ b/rails/ui/swing/MessagePanel.java
@@ -3,6 +3,7 @@ package rails.ui.swing;
import java.awt.Color;
import java.awt.Dimension;
+import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
@@ -37,6 +38,10 @@ public class MessagePanel extends JPanel {
setBackground(background);
setBorder(new EmptyBorder(0,0,0,0));
+ //add layout manager
+ //necessary for auto word-wrap when diminishing width
+ setLayout(new GridLayout(1,1));
+
message = new JLabel("");
message.setBackground(background);
message.setVerticalAlignment(SwingConstants.CENTER);
@@ -138,5 +143,15 @@ public class MessagePanel extends JPanel {
currentDetails = "<BR>" + detailText;
updateMessageText();
}
-
+
+ @Override
+ public Dimension getPreferredSize() {
+ Dimension nativeSize = super.getPreferredSize();
+ if (parentSlider == null) return nativeSize;
+ int width = parentSlider.getSize().width
+ - parentSlider.getVerticalScrollBar().getWidth()
+ - 5;
+ if (width <= 0) width = 1;
+ return new Dimension (width , nativeSize.height);
+ }
}
|
|
From: Frederick W. <fre...@us...> - 2012-02-08 17:17:51
|
LocalisedText.properties | 14 -
rails/ui/swing/GameUIManager.java | 2
rails/ui/swing/ORPanel.java | 19 +
rails/ui/swing/ORWindow.java | 276 ++---------------------
rails/ui/swing/UpgradesPanel.java | 2
rails/ui/swing/elements/DockingFrame.java | 346 ++++++++++++++++++++++++++++++
6 files changed, 402 insertions(+), 257 deletions(-)
New commits:
commit 85873585f82f47e4a5f752195b76412eb12edd33
Author: Frederick Weld <fre...@gm...>
Date: Wed Feb 8 18:17:01 2012 +0100
Corrected comment for ORPanel's add JSpinner to Grid
diff --git a/rails/ui/swing/ORPanel.java b/rails/ui/swing/ORPanel.java
index ab3bf8f..bd3ea58 100644
--- a/rails/ui/swing/ORPanel.java
+++ b/rails/ui/swing/ORPanel.java
@@ -604,9 +604,9 @@ implements ActionListener, KeyListener, RevenueListener {
f = revenue[i] = new Field(c.getLastRevenueModel());
addField(f, revXOffset, revYOffset + i, 1, 1, 0, visible);
f = revenueSelect[i] = new Spinner(0, 0, 0, 10);
- //zero-border so that size matches revenue field (thus, averting or panel resize)
+ //align spinner size with field size
+ //(so that changes to visibility don't affect panel sizing)
f.setPreferredSize(revenue[i].getPreferredSize());
- //f.setBorder(new javax.swing.border.EmptyBorder(0,0,0,0));
addField(f, revXOffset, revYOffset + i, 1, 1, 0, false);
// deactived below, as this caused problems by gridpanel rowvisibility function -- sfy
// revenue[i].addDependent(revenueSelect[i]);
commit d0bc83b44b210e1f9dc0cddb32dc543a4067ef84
Author: Frederick Weld <fre...@gm...>
Date: Tue Feb 7 19:49:01 2012 +0100
Reworked dockingframe logging / popups
Now:
- logging entry instead of popup for layout save.
- no popup during initial tentative layout load.
diff --git a/rails/ui/swing/elements/DockingFrame.java b/rails/ui/swing/elements/DockingFrame.java
index 8452ce0..8cc1203 100644
--- a/rails/ui/swing/elements/DockingFrame.java
+++ b/rails/ui/swing/elements/DockingFrame.java
@@ -158,7 +158,7 @@ public abstract class DockingFrame extends JFrame {
*/
protected void initLayout() {
control.save(layoutName_initial);
- loadLayout();
+ loadLayout(getLayoutFile(),true);
}
/**
@@ -199,17 +199,16 @@ public abstract class DockingFrame extends JFrame {
control.writeXML(layoutFile);
log.info("Layout saved to " + layoutFile.getName());
} catch (Exception e) {
- JOptionPane.showMessageDialog(this,
- "Unable to save layout to " + layoutFile.getName());
+ log.error("Layout could not be saved to " + layoutFile.getName());
return;
}
}
- private void loadLayout() {
- loadLayout(getLayoutFile());
- }
-
- private void loadLayout(File layoutFile) {
+ /**
+ * @param isTentative If true, then method only tries to load specified layout
+ * but would not produce any error popup.
+ */
+ private void loadLayout(File layoutFile, boolean isTentative) {
if (!isDockingFrameworkEnabled) return;
try {
@@ -217,8 +216,11 @@ public abstract class DockingFrame extends JFrame {
control.load(layoutName_current);
log.info("Layout loaded from " + layoutFile.getName());
} catch (Exception e) {
- JOptionPane.showMessageDialog(this,
- "Unable to load layout from " + layoutFile.getName());
+ if (!isTentative) {
+ JOptionPane.showMessageDialog(this,
+ "Unable to load layout from " + layoutFile.getName());
+ }
+ log.error("Layout could not be loaded from " + layoutFile.getName());
return;
}
@@ -245,7 +247,7 @@ public abstract class DockingFrame extends JFrame {
JFileChooser jfc = new JFileChooser();
jfc.setCurrentDirectory(getLayoutDirectory());
if (jfc.showOpenDialog(getContentPane()) != JFileChooser.APPROVE_OPTION) return; // cancel pressed
- loadLayout(jfc.getSelectedFile());
+ loadLayout(jfc.getSelectedFile(),false);
}
/**
commit 21afe1d386c3a4d3d5b2987f8dab27d2c01698b0
Author: Frederick Weld <fre...@gm...>
Date: Tue Feb 7 17:49:58 2012 +0100
Added docking features: apply template, logging, error popups
Added feature to pick existing docking layouts as template. Menu item
is called "Apply from..." and lets the user choose from the list of
persisted layouts.
Logging and error popups are added to the steps of loading/saving
docking layouts.
diff --git a/rails/ui/swing/elements/DockingFrame.java b/rails/ui/swing/elements/DockingFrame.java
index 52375d0..8452ce0 100644
--- a/rails/ui/swing/elements/DockingFrame.java
+++ b/rails/ui/swing/elements/DockingFrame.java
@@ -1,6 +1,3 @@
-/**
- *
- */
package rails.ui.swing.elements;
import java.awt.BorderLayout;
@@ -10,9 +7,11 @@ import java.io.File;
import java.util.Locale;
import javax.swing.JComponent;
+import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import rails.common.LocalText;
@@ -40,6 +39,8 @@ import bibliothek.gui.dock.facile.menu.RootMenuPiece;
import bibliothek.gui.dock.facile.menu.SubmenuPiece;
import bibliothek.gui.dock.station.LayoutLocked;
+import org.apache.log4j.Logger;
+
/**
* Superclass for all application frames that want to use the docking
* framework for managing its panels.
@@ -53,12 +54,13 @@ import bibliothek.gui.dock.station.LayoutLocked;
*/
public abstract class DockingFrame extends JFrame {
private static final long serialVersionUID = 1L;
- private static final String layoutFolderName = "DockableLayout";
+ private static final String layoutDirectoryName = "DockableLayout";
private static final String layoutFileSuffix = "_layout.rails_ini";
private static final String layoutName_initial = "InitialLayout";
private static final String layoutName_current = "CurrentLayout";
private static final String defaultTheme = ThemeMap.KEY_BASIC_THEME;
-
+ private static Logger log = Logger.getLogger(DockingFrame.class.getPackage().getName());
+
private boolean isDockingFrameworkEnabled;
private CControl control = null;
private CGrid gridLayout = null;
@@ -140,7 +142,7 @@ public abstract class DockingFrame extends JFrame {
LocalText.getText("DockingFrame.menu.layout.applyFrom"));
applyFromMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
- //TODO: apply from
+ loadLayoutUserDefined();
}
});
layoutMenu.getMenu().add(applyFromMenuItem);
@@ -165,31 +167,41 @@ public abstract class DockingFrame extends JFrame {
*/
abstract protected String getLayoutFileName();
- private File getLayoutFile() {
+ /**
+ * get layout directory (and ensure that it is available)
+ */
+ private File getLayoutDirectory() {
try {
- //get layout folder (and ensure that it is available)
- File layoutFolder = new File(Config.get("save.directory"),layoutFolderName);
- if (!layoutFolder.isDirectory()) {
- layoutFolder.mkdirs();
+ File layoutDirectory = new File(Config.get("save.directory"),layoutDirectoryName);
+ if (!layoutDirectory.isDirectory()) {
+ layoutDirectory.mkdirs();
}
- File layoutFile = new File(layoutFolder,
- getLayoutFileName() + layoutFileSuffix );
- return layoutFile;
- } catch (Exception e) {
+ return layoutDirectory;
+ }
+ catch (Exception e) {
//return no valid file if anything goes wrong
return null;
}
}
+ private File getLayoutFile() {
+ File layoutFile = new File(getLayoutDirectory(),
+ getLayoutFileName() + layoutFileSuffix );
+ return layoutFile;
+ }
+
public void saveLayout() {
if (!isDockingFrameworkEnabled) return;
File layoutFile = getLayoutFile();
- if (layoutFile != null) {
- try {
- control.save(layoutName_current);
- control.writeXML(layoutFile);
- } catch (Exception e) {} //skip in case of issue
+ try {
+ control.save(layoutName_current);
+ control.writeXML(layoutFile);
+ log.info("Layout saved to " + layoutFile.getName());
+ } catch (Exception e) {
+ JOptionPane.showMessageDialog(this,
+ "Unable to save layout to " + layoutFile.getName());
+ return;
}
}
@@ -200,11 +212,14 @@ public abstract class DockingFrame extends JFrame {
private void loadLayout(File layoutFile) {
if (!isDockingFrameworkEnabled) return;
- if (layoutFile != null) {
- try {
- control.readXML(layoutFile);
- control.load(layoutName_current);
- } catch (Exception e) {} //skip if layout not found
+ try {
+ control.readXML(layoutFile);
+ control.load(layoutName_current);
+ log.info("Layout loaded from " + layoutFile.getName());
+ } catch (Exception e) {
+ JOptionPane.showMessageDialog(this,
+ "Unable to load layout from " + layoutFile.getName());
+ return;
}
//ensure that all dockables that are externalized according to layout
@@ -224,6 +239,16 @@ public abstract class DockingFrame extends JFrame {
}
/**
+ * Lets user choose a layout in a file chooser popup and then loads/applies it
+ */
+ private void loadLayoutUserDefined() {
+ JFileChooser jfc = new JFileChooser();
+ jfc.setCurrentDirectory(getLayoutDirectory());
+ if (jfc.showOpenDialog(getContentPane()) != JFileChooser.APPROVE_OPTION) return; // cancel pressed
+ loadLayout(jfc.getSelectedFile());
+ }
+
+ /**
* The behavior of the specified CControl is altered by the following:
* If a dockable is detached / externalized, it would normally put directly
* under the ScreenDockStation - thus inhibiting any docking to/from this
@@ -316,4 +341,4 @@ public abstract class DockingFrame extends JFrame {
}
}
-}
+}
\ No newline at end of file
commit b19b2c0926fceec643a42074a657975a12072555
Author: Frederick Weld <fre...@gm...>
Date: Tue Feb 7 17:49:27 2012 +0100
Merged OR panel's menu bar into ORWindow's menu bar (docking layout)
diff --git a/rails/ui/swing/ORPanel.java b/rails/ui/swing/ORPanel.java
index 357d208..ab3bf8f 100644
--- a/rails/ui/swing/ORPanel.java
+++ b/rails/ui/swing/ORPanel.java
@@ -233,7 +233,11 @@ implements ActionListener, KeyListener, RevenueListener {
zoomMenu.add(calibrateMap);
menuBar.add(zoomMenu);
- add(menuBar, BorderLayout.NORTH);
+ // only add menu bar for conventional layout
+ // (otherwise part of DockingFrame)
+ if (!parent.isDockingFrameworkEnabled()) {
+ add(menuBar, BorderLayout.NORTH);
+ }
setVisible(true);
@@ -1353,4 +1357,7 @@ implements ActionListener, KeyListener, RevenueListener {
return buttonPanel;
}
+ public JMenuBar getMenuBar() {
+ return menuBar;
+ }
}
\ No newline at end of file
diff --git a/rails/ui/swing/ORWindow.java b/rails/ui/swing/ORWindow.java
index f9d4d4f..278e9b0 100644
--- a/rails/ui/swing/ORWindow.java
+++ b/rails/ui/swing/ORWindow.java
@@ -90,8 +90,8 @@ public class ORWindow extends DockingFrame implements ActionPerformer {
0, 95, 100, 5);
deployDockables();
- //create the frame menu
- JMenuBar menuBar = new JMenuBar();
+ //take over or panel's menu bar as the frame menu bar
+ JMenuBar menuBar = orPanel.getMenuBar();
addDockingFrameMenu(menuBar);
setJMenuBar( menuBar );
@@ -268,4 +268,4 @@ public class ORWindow extends DockingFrame implements ActionPerformer {
+ gameUIManager.getGameManager().getGameName() ;
}
-}
+}
\ No newline at end of file
commit 477e51b07cf09c0ed71e96af6f2a6c072ad6441c
Author: Frederick Weld <fre...@gm...>
Date: Mon Feb 6 18:24:40 2012 +0100
Refactored docking logic - separated it from ORWin to separate class
Now, ORWindow inherits from this new class (elements.DockingFrame).
As a result, ORWindow does not have any single reference to the
DockingFrame framework - the new class acts both as a facade and
as a rails-aware decorator to the framework's features.
During refactoring, the following was also done:
- Enablement of config option is only tested once (at the beginning)
- due to potential issues when changing during a game
- Enhanced scope of layout menu item "reset"
- now also encompasses resetting the theme
- Menu items "Look and Feel" and "Preferences" are dropped
- they could not be reset properly
- they had side-effects on other windows
diff --git a/LocalisedText.properties b/LocalisedText.properties
index 4f46859..4f344b2 100644
--- a/LocalisedText.properties
+++ b/LocalisedText.properties
@@ -292,15 +292,14 @@ DoesNotExist=Item does not exist
DoesNotForm={0} does not form
DoesNotHaveTheShares=Does not have the shares
Dockable.orWindow.buttonPanel = Commands
-Dockable.orWindow.menu.appearance = Appearance
-Dockable.orWindow.menu.appearance.lookAndFeel = Look and Feel
-Dockable.orWindow.menu.appearance.theme = Theme
-Dockable.orWindow.menu.appearance.preferences = Preferences
-Dockable.orWindow.menu.appearance.resetLayout = Reset Layout
Dockable.orWindow.mapPanel = Map
Dockable.orWindow.messagePanel = Messages
Dockable.orWindow.orPanel = Companies
Dockable.orWindow.upgradePanel = Upgrades
+DockingFrame.menu.layout = Layout
+DockingFrame.menu.layout.applyFrom = Apply From...
+DockingFrame.menu.layout.theme = Theme
+DockingFrame.menu.layout.reset = Reset
Done=Done
DoubleHeadingModifier1825={0} are two {1}-trains running as a {2}-train (double heading).
ShortORExecuted=A short OR has been held, in which only the sold privates have paid out.
diff --git a/rails/ui/swing/GameUIManager.java b/rails/ui/swing/GameUIManager.java
index f281034..1440df6 100644
--- a/rails/ui/swing/GameUIManager.java
+++ b/rails/ui/swing/GameUIManager.java
@@ -126,7 +126,7 @@ public class GameUIManager implements DialogOwner {
public void terminate () {
getWindowSettings ().save();
- if (orWindow != null) orWindow.saveDockableLayout();
+ if (orWindow != null) orWindow.saveLayout();
System.exit(0);
}
diff --git a/rails/ui/swing/ORPanel.java b/rails/ui/swing/ORPanel.java
index 453db01..357d208 100644
--- a/rails/ui/swing/ORPanel.java
+++ b/rails/ui/swing/ORPanel.java
@@ -163,7 +163,7 @@ implements ActionListener, KeyListener, RevenueListener {
add(statusPanel, BorderLayout.CENTER);
//only add button panel directly for conventional layout
- if (!parent.isDockablePanelsEnabled()) {
+ if (!parent.isDockingFrameworkEnabled()) {
add(buttonPanel, BorderLayout.SOUTH);
}
@@ -314,7 +314,7 @@ implements ActionListener, KeyListener, RevenueListener {
redoButton.setEnabled(false);
//choose button panel layout depending on whether panel becomes a dockable
- if (orWindow.isDockablePanelsEnabled()) {
+ if (orWindow.isDockingFrameworkEnabled()) {
//customized panel for dockable layout
//the minimal size is defined by the size of one button
@@ -357,7 +357,7 @@ implements ActionListener, KeyListener, RevenueListener {
//for dockable button panel, ensure that all buttons have the same size
//(necessary, otherwise vertical/box layout will look ugly)
- if (orWindow.isDockablePanelsEnabled()) {
+ if (orWindow.isDockingFrameworkEnabled()) {
//get maximum size
Dimension maxSize = new Dimension();
diff --git a/rails/ui/swing/ORWindow.java b/rails/ui/swing/ORWindow.java
index 057e6a2..f9d4d4f 100644
--- a/rails/ui/swing/ORWindow.java
+++ b/rails/ui/swing/ORWindow.java
@@ -2,61 +2,31 @@
package rails.ui.swing;
import java.awt.BorderLayout;
-import java.awt.MenuItem;
import java.awt.Rectangle;
import java.awt.event.*;
-import java.io.File;
import java.util.ArrayList;
import java.util.List;
-import java.util.Locale;
import javax.swing.JFrame;
-import javax.swing.JMenu;
import javax.swing.JMenuBar;
-import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
-import javax.swing.SwingUtilities;
import org.apache.log4j.Logger;
-import bibliothek.gui.DockController;
-import bibliothek.gui.Dockable;
-import bibliothek.gui.DockStation;
-import bibliothek.gui.dock.ScreenDockStation;
-import bibliothek.gui.dock.SplitDockStation;
-import bibliothek.gui.dock.common.CControl;
-import bibliothek.gui.dock.common.CGrid;
-import bibliothek.gui.dock.common.CStation;
-import bibliothek.gui.dock.common.DefaultSingleCDockable;
-import bibliothek.gui.dock.common.action.predefined.CBlank;
-import bibliothek.gui.dock.common.event.CDockableStateListener;
-import bibliothek.gui.dock.common.intern.CDockable;
-import bibliothek.gui.dock.common.intern.DefaultCDockable;
-import bibliothek.gui.dock.common.intern.ui.CSingleParentRemover;
-import bibliothek.gui.dock.common.menu.CLayoutChoiceMenuPiece;
-import bibliothek.gui.dock.common.menu.CLookAndFeelMenuPiece;
-import bibliothek.gui.dock.common.menu.CPreferenceMenuPiece;
-import bibliothek.gui.dock.common.menu.CThemeMenuPiece;
-import bibliothek.gui.dock.common.mode.ExtendedMode;
-import bibliothek.gui.dock.common.theme.ThemeMap;
-import bibliothek.gui.dock.event.DockStationAdapter;
-import bibliothek.gui.dock.facile.menu.RootMenuPiece;
-import bibliothek.gui.dock.facile.menu.SubmenuPiece;
-import bibliothek.gui.dock.station.LayoutLocked;
-
import rails.common.GuiDef;
import rails.common.LocalText;
import rails.common.parser.Config;
import rails.game.GameManager;
import rails.game.OperatingRound;
import rails.game.action.*;
+import rails.ui.swing.elements.DockingFrame;
/**
* This Window displays the available operations that may be performed during an
* Operating Round. This window also contains the Game Map.
*/
-public class ORWindow extends JFrame implements ActionPerformer {
+public class ORWindow extends DockingFrame implements ActionPerformer {
private static final long serialVersionUID = 1L;
protected GameUIManager gameUIManager;
protected ORUIManager orUIManager;
@@ -72,17 +42,11 @@ public class ORWindow extends JFrame implements ActionPerformer {
List<LayTile> allowedTileLays = new ArrayList<LayTile>();
List<LayToken> allowedTokenLays = new ArrayList<LayToken>();
- CControl orWindowControl = null;
-
- private static final String layoutFolderName = "DockableLayout";
- private static final String layoutFileSuffix = "_layout.rails_ini";
- private static final String initialLayoutName = "InitialDockableLayout";
-
protected static Logger log =
Logger.getLogger(ORWindow.class.getPackage().getName());
public ORWindow(GameUIManager gameUIManager) {
- super();
+ super( "yes".equals(Config.get("or.window.dockablePanels")) );
this.gameUIManager = gameUIManager;
String orUIManagerClassName = gameUIManager.getClassName(GuiDef.ClassName.OR_UI_MANAGER);
@@ -109,93 +73,27 @@ public class ORWindow extends JFrame implements ActionPerformer {
orPanel = new ORPanel(this, orUIManager);
- //create docking / conventional layout depending config
- if (isDockablePanelsEnabled()) {
- //DOCKABLE LAYOUT
-
- //build the docking layout
- orWindowControl = new CControl( this );
- add( orWindowControl.getContentArea() );
- CGrid orWindowLayout = new CGrid( orWindowControl );
-
- //ensure that externalized dockables get a split station as parent
- //necessary, otherwise externalized dockables cannot be docked together
- alwaysAddStationsToExternalizedDockables(orWindowControl);
-
- //set docks tooltip language
- if ("en_us".equalsIgnoreCase(Config.get("locale"))) {
- //hard setting to default in case of US as this is DockingFrames default language
- //don't use Locale constant as it is en_US (case sensitive)
- orWindowControl.setLanguage(new Locale(""));
- }
-
- //add message panel
- String dockableName = LocalText.getText("Dockable.orWindow.messagePanel");
- DefaultSingleCDockable singleDockable = new DefaultSingleCDockable( dockableName, dockableName );
- singleDockable.add( slider, BorderLayout.CENTER );
- singleDockable.setCloseable( false );
- orWindowLayout.add( 0, 0, 100, 10, singleDockable );
+ //create docking / conventional layout
+ if (isDockingFrameworkEnabled()) {
- //add upgrade panel
- dockableName = LocalText.getText("Dockable.orWindow.upgradePanel");
- singleDockable = new DefaultSingleCDockable( dockableName, dockableName );
- singleDockable.add( upgradePanel, BorderLayout.CENTER );
- singleDockable.setCloseable( false );
- orWindowLayout.add( 0, 10, 20, 70, singleDockable );
-
- //add map panel
- dockableName = LocalText.getText("Dockable.orWindow.mapPanel");
- singleDockable = new DefaultSingleCDockable( dockableName, dockableName );
- singleDockable.add( mapPanel, BorderLayout.CENTER );
- singleDockable.setCloseable( false );
- orWindowLayout.add( 20, 10, 80, 70, singleDockable );
-
- //add or panel
- dockableName = LocalText.getText("Dockable.orWindow.orPanel");
- singleDockable = new DefaultSingleCDockable( dockableName, dockableName );
- singleDockable.add( orPanel, BorderLayout.CENTER );
- singleDockable.setCloseable( false );
- orWindowLayout.add( 0, 80, 100, 15, singleDockable );
-
- //add button panel of or panel
- dockableName = LocalText.getText("Dockable.orWindow.buttonPanel");
- singleDockable = new DefaultSingleCDockable( dockableName, dockableName );
- singleDockable.add( orPanel.getButtonPanel(), BorderLayout.CENTER );
- singleDockable.setCloseable( false );
- orWindowLayout.add( 0, 95, 100, 5, singleDockable );
-
- //deploy layout to control's content area
- orWindowControl.getContentArea().deploy( orWindowLayout );
+ //generate layout
+ addDockable ( slider, LocalText.getText("Dockable.orWindow.messagePanel"),
+ 0, 0, 100, 10);
+ addDockable ( upgradePanel, LocalText.getText("Dockable.orWindow.upgradePanel"),
+ 0, 10, 20, 70);
+ addDockable ( mapPanel, LocalText.getText("Dockable.orWindow.mapPanel"),
+ 20, 10, 80, 70);
+ addDockable ( orPanel, LocalText.getText("Dockable.orWindow.orPanel"),
+ 0, 80, 100, 15);
+ addDockable ( orPanel.getButtonPanel(),
+ LocalText.getText("Dockable.orWindow.buttonPanel"),
+ 0, 95, 100, 5);
+ deployDockables();
//create the frame menu
- JMenuBar menubar = new JMenuBar();
- RootMenuPiece appearanceMenu = new RootMenuPiece(
- LocalText.getText("Dockable.orWindow.menu.appearance"),
- false);
- appearanceMenu.add( new SubmenuPiece(
- LocalText.getText("Dockable.orWindow.menu.appearance.lookAndFeel"),
- false,
- new CLookAndFeelMenuPiece( orWindowControl )
- ));
- appearanceMenu.add( new SubmenuPiece(
- LocalText.getText("Dockable.orWindow.menu.appearance.theme"),
- false,
- new CThemeMenuPiece( orWindowControl )
- ));
- appearanceMenu.add( CPreferenceMenuPiece.setup( orWindowControl ));
- appearanceMenu.getMenu().addSeparator();
- JMenuItem resetLayoutMenuItem = new JMenuItem (
- LocalText.getText("Dockable.orWindow.menu.appearance.resetLayout"));
- resetLayoutMenuItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- orWindowControl.load(initialLayoutName);
- }
- });
- appearanceMenu.getMenu().add(resetLayoutMenuItem);
-
- //deploy menu
- menubar.add( appearanceMenu.getMenu() );
- setJMenuBar( menubar );
+ JMenuBar menuBar = new JMenuBar();
+ addDockingFrameMenu(menuBar);
+ setJMenuBar( menuBar );
} else {
// CONVENTIONAL LAYOUT
@@ -230,9 +128,9 @@ public class ORWindow extends JFrame implements ActionPerformer {
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
- saveDockableLayout();
+ saveLayout();
StatusWindow.uncheckMenuItemBox(StatusWindow.MAP_CMD);
- if (!isDockablePanelsEnabled()) {
+ if (!isDockingFrameworkEnabled()) {
frame.dispose();
} else {
setVisible(false);
@@ -251,7 +149,7 @@ public class ORWindow extends JFrame implements ActionPerformer {
});
//rearrange layout only if no docking framework active
- if (!isDockablePanelsEnabled()) {
+ if (!isDockingFrameworkEnabled()) {
pack();
}
@@ -263,11 +161,7 @@ public class ORWindow extends JFrame implements ActionPerformer {
gameUIManager.reportWindow.updateLog();
- //dockable panes: save initial layout and restore former layout
- if (isDockablePanelsEnabled()) {
- orWindowControl.save(initialLayoutName);
- loadDockableLayout();
- }
+ if (isDockingFrameworkEnabled()) initLayout();
}
public ORUIManager getORUIManager() {
@@ -319,7 +213,7 @@ public class ORWindow extends JFrame implements ActionPerformer {
public void repaintORPanel() {
//rearrange layout only if no docking framework active
- if (!isDockablePanelsEnabled()) {
+ if (!isDockingFrameworkEnabled()) {
orPanel.revalidate();
}
}
@@ -335,7 +229,7 @@ public class ORWindow extends JFrame implements ActionPerformer {
numORs ));
//rearrange layout only if no docking framework active
- if (!isDockablePanelsEnabled()) {
+ if (!isDockingFrameworkEnabled()) {
pack();
if (lastBounds != null) {
Rectangle newBounds = getBounds();
@@ -368,160 +262,10 @@ public class ORWindow extends JFrame implements ActionPerformer {
messagePanel.setMessage("");
setTitle(LocalText.getText("MapWindowTitle"));
}
-
- public boolean isDockablePanelsEnabled() {
- return "yes".equals(Config.get("or.window.dockablePanels"));
- }
-
-
- private String getLayoutName() {
+
+ protected String getLayoutFileName() {
return getClass().getSimpleName() + "_"
+ gameUIManager.getGameManager().getGameName() ;
}
-
- private File getLayoutFile() {
- try {
- //get layout folder (and ensure that it is available)
- File layoutFolder = new File(Config.get("save.directory"),layoutFolderName);
- if (!layoutFolder.isDirectory()) {
- layoutFolder.mkdirs();
- }
- File layoutFile = new File(layoutFolder,
- getLayoutName() + layoutFileSuffix );
- return layoutFile;
- } catch (Exception e) {
- //return no valid file if anything goes wrong
- return null;
- }
- }
-
- public void saveDockableLayout() {
- if (!isDockablePanelsEnabled()) return;
-
- File layoutFile = getLayoutFile();
- if (layoutFile != null) {
- try {
- orWindowControl.save(getLayoutName());
- orWindowControl.writeXML(layoutFile);
- } catch (Exception e) {} //skip in case of issue
- }
- }
-
- private void loadDockableLayout() {
- if (!isDockablePanelsEnabled()) return;
-
- File layoutFile = getLayoutFile();
- if (layoutFile != null) {
- try {
- orWindowControl.readXML(layoutFile);
- orWindowControl.load(getLayoutName());
- } catch (Exception e) {} //skip if layout not found
- }
-
- //ensure that all dockables that are externalized according to layout
- //information don't have the deault maximize button (as it won't work
- //for the adjusted externalization setup)
- for (int i = 0 ; i < orWindowControl.getCDockableCount() ; i++ ) {
- CDockable d = orWindowControl.getCDockable(i);
- if (d instanceof DefaultCDockable) {
- DefaultCDockable dd = (DefaultCDockable)d;
- if (ExtendedMode.EXTERNALIZED.equals(d.getExtendedMode())) {
- dd.putAction( CDockable.ACTION_KEY_MAXIMIZE, CBlank.BLANK );
- }
- }
- }
- }
-
- /**
- * The behavior of the specified CControl is altered by the following:
- * If a dockable is detached / externalized, it would normally put directly
- * under the ScreenDockStation - thus inhibiting any docking to/from this
- * dockable. This is changed such that a split station (that would allow for
- * that) is put in between the ScreenDockStation and the Dockable.
- */
- private void alwaysAddStationsToExternalizedDockables(CControl cc) {
- // access the DockStation which shows our detached (externalized) items
- CStation<?> screen = (CStation<?>)
- cc.getStation( CControl.EXTERNALIZED_STATION_ID );
-
- // remove the standard maximize action when externalizing
- // and adds it back when unexternalizing
- // (as maximize won't work for the adjusted externalization setup)
- cc.addStateListener( new CDockableStateListener() {
- public void visibilityChanged( CDockable cd ){
- // ignore
- }
-
- public void extendedModeChanged( CDockable cd, ExtendedMode mode ){
- if( cd instanceof DefaultCDockable ) {
- DefaultCDockable dockable = (DefaultCDockable) cd;
- if( mode.equals( ExtendedMode.EXTERNALIZED ) ) {
- dockable.putAction( CDockable.ACTION_KEY_MAXIMIZE, CBlank.BLANK );
- }
- else {
- dockable.putAction( CDockable.ACTION_KEY_MAXIMIZE, null );
- }
- }
- }
- });
-
- // if a Dockable is added to that station...
- screen.getStation().addDockStationListener( new ScreenDockStationListener());
-
- // make sure a SplitDockStation with one child and a parent
- // that is a ScreenDockStation does not get removed
- cc.intern().getController().setSingleParentRemover(
- new CSingleParentRemover( cc ){
- @Override
- protected boolean shouldTest( DockStation station ){
- if( station instanceof SplitDockStation ) {
- SplitDockStation split = (SplitDockStation) station;
- if( split.getDockParent() instanceof ScreenDockStation ) {
- // but we want to remove the station if it does
- // not have any children at all
- return split.getDockableCount() == 0;
- }
- }
- return super.shouldTest( station );
- }
- } );
- }
-
- @LayoutLocked(locked = false)
- private class ScreenDockStationListener extends DockStationAdapter {
- public void dockableAdded( DockStation station, final Dockable dockable ){
- // ... and the new child is not a SplitDockStation ...
- if( !(dockable instanceof SplitDockStation) ) {
- SwingUtilities.invokeLater( new Runnable(){
- public void run(){
- checkAndReplace( dockable );
- }
- } );
- }
- }
- private void checkAndReplace( Dockable dockable ){
- DockStation station = dockable.getDockParent();
- if( !(station instanceof ScreenDockStation) ) {
- // cancel
- return;
- }
-
- // .. then we just insert a SplitDockStation
- SplitDockStation split = new SplitDockStation();
- DockController controller = station.getController();
-
- try {
- // disable events while rearranging our layout
- controller.freezeLayout();
-
- station.replace( dockable, split );
- split.drop( dockable );
- }
- finally {
- // and enable events after we finished
- controller.meltLayout();
- }
- }
- }
}
diff --git a/rails/ui/swing/UpgradesPanel.java b/rails/ui/swing/UpgradesPanel.java
index 02556b6..edf24a2 100644
--- a/rails/ui/swing/UpgradesPanel.java
+++ b/rails/ui/swing/UpgradesPanel.java
@@ -409,7 +409,7 @@ public class UpgradesPanel extends Box implements MouseListener, ActionListener
* could be necessary when displaying tiles of an arbitrary size
*/
private int getZoomStep() {
- if (orUIManager.getORWindow().isDockablePanelsEnabled()) {
+ if (orUIManager.getORWindow().isDockingFrameworkEnabled()) {
return hexMap.getZoomStep();
} else {
return UPGRADE_TILE_ZOOM_STEP;
diff --git a/rails/ui/swing/elements/DockingFrame.java b/rails/ui/swing/elements/DockingFrame.java
new file mode 100644
index 0000000..52375d0
--- /dev/null
+++ b/rails/ui/swing/elements/DockingFrame.java
@@ -0,0 +1,319 @@
+/**
+ *
+ */
+package rails.ui.swing.elements;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.util.Locale;
+
+import javax.swing.JComponent;
+import javax.swing.JFrame;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.SwingUtilities;
+
+import rails.common.LocalText;
+import rails.common.parser.Config;
+
+import bibliothek.gui.DockController;
+import bibliothek.gui.DockStation;
+import bibliothek.gui.Dockable;
+import bibliothek.gui.dock.ScreenDockStation;
+import bibliothek.gui.dock.SplitDockStation;
+import bibliothek.gui.dock.common.CControl;
+import bibliothek.gui.dock.common.CGrid;
+import bibliothek.gui.dock.common.CStation;
+import bibliothek.gui.dock.common.DefaultSingleCDockable;
+import bibliothek.gui.dock.common.action.predefined.CBlank;
+import bibliothek.gui.dock.common.event.CDockableStateListener;
+import bibliothek.gui.dock.common.intern.CDockable;
+import bibliothek.gui.dock.common.intern.DefaultCDockable;
+import bibliothek.gui.dock.common.intern.ui.CSingleParentRemover;
+import bibliothek.gui.dock.common.menu.CThemeMenuPiece;
+import bibliothek.gui.dock.common.mode.ExtendedMode;
+import bibliothek.gui.dock.common.theme.ThemeMap;
+import bibliothek.gui.dock.event.DockStationAdapter;
+import bibliothek.gui.dock.facile.menu.RootMenuPiece;
+import bibliothek.gui.dock.facile.menu.SubmenuPiece;
+import bibliothek.gui.dock.station.LayoutLocked;
+
+/**
+ * Superclass for all application frames that want to use the docking
+ * framework for managing its panels.
+ *
+ * All references to the docking framework are private by purpose. This
+ * enforces that any sub-class must not deal with any framework related
+ * issues (this superclass acts as a facade to the framework).
+ *
+ * @author Frederick Weld
+ *
+ */
+public abstract class DockingFrame extends JFrame {
+ private static final long serialVersionUID = 1L;
+ private static final String layoutFolderName = "DockableLayout";
+ private static final String layoutFileSuffix = "_layout.rails_ini";
+ private static final String layoutName_initial = "InitialLayout";
+ private static final String layoutName_current = "CurrentLayout";
+ private static final String defaultTheme = ThemeMap.KEY_BASIC_THEME;
+
+ private boolean isDockingFrameworkEnabled;
+ private CControl control = null;
+ private CGrid gridLayout = null;
+
+ /**
+ * Decision whether docking framework should be activated for a frame
+ * has to be done at the beginning as later switching is not supported
+ */
+ protected DockingFrame(boolean isDockingFrameworkEnabled) {
+ this.isDockingFrameworkEnabled = isDockingFrameworkEnabled;
+ if (!isDockingFrameworkEnabled) return;
+
+ //init the ccontrol
+ control = new CControl( this );
+ control.setTheme(defaultTheme);
+ add( control.getContentArea() );
+ if ("en_us".equalsIgnoreCase(Config.get("locale"))) {
+ //hard setting to default in case of US as this is DockingFrames default language
+ //don't use Locale constant as it is en_US (case sensitive)
+ control.setLanguage(new Locale(""));
+ }
+
+ //init the grid layout
+ gridLayout = new CGrid( control );
+
+ //ensure that externalized dockables get a split station as parent
+ //necessary, otherwise externalized dockables cannot be docked together
+ alwaysAddStationsToExternalizedDockables(control);
+
+
+ }
+
+ public boolean isDockingFrameworkEnabled() {
+ return isDockingFrameworkEnabled;
+ }
+
+ /**
+ * Registers a component that is to become a dockable.
+ * The dockable is only deployed to the frame if deployDockables is called.
+ */
+ protected void addDockable(JComponent c, String dockableTitle, int x, int y, int width, int height) {
+ DefaultSingleCDockable d = new DefaultSingleCDockable(
+ dockableTitle, dockableTitle );
+ d.add( c, BorderLayout.CENTER );
+ d.setCloseable( false );
+ gridLayout.add( x, y, width, height, d );
+ }
+
+ /**
+ * Deploys to the frame all dockables that have been added before
+ */
+ protected void deployDockables() {
+ control.getContentArea().deploy( gridLayout );
+ }
+
+ /**
+ * Creates a generic layout menu and adds it to the specified menu bar
+ */
+ protected void addDockingFrameMenu(JMenuBar menuBar) {
+ RootMenuPiece layoutMenu = new RootMenuPiece(
+ LocalText.getText("DockingFrame.menu.layout"),
+ false);
+ layoutMenu.add( new SubmenuPiece(
+ LocalText.getText("DockingFrame.menu.layout.theme"),
+ false,
+ new CThemeMenuPiece( control )
+ ));
+ layoutMenu.getMenu().addSeparator();
+ JMenuItem resetMenuItem = new JMenuItem (
+ LocalText.getText("DockingFrame.menu.layout.reset"));
+ resetMenuItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ control.load(layoutName_initial);
+ control.setTheme(defaultTheme);
+ }
+ });
+ layoutMenu.getMenu().add(resetMenuItem);
+ JMenuItem applyFromMenuItem = new JMenuItem (
+ LocalText.getText("DockingFrame.menu.layout.applyFrom"));
+ applyFromMenuItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ //TODO: apply from
+ }
+ });
+ layoutMenu.getMenu().add(applyFromMenuItem);
+
+ //deploy menu
+ menuBar.add( layoutMenu.getMenu() );
+ }
+
+ /**
+ * May only be called once the docking frame's layout has been constructed.
+ * Remembers that layout as the initial one.
+ * Loads a former layout if that was persisted in a prior session.
+ */
+ protected void initLayout() {
+ control.save(layoutName_initial);
+ loadLayout();
+ }
+
+ /**
+ * @return The file name which is to be used for storing the layout upon exit
+ * and restoring prior layout when entering a session.
+ */
+ abstract protected String getLayoutFileName();
+
+ private File getLayoutFile() {
+ try {
+ //get layout folder (and ensure that it is available)
+ File layoutFolder = new File(Config.get("save.directory"),layoutFolderName);
+ if (!layoutFolder.isDirectory()) {
+ layoutFolder.mkdirs();
+ }
+ File layoutFile = new File(layoutFolder,
+ getLayoutFileName() + layoutFileSuffix );
+ return layoutFile;
+ } catch (Exception e) {
+ //return no valid file if anything goes wrong
+ return null;
+ }
+ }
+
+ public void saveLayout() {
+ if (!isDockingFrameworkEnabled) return;
+
+ File layoutFile = getLayoutFile();
+ if (layoutFile != null) {
+ try {
+ control.save(layoutName_current);
+ control.writeXML(layoutFile);
+ } catch (Exception e) {} //skip in case of issue
+ }
+ }
+
+ private void loadLayout() {
+ loadLayout(getLayoutFile());
+ }
+
+ private void loadLayout(File layoutFile) {
+ if (!isDockingFrameworkEnabled) return;
+
+ if (layoutFile != null) {
+ try {
+ control.readXML(layoutFile);
+ control.load(layoutName_current);
+ } catch (Exception e) {} //skip if layout not found
+ }
+
+ //ensure that all dockables that are externalized according to layout
+ //information don't have the default maximize button (as it won't work
+ //for the adjusted externalization setup)
+ for (int i = 0 ; i < control.getCDockableCount() ; i++ ) {
+ CDockable d = control.getCDockable(i);
+ if (d instanceof DefaultCDockable) {
+ DefaultCDockable dd = (DefaultCDockable)d;
+ if (ExtendedMode.EXTERNALIZED.equals(d.getExtendedMode())) {
+ dd.putAction( CDockable.ACTION_KEY_MAXIMIZE, CBlank.BLANK );
+ } else {
+ dd.putAction( CDockable.ACTION_KEY_MAXIMIZE, null );
+ }
+ }
+ }
+ }
+
+ /**
+ * The behavior of the specified CControl is altered by the following:
+ * If a dockable is detached / externalized, it would normally put directly
+ * under the ScreenDockStation - thus inhibiting any docking to/from this
+ * dockable. This is changed such that a split station (that would allow for
+ * that) is put in between the ScreenDockStation and the Dockable.
+ */
+ private void alwaysAddStationsToExternalizedDockables(CControl cc) {
+
+ // access the DockStation which shows our detached (externalized) items
+ CStation<?> screen = (CStation<?>)
+ cc.getStation( CControl.EXTERNALIZED_STATION_ID );
+
+ // remove the standard maximize action when externalizing
+ // and adds it back when unexternalizing
+ // (as maximize won't work for the adjusted externalization setup)
+ cc.addStateListener( new CDockableStateListener() {
+ public void visibilityChanged( CDockable cd ){
+ // ignore
+ }
+
+ public void extendedModeChanged( CDockable cd, ExtendedMode mode ){
+ if( cd instanceof DefaultCDockable ) {
+ DefaultCDockable dockable = (DefaultCDockable) cd;
+ if( mode.equals( ExtendedMode.EXTERNALIZED ) ) {
+ dockable.putAction( CDockable.ACTION_KEY_MAXIMIZE, CBlank.BLANK );
+ }
+ else {
+ dockable.putAction( CDockable.ACTION_KEY_MAXIMIZE, null );
+ }
+ }
+ }
+ });
+
+ // if a Dockable is added to that station...
+ screen.getStation().addDockStationListener( new ScreenDockStationListener());
+
+ // make sure a SplitDockStation with one child and a parent
+ // that is a ScreenDockStation does not get removed
+ cc.intern().getController().setSingleParentRemover(
+ new CSingleParentRemover( cc ){
+ @Override
+ protected boolean shouldTest( DockStation station ){
+ if( station instanceof SplitDockStation ) {
+ SplitDockStation split = (SplitDockStation) station;
+ if( split.getDockParent() instanceof ScreenDockStation ) {
+ // but we want to remove the station if it does
+ // not have any children at all
+ return split.getDockableCount() == 0;
+ }
+ }
+ return super.shouldTest( station );
+ }
+ } );
+ }
+
+ @LayoutLocked(locked = false)
+ private class ScreenDockStationListener extends DockStationAdapter {
+ public void dockableAdded( DockStation station, final Dockable dockable ){
+ // ... and the new child is not a SplitDockStation ...
+ if( !(dockable instanceof SplitDockStation) ) {
+ SwingUtilities.invokeLater( new Runnable(){
+ public void run(){
+ checkAndReplace( dockable );
+ }
+ } );
+ }
+ }
+ private void checkAndReplace( Dockable dockable ){
+ DockStation station = dockable.getDockParent();
+ if( !(station instanceof ScreenDockStation) ) {
+ // cancel
+ return;
+ }
+
+ // .. then we just insert a SplitDockStation
+ SplitDockStation split = new SplitDockStation();
+ DockController controller = station.getController();
+
+ try {
+ // disable events while rearranging our layout
+ controller.freezeLayout();
+
+ station.replace( dockable, split );
+ split.drop( dockable );
+ }
+ finally {
+ // and enable events after we finished
+ controller.meltLayout();
+ }
+ }
+ }
+
+}
commit 862f6ee2affe8b2400bb615dca8854bb8f835534
Author: Frederick Weld <fre...@gm...>
Date: Sun Feb 5 19:34:30 2012 +0100
Added OR Window menu (for dockables) incl. reset layout
Apart from reset layout (restores standard rails layout of the OR
window), further appearance options of DockingFrames are exposed.
diff --git a/LocalisedText.properties b/LocalisedText.properties
index 6aaa145..4f46859 100644
--- a/LocalisedText.properties
+++ b/LocalisedText.properties
@@ -291,11 +291,16 @@ DiscardsBaseToken={0} discards a {1} base token on {2}
DoesNotExist=Item does not exist
DoesNotForm={0} does not form
DoesNotHaveTheShares=Does not have the shares
-DockableTitle.orWindow.messagePanel = Messages
-DockableTitle.orWindow.upgradePanel = Upgrades
-DockableTitle.orWindow.mapPanel = Map
-DockableTitle.orWindow.orPanel = Companies
-DockableTitle.orWindow.buttonPanel = Commands
+Dockable.orWindow.buttonPanel = Commands
+Dockable.orWindow.menu.appearance = Appearance
+Dockable.orWindow.menu.appearance.lookAndFeel = Look and Feel
+Dockable.orWindow.menu.appearance.theme = Theme
+Dockable.orWindow.menu.appearance.preferences = Preferences
+Dockable.orWindow.menu.appearance.resetLayout = Reset Layout
+Dockable.orWindow.mapPanel = Map
+Dockable.orWindow.messagePanel = Messages
+Dockable.orWindow.orPanel = Companies
+Dockable.orWindow.upgradePanel = Upgrades
Done=Done
DoubleHeadingModifier1825={0} are two {1}-trains running as a {2}-train (double heading).
ShortORExecuted=A short OR has been held, in which only the sold privates have paid out.
diff --git a/rails/ui/swing/ORWindow.java b/rails/ui/swing/ORWindow.java
index 441be07..057e6a2 100644
--- a/rails/ui/swing/ORWindow.java
+++ b/rails/ui/swing/ORWindow.java
@@ -2,6 +2,7 @@
package rails.ui.swing;
import java.awt.BorderLayout;
+import java.awt.MenuItem;
import java.awt.Rectangle;
import java.awt.event.*;
import java.io.File;
@@ -10,6 +11,9 @@ import java.util.List;
import java.util.Locale;
import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
@@ -30,9 +34,15 @@ import bibliothek.gui.dock.common.event.CDockableStateListener;
import bibliothek.gui.dock.common.intern.CDockable;
import bibliothek.gui.dock.common.intern.DefaultCDockable;
import bibliothek.gui.dock.common.intern.ui.CSingleParentRemover;
+import bibliothek.gui.dock.common.menu.CLayoutChoiceMenuPiece;
+import bibliothek.gui.dock.common.menu.CLookAndFeelMenuPiece;
+import bibliothek.gui.dock.common.menu.CPreferenceMenuPiece;
+import bibliothek.gui.dock.common.menu.CThemeMenuPiece;
import bibliothek.gui.dock.common.mode.ExtendedMode;
import bibliothek.gui.dock.common.theme.ThemeMap;
import bibliothek.gui.dock.event.DockStationAdapter;
+import bibliothek.gui.dock.facile.menu.RootMenuPiece;
+import bibliothek.gui.dock.facile.menu.SubmenuPiece;
import bibliothek.gui.dock.station.LayoutLocked;
import rails.common.GuiDef;
@@ -66,6 +76,7 @@ public class ORWindow extends JFrame implements ActionPerformer {
private static final String layoutFolderName = "DockableLayout";
private static final String layoutFileSuffix = "_layout.rails_ini";
+ private static final String initialLayoutName = "InitialDockableLayout";
protected static Logger log =
Logger.getLogger(ORWindow.class.getPackage().getName());
@@ -104,7 +115,6 @@ public class ORWindow extends JFrame implements ActionPerformer {
//build the docking layout
orWindowControl = new CControl( this );
- orWindowControl.setTheme( ThemeMap.KEY_SMOOTH_THEME );
add( orWindowControl.getContentArea() );
CGrid orWindowLayout = new CGrid( orWindowControl );
@@ -120,42 +130,73 @@ public class ORWindow extends JFrame implements ActionPerformer {
}
//add message panel
- String dockableName = LocalText.getText("DockableTitle.orWindow.messagePanel");
+ String dockableName = LocalText.getText("Dockable.orWindow.messagePanel");
DefaultSingleCDockable singleDockable = new DefaultSingleCDockable( dockableName, dockableName );
singleDockable.add( slider, BorderLayout.CENTER );
singleDockable.setCloseable( false );
orWindowLayout.add( 0, 0, 100, 10, singleDockable );
//add upgrade panel
- dockableName = LocalText.getText("DockableTitle.orWindow.upgradePanel");
+ dockableName = LocalText.getText("Dockable.orWindow.upgradePanel");
singleDockable = new DefaultSingleCDockable( dockableName, dockableName );
singleDockable.add( upgradePanel, BorderLayout.CENTER );
singleDockable.setCloseable( false );
orWindowLayout.add( 0, 10, 20, 70, singleDockable );
//add map panel
- dockableName = LocalText.getText("DockableTitle.orWindow.mapPanel");
+ dockableName = LocalText.getText("Dockable.orWindow.mapPanel");
singleDockable = new DefaultSingleCDockable( dockableName, dockableName );
singleDockable.add( mapPanel, BorderLayout.CENTER );
singleDockable.setCloseable( false );
orWindowLayout.add( 20, 10, 80, 70, singleDockable );
//add or panel
- dockableName = LocalText.getText("DockableTitle.orWindow.orPanel");
+ dockableName = LocalText.getText("Dockable.orWindow.orPanel");
singleDockable = new DefaultSingleCDockable( dockableName, dockableName );
singleDockable.add( orPanel, BorderLayout.CENTER );
singleDockable.setCloseable( false );
orWindowLayout.add( 0, 80, 100, 15, singleDockable );
//add button panel of or panel
- dockableName = LocalText.getText("DockableTitle.orWindow.buttonPanel");
+ dockableName = LocalText.getText("Dockable.orWindow.buttonPanel");
singleDockable = new DefaultSingleCDockable( dockableName, dockableName );
singleDockable.add( orPanel.getButtonPanel(), BorderLayout.CENTER );
singleDockable.setCloseable( false );
orWindowLayout.add( 0, 95, 100, 5, singleDockable );
+ //deploy layout to control's content area
orWindowControl.getContentArea().deploy( orWindowLayout );
+ //create the frame menu
+ JMenuBar menubar = new JMenuBar();
+ RootMenuPiece appearanceMenu = new RootMenuPiece(
+ LocalText.getText("Dockable.orWindow.menu.appearance"),
+ false);
+ appearanceMenu.add( new SubmenuPiece(
+ LocalText.getText("Dockable.orWindow.menu.appearance.lookAndFeel"),
+ false,
+ new CLookAndFeelMenuPiece( orWindowControl )
+ ));
+ appearanceMenu.add( new SubmenuPiece(
+ LocalText.getText("Dockable.orWindow.menu.appearance.theme"),
+ false,
+ new CThemeMenuPiece( orWindowControl )
+ ));
+ appearanceMenu.add( CPreferenceMenuPiece.setup( orWindowControl ));
+ appearanceMenu.getMenu().addSeparator();
+ JMenuItem resetLayoutMenuItem = new JMenuItem (
+ LocalText.getText("Dockable.orWindow.menu.appearance.resetLayout"));
+ resetLayoutMenuItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ orWindowControl.load(initialLayoutName);
+ }
+ });
+ appearanceMenu.getMenu().add(resetLayoutMenuItem);
+
+ //deploy menu
+ menubar.add( appearanceMenu.getMenu() );
+ setJMenuBar( menubar );
+
} else {
// CONVENTIONAL LAYOUT
@@ -222,8 +263,11 @@ public class ORWindow extends JFrame implements ActionPerformer {
gameUIManager.reportWindow.updateLog();
- //dockable panes: restore former layout (depending on game variant)
- loadDockableLayout();
+ //dockable panes: save initial layout and restore former layout
+ if (isDockablePanelsEnabled()) {
+ orWindowControl.save(initialLayoutName);
+ loadDockableLayout();
+ }
}
public ORUIManager getORUIManager() {
|
|
From: Frederick W. <fre...@us...> - 2012-02-08 16:50:21
|
rails/ui/swing/GridPanel.java | 28 +++++++++++++++++-----------
1 file changed, 17 insertions(+), 11 deletions(-)
New commits:
commit 5f70d21472cf24abf7ac417896273245f39074e8
Author: Frederick Weld <fre...@gm...>
Date: Wed Feb 8 17:49:20 2012 +0100
Increased robustness for GridPanel(2): Added field may have null-border
diff --git a/rails/ui/swing/GridPanel.java b/rails/ui/swing/GridPanel.java
index d2ea42b..ddc4582 100644
--- a/rails/ui/swing/GridPanel.java
+++ b/rails/ui/swing/GridPanel.java
@@ -244,24 +244,30 @@ implements ActionListener, KeyListener {
private class FieldBorder extends CompoundBorder {
private static final long serialVersionUID = 1L;
Border nativeInnerBorder;
- DynamicBorder highlightedInnerBorder;
+ /**
+ * remains null if nativeInnerBorder is null or broken
+ */
+ DynamicBorder highlightedInnerBorder = null;
DynamicBorder outlineBorder;
DynamicBorder outerBorder;
public FieldBorder(Border innerBorder,DynamicBorder outlineBorder,DynamicBorder outerBorder) {
super(new CompoundBorder(outerBorder,outlineBorder),innerBorder);
- this.nativeInnerBorder = innerBorder;
+ nativeInnerBorder = innerBorder;
this.outlineBorder = outlineBorder;
this.outerBorder = outerBorder;
- Insets nativeInnerBorderInsets = nativeInnerBorder.getBorderInsets(null);
- if (nativeInnerBorderInsets == null) {
- nativeInnerBorderInsets = new Insets(0,0,0,0);
+
+ //prepare highlighted inner border
+ if (nativeInnerBorder != null) {
+ Insets nativeInnerBorderInsets = nativeInnerBorder.getBorderInsets(null);
+ if (nativeInnerBorderInsets != null) {
+ highlightedInnerBorder = new DynamicBorder(
+ highlightedBorderColor,
+ nativeInnerBorderInsets.top,
+ nativeInnerBorderInsets.left,
+ nativeInnerBorderInsets.bottom,
+ nativeInnerBorderInsets.right);
+ }
}
- this.highlightedInnerBorder = new DynamicBorder(
- highlightedBorderColor,
- nativeInnerBorderInsets.top,
- nativeInnerBorderInsets.left,
- nativeInnerBorderInsets.bottom,
- nativeInnerBorderInsets.right);
}
public void setHighlight(boolean isToBeHighlighted) {
outlineBorder.setHighlight(isToBeHighlighted);
|
|
From: Erik V. <ev...@us...> - 2012-02-07 22:02:17
|
rails/game/StartRound.java | 24 +++++++++++-------------
1 file changed, 11 insertions(+), 13 deletions(-)
New commits:
commit c60ac2a448bd5b3d727673a23fa879da839c4d54
Author: Erik Vos <eri...@xs...>
Date: Tue Feb 7 23:01:08 2012 +0100
Fix for 1835 bug: BY presidency not transferred during start round.
Presidency check was missing and has now been added in the start round.
diff --git a/rails/game/StartRound.java b/rails/game/StartRound.java
index c9ab5b6..73008d1 100644
--- a/rails/game/StartRound.java
+++ b/rails/game/StartRound.java
@@ -3,9 +3,7 @@ package rails.game;
import java.util.ArrayList;
import java.util.List;
-import rails.common.DisplayBuffer;
-import rails.common.GuiDef;
-import rails.common.LocalText;
+import rails.common.*;
import rails.common.parser.GameOption;
import rails.game.action.*;
import rails.game.model.ModelObject;
@@ -18,7 +16,7 @@ public abstract class StartRound extends Round {
protected int[] itemIndex;
protected List<StartItem> itemsToSell = null;
protected State auctionItemState =
- new State("AuctionItem", StartItem.class);
+ new State("AuctionItem", StartItem.class);
protected IntegerState numPasses = new IntegerState("StartRoundPasses");
protected int numPlayers;
protected String variant;
@@ -120,7 +118,7 @@ public abstract class StartRound extends Round {
BuyStartItem buyAction = (BuyStartItem) startItemAction;
if (buyAction.hasSharePriceToSet()
- && buyAction.getAssociatedSharePrice() == 0) {
+ && buyAction.getAssociatedSharePrice() == 0) {
// We still need a share price for this item
startItemAction.getStartItem().setStatus(
StartItem.NEEDS_SHARE_PRICE);
@@ -138,7 +136,7 @@ public abstract class StartRound extends Round {
DisplayBuffer.add(LocalText.getText("UnexpectedAction",
action.toString()));
}
-
+
startPacketChecks();
if (startPacket.areAllSold()) {
@@ -210,14 +208,14 @@ public abstract class StartRound extends Round {
sharePrice = boughtItem.getAssociatedSharePrice();
if (sharePrice == 0) {
errMsg =
- LocalText.getText("NoSharePriceSet", shareCompName);
+ LocalText.getText("NoSharePriceSet", shareCompName);
break;
}
if ((stockMarket.getStartSpace(sharePrice)) == null) {
errMsg =
- LocalText.getText("InvalidStartPrice",
- Bank.format(sharePrice),
- shareCompName );
+ LocalText.getText("InvalidStartPrice",
+ Bank.format(sharePrice),
+ shareCompName );
break;
}
}
@@ -302,7 +300,7 @@ public abstract class StartRound extends Round {
if (comp.hasStarted() && !comp.hasFloated()) {
checkFlotation(comp);
}
-
+ if (comp.hasStarted()) comp.checkPresidency(); // Needed for 1835 BY
}
}
@@ -318,9 +316,9 @@ public abstract class StartRound extends Round {
super.finishRound();
}
- /*----- Setting up the UI for the next action -----*/
+ /*----- Setting up the UI for the next action -----*/
- /**
+ /**
* Get the currentPlayer index in the player list (starting at 0).
*
* @return The index of the current Player.
|
|
From: Stefan F. <ste...@us...> - 2012-02-07 18:05:12
|
rails/game/state/ArrayListMultimapState.java | 4
rails/game/state/Context.java | 2
rails/game/state/CountableItem.java | 11 ++
rails/game/state/HashMultimapState.java | 2
rails/game/state/ItemType.java | 5 +
rails/game/state/MultimapState.java | 2
rails/game/state/OwnableItem.java | 16 +++
rails/game/state/PortfolioChange.java | 44 ++++++++++
rails/game/state/PortfolioManager.java | 38 ++++++++
rails/game/state/PortfolioNG.java | 117 +++++++++++++++++++++++++++
rails/game/state/StateManager.java | 61 +++++++++++---
rails/game/state/Wallet.java | 111 +++++++++++++++++++++++++
rails/game/state/WalletChange.java | 50 +++++++++++
rails/game/state/WalletManager.java | 38 ++++++++
14 files changed, 485 insertions(+), 16 deletions(-)
New commits:
commit 6d9cd8a9cc6a0e0f1f638d7b518fd75d9b363f7f
Author: Stefan Frey <ste...@we...>
Date: Mon Feb 6 20:27:46 2012 +0100
Creation of next generation portfolio mechanism based on a portfolio class that extends State class
Creation of a wallet class that allows countable items
diff --git a/rails/game/state/ArrayListMultimapState.java b/rails/game/state/ArrayListMultimapState.java
index 406a90e..d23a0eb 100644
--- a/rails/game/state/ArrayListMultimapState.java
+++ b/rails/game/state/ArrayListMultimapState.java
@@ -42,7 +42,7 @@ public class ArrayListMultimapState<K,V> extends MultimapState<K,V> {
*/
public boolean put(K key, V value) {
- new MultimapChange<K,V>(this, key, value, true );
+ new MultimapChange<K,V>(this, key, value, true);
return true;
}
@@ -65,7 +65,7 @@ public class ArrayListMultimapState<K,V> extends MultimapState<K,V> {
return map.toString();
}
- public void change(K key, V value, boolean addToMap) {
+ void change(K key, V value, boolean addToMap) {
if (addToMap) {
map.put(key, value);
} else {
diff --git a/rails/game/state/Context.java b/rails/game/state/Context.java
index 65b69ba..2036777 100644
--- a/rails/game/state/Context.java
+++ b/rails/game/state/Context.java
@@ -68,7 +68,7 @@ public class Context extends GameItem {
private Context initRoot() {
super.init(this); // sets parent identical to ROOT
- stateManager = new StateManager(this);
+ stateManager = StateManager.create();
return this;
}
diff --git a/rails/game/state/CountableItem.java b/rails/game/state/CountableItem.java
new file mode 100644
index 0000000..122b22c
--- /dev/null
+++ b/rails/game/state/CountableItem.java
@@ -0,0 +1,11 @@
+package rails.game.state;
+
+/**
+ * Identifies items which are countable
+ * They are stored inside wallets
+ * @author freystef
+ */
+
+public interface CountableItem extends Item {
+
+}
diff --git a/rails/game/state/HashMultimapState.java b/rails/game/state/HashMultimapState.java
index 0c2faa4..50a3640 100644
--- a/rails/game/state/HashMultimapState.java
+++ b/rails/game/state/HashMultimapState.java
@@ -106,7 +106,7 @@ public final class HashMultimapState<K,V> extends MultimapState<K,V> implements
return map.toString();
}
- public void change(K key, V value, boolean addToMap) {
+ void change(K key, V value, boolean addToMap) {
if (addToMap) {
map.put(key, value);
} else {
diff --git a/rails/game/state/ItemType.java b/rails/game/state/ItemType.java
new file mode 100644
index 0000000..efd0639
--- /dev/null
+++ b/rails/game/state/ItemType.java
@@ -0,0 +1,5 @@
+package rails.game.state;
+
+public interface ItemType extends Item {
+
+}
diff --git a/rails/game/state/MultimapState.java b/rails/game/state/MultimapState.java
index 3750ffb..f9f3550 100644
--- a/rails/game/state/MultimapState.java
+++ b/rails/game/state/MultimapState.java
@@ -13,6 +13,6 @@ abstract class MultimapState<K,V> extends State {
public abstract boolean remove(K key, V value);
- public abstract void change(K key, V value, boolean addToMap);
+ abstract void change(K key, V value, boolean addToMap);
}
diff --git a/rails/game/state/OwnableItem.java b/rails/game/state/OwnableItem.java
new file mode 100644
index 0000000..aad0cad
--- /dev/null
+++ b/rails/game/state/OwnableItem.java
@@ -0,0 +1,16 @@
+package rails.game.state;
+
+
+public interface OwnableItem<T extends OwnableItem<T>> extends Item {
+
+ /**
+ * @return the parent of an ownableItem has to be an ItemType
+ */
+ public ItemType getParent();
+
+ /**
+ * @return the current portfolio
+ */
+ public PortfolioNG<T> getPortfolio();
+
+}
diff --git a/rails/game/state/PortfolioChange.java b/rails/game/state/PortfolioChange.java
new file mode 100644
index 0000000..acdf5d3
--- /dev/null
+++ b/rails/game/state/PortfolioChange.java
@@ -0,0 +1,44 @@
+package rails.game.state;
+
+final class PortfolioChange<T extends OwnableItem<T>> implements Change {
+
+ private final PortfolioNG<T> in;
+ private final PortfolioNG<T> out; // can be null
+ private final T item;
+
+ PortfolioChange(PortfolioNG<T> in, PortfolioNG<T> out, T item) {
+ this.in = in;
+ this.out = out;
+ this.item = item;
+
+ ChangeStack.add(this);
+ }
+
+ public void execute() {
+ in.change(item, true);
+ if (out != null) {
+ out.change(item, false);
+ }
+ }
+
+ public void undo() {
+ in.change(item, false);
+ if (out != null) {
+ out.change(item, true);
+ }
+ }
+
+ public PortfolioNG<T> getState() {
+ return in;
+ }
+
+ @Override
+ public String toString() {
+ if (out == null) {
+ return "PortfolioChange: Adds item " + item + " to portfolio " + in.getId();
+ } else {
+ return "PortfolioChange: Moves item " + item + " from portfolio " + out.getId() + " to portfolio " + in.getId();
+ }
+ }
+
+}
diff --git a/rails/game/state/PortfolioManager.java b/rails/game/state/PortfolioManager.java
new file mode 100644
index 0000000..b7dab6c
--- /dev/null
+++ b/rails/game/state/PortfolioManager.java
@@ -0,0 +1,38 @@
+package rails.game.state;
+
+import com.google.common.collect.HashMultimap;
+
+/**
+ * PortfolioManager stores links to all existing portfolios
+ * @author freystef
+ */
+
+public class PortfolioManager extends Context {
+
+ public static final String ID = "Portfolios";
+
+ private final HashMultimap<Item, PortfolioNG<?>> portfolios = HashMultimap.create();
+
+ private PortfolioManager() {
+ super(ID);
+ }
+
+ static PortfolioManager create() {
+ return new PortfolioManager();
+ }
+
+ @Override
+ public PortfolioManager init(Item parent) {
+ super.init(parent);
+ return this;
+ }
+
+ boolean addPortfolio(PortfolioNG<?> p){
+ return portfolios.put(p.getParent(), p);
+ }
+
+ boolean removePortfolio(PortfolioNG<?> p){
+ return portfolios.remove(p.getParent(), p);
+ }
+
+}
diff --git a/rails/game/state/PortfolioNG.java b/rails/game/state/PortfolioNG.java
new file mode 100644
index 0000000..e6eb2b3
--- /dev/null
+++ b/rails/game/state/PortfolioNG.java
@@ -0,0 +1,117 @@
+package rails.game.state;
+
+import java.util.Collection;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableListMultimap;
+import com.google.common.collect.ImmutableMap;
+
+public final class PortfolioNG<T extends OwnableItem<T>> extends State {
+
+ private final ArrayListMultimap<ItemType, T> portfolio;
+
+ private PortfolioNG(String id) {
+ super(id);
+ portfolio = ArrayListMultimap.create();
+ }
+
+ /**
+ * Creates an owned and empty Portfolio
+ */
+ public static <T extends OwnableItem<T>> PortfolioNG<T> create(Item parent, String id){
+ return new PortfolioNG<T>(id).init(parent);
+ }
+
+ /**
+ * Creates an unowned and empty Portfolio
+ * Remark: Still requires a call to the init-method
+ */
+ public static <T extends OwnableItem<T>> PortfolioNG<T> create( String id){
+ return new PortfolioNG<T>(id);
+ }
+
+ @Override
+ public PortfolioNG<T> init(Item parent){
+ super.init(parent);
+ return this;
+ }
+
+ /**
+ * Adds an item to the portfolio
+ * @param item to add
+ * @return false if portfolio already contains the item, otherwise true
+ */
+ public boolean initialAdd(T item) {
+ if (portfolio.containsValue(item)) return false;
+ new PortfolioChange<T>(this, null, item);
+ return true;
+ }
+
+ /**
+ * Move a new item to the portfolio
+ * and removes the item from the previous portfolio
+ * @param item to move
+ * @return false if the portfolio already contains the item, otherwise true
+ */
+ public boolean moveInto(T item) {
+ if (portfolio.containsValue(item)) return false;
+ new PortfolioChange<T>(this, item.getPortfolio(), item);
+ return true;
+ }
+
+ /**
+ * @param item that is checked if it is in the portfolio
+ * @return true if contained, false otherwise
+ */
+ public boolean containsItem(T item) {
+ return portfolio.containsValue(item);
+ }
+
+ /**
+ * @param type that is checked if there are items stored for
+ * @return true if there a items stored under that type, false otherwise
+ */
+ public boolean containsKey(ItemType type) {
+ return portfolio.containsKey(type);
+ }
+
+ /**
+ * @return all items contained in the portfolio
+ */
+ public ImmutableList<T> items() {
+ return ImmutableList.copyOf(portfolio.values());
+ }
+
+
+ /**
+ * @param key that defines the specific itemtype for which the portfolio members get returned
+ * @return all items of type key contained in the portfolio
+ */
+ public ImmutableList<T> getItems(ItemType key) {
+ return ImmutableList.copyOf(portfolio.get(key));
+ }
+
+ /**
+ * @return a ListMultimap view of the Portfolio
+ */
+ public ImmutableListMultimap<ItemType, T> view() {
+ return ImmutableListMultimap.copyOf(portfolio);
+ }
+
+ /**
+ * @return a Map view of the Portfolio
+ */
+ public ImmutableMap<ItemType, Collection<T>> viewAsMap() {
+ return ImmutableMap.copyOf(portfolio.asMap());
+ }
+
+ void change (T item, boolean intoPortfolio){
+ if (intoPortfolio) {
+ portfolio.put(item.getParent(), item);
+ } else {
+ portfolio.remove(item.getParent(), item);
+ }
+ }
+
+}
diff --git a/rails/game/state/StateManager.java b/rails/game/state/StateManager.java
index 7ef27c5..3812e44 100644
--- a/rails/game/state/StateManager.java
+++ b/rails/game/state/StateManager.java
@@ -15,33 +15,72 @@ import com.google.common.collect.Sets;
import rails.game.GameManager;
import rails.game.model.Model;
+// TODO: Change it to a Context subclass
+
public final class StateManager extends GameItem {
+ public static final String ID = "States";
+
protected static Logger log =
Logger.getLogger(StateManager.class.getPackage().getName());
private final Set<State> allStates = new HashSet<State>();
+
+ private final PortfolioManager portfolioManager = PortfolioManager.create();
+ private final WalletManager walletManager = WalletManager.create();
+
+ private StateManager() {
+ super(ID);
+ }
/**
- * Creates a StateManager (only possible for a root GameContext)
- * @param parent a root GameContext
+ * Creates an (unowned) StateManager
+ * Remark: Still requires a call to the init-method
*/
- StateManager(Context parent) {
- super("StateManager");
-
- if (parent.getId() != Context.ROOT) {
+ public static StateManager create(){
+ return new StateManager();
+ }
+
+ /**
+ * @exception IllegalArgumentException if parent is not the Context with an id equal to Context.ROOT
+ */
+ @Override
+ public StateManager init(Item parent) {
+ if (!(parent instanceof Context && parent.getId() != Context.ROOT)) {
throw new IllegalArgumentException("StateManager can only be created for a root GameContext");
}
- // immediate initialization
- init(parent);
+ super.init(parent);
+ portfolioManager.init(parent);
+ walletManager.init(parent);
+ return this;
}
- void registerState(State state) {
- allStates.add(state);
+ /**
+ * Register states
+ * Remark: Portfolios and Wallets get added from their respective managers automatically
+ */
+ boolean registerState(State state) {
+ if (!allStates.add(state)) return false;
+ if (state instanceof PortfolioNG) {
+ return portfolioManager.addPortfolio((PortfolioNG<?>) state);
+ } else if (state instanceof Wallet) {
+ return walletManager.addWallet((Wallet<?>) state);
+ }
+ return true;
}
+ /**
+ * De-Register states
+ * Remark: Portfolios and Wallets are removed from their respective managers automatically
+ */
boolean deRegisterState(State state) {
- return allStates.remove(state);
+ if (!allStates.remove(state)) return false;
+ if (state instanceof PortfolioNG) {
+ return portfolioManager.removePortfolio((PortfolioNG<?>) state);
+ } else if (state instanceof Wallet) {
+ return walletManager.removeWallet((Wallet<?>) state);
+ }
+ return true;
}
/**
diff --git a/rails/game/state/Wallet.java b/rails/game/state/Wallet.java
new file mode 100644
index 0000000..da119bd
--- /dev/null
+++ b/rails/game/state/Wallet.java
@@ -0,0 +1,111 @@
+package rails.game.state;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.ImmutableMultiset;
+
+/**
+ * A wallet allows the storage of CountableItem(s)
+ *
+ * Remark: It is a wrapper around a Multiset, thus it does not support negative
+ * numbers.
+ *
+ * @author freystef
+ */
+
+public final class Wallet<T extends CountableItem> extends State {
+
+
+ private final HashMultiset<T> wallet;
+
+
+ private Wallet(String id) {
+ super(id);
+ wallet = HashMultiset.create();
+ }
+
+ /**
+ * Creates an owned and empty Wallet
+ */
+ public static <T extends CountableItem> Wallet<T> create(Item parent, String id){
+ return new Wallet<T>(id).init(parent);
+ }
+
+ /**
+ * Creates an unowned and empty Wallet
+ * Remark: Still requires a call to the init-method
+ */
+ public static <T extends CountableItem> Wallet<T> create( String id){
+ return new Wallet<T>(id);
+ }
+
+ @Override
+ public Wallet<T> init(Item parent){
+ super.init(parent);
+ return this;
+ }
+
+ /**
+ * Sets an item to the wallet to the amount given (only if there is no amount defined yet)
+ * @param item to set
+ * @param amount initial (has to be positive)
+ * @return false if portfolio already contains the item (=> no change), otherwise true
+
+ * @exception IllegalArgumentException if amount is negative
+ */
+ public boolean initialSet(T item, int amount) {
+ if (amount < 0) throw new IllegalArgumentException("Wallet amounts have to be positive");
+ if (wallet.contains(item)) return false;
+
+ new WalletChange<T>(this, null, item, amount);
+ return true;
+ }
+
+ /**
+ * Adds a specific amount to the specified item
+ * @param item to change
+ * @param amount initial (has to be positive)
+ * @param source the wallet from which the amount is moved
+
+ * @exception IllegalArgumentException if amount is negative
+ * @exception ArithmeticException if wallet which is used as source does not contain at least the amount
+ */
+
+ public void moveInto(T item, int amount, Wallet<T> source) {
+ if (amount < 0) throw new IllegalArgumentException("Wallet amounts have to be positive");
+
+ if (amount > source.count(item)) throw new ArithmeticException("Source wallet does not contain required amount");
+
+ new WalletChange<T>(this, source, item, amount);
+ }
+
+ /**
+ * Adds one unit of the specified item
+ * @param item to change
+ * @param from the wallet from which the unit is taken
+ */
+ public void moveInto(T item, Wallet<T> from) {
+ moveInto(item, 1, from);
+ }
+
+
+ /**
+ * @param item to count
+ * @return the current number of the specified amount in the wallet
+ */
+ public int count(T item) {
+ return wallet.count(item);
+ }
+
+ /**
+ * @return a Multiset view of the Wallet
+ */
+ public ImmutableMultiset<T> view() {
+ return ImmutableMultiset.copyOf(wallet);
+ }
+
+
+ void change (T item, int value) {
+ wallet.add(item, value);
+ }
+
+}
diff --git a/rails/game/state/WalletChange.java b/rails/game/state/WalletChange.java
new file mode 100644
index 0000000..da646c3
--- /dev/null
+++ b/rails/game/state/WalletChange.java
@@ -0,0 +1,50 @@
+package rails.game.state;
+
+final class WalletChange<T extends CountableItem> implements Change {
+
+ private final Wallet<T> in;
+ private final Wallet<T> out;
+ private final T item;
+ private final int amount;
+
+
+ WalletChange(Wallet<T> in, Wallet<T> out, T item, int amount) {
+ this.in = in;
+ this.out = out;
+ this.item = item;
+ this.amount = amount;
+
+ ChangeStack.add(this);
+ }
+
+
+ public void execute() {
+ in.change(item, amount);
+ if (out != null) {
+ out.change(item, - amount);
+ }
+ }
+
+ public void undo() {
+ in.change(item, - amount);
+ if (out != null) {
+ out.change(item, amount);
+ }
+ }
+
+ public Wallet<T> getState() {
+ return in;
+ }
+
+ @Override
+ public String toString() {
+ if (out == null) {
+ return "WalletChange: Sets " + amount + " of " + item + " in wallet " + in.getId();
+ } else {
+ return "WalletChange: Moves " + amount + " of " + item + " from wallet " + out.getId() + " to wallet " + in.getId();
+ }
+ }
+
+
+
+}
diff --git a/rails/game/state/WalletManager.java b/rails/game/state/WalletManager.java
new file mode 100644
index 0000000..2d00847
--- /dev/null
+++ b/rails/game/state/WalletManager.java
@@ -0,0 +1,38 @@
+package rails.game.state;
+
+import com.google.common.collect.HashMultimap;
+
+/**
+ * WalletManager stores links to all existing wallets
+ * @author freystef
+ */
+
+public class WalletManager extends Context {
+
+ public static final String ID = "Wallets";
+
+ private final HashMultimap<Item, Wallet<?>> wallets = HashMultimap.create();
+
+ private WalletManager() {
+ super(ID);
+ }
+
+ static WalletManager create() {
+ return new WalletManager();
+ }
+
+ @Override
+ public WalletManager init(Item parent) {
+ super.init(parent);
+ return this;
+ }
+
+ boolean addWallet(Wallet<?> w){
+ return wallets.put(w.getParent(), w);
+ }
+
+ boolean removeWallet(Wallet<?> w){
+ return wallets.remove(w.getParent(), w);
+ }
+
+}
|
|
From: Frederick W. <fre...@us...> - 2012-02-07 16:37:37
|
rails/ui/swing/GridPanel.java | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
New commits:
commit 59e98fa0bda31a4f2944fee0dac6bd123b322bb0
Author: Frederick Weld <fre...@gm...>
Date: Tue Feb 7 17:36:03 2012 +0100
Increased robustness of grid panel highlighting
getBorderInsets was reported to return null under some conditions.
Now, GridPanel is able to handle that.
diff --git a/rails/ui/swing/GridPanel.java b/rails/ui/swing/GridPanel.java
index 9f11f42..d2ea42b 100644
--- a/rails/ui/swing/GridPanel.java
+++ b/rails/ui/swing/GridPanel.java
@@ -252,12 +252,16 @@ implements ActionListener, KeyListener {
this.nativeInnerBorder = innerBorder;
this.outlineBorder = outlineBorder;
this.outerBorder = outerBorder;
+ Insets nativeInnerBorderInsets = nativeInnerBorder.getBorderInsets(null);
+ if (nativeInnerBorderInsets == null) {
+ nativeInnerBorderInsets = new Insets(0,0,0,0);
+ }
this.highlightedInnerBorder = new DynamicBorder(
highlightedBorderColor,
- nativeInnerBorder.getBorderInsets(null).top,
- nativeInnerBorder.getBorderInsets(null).left,
- nativeInnerBorder.getBorderInsets(null).bottom,
- nativeInnerBorder.getBorderInsets(null).right);
+ nativeInnerBorderInsets.top,
+ nativeInnerBorderInsets.left,
+ nativeInnerBorderInsets.bottom,
+ nativeInnerBorderInsets.right);
}
public void setHighlight(boolean isToBeHighlighted) {
outlineBorder.setHighlight(isToBeHighlighted);
|
|
From: Stefan F. <ste...@us...> - 2012-02-07 11:53:44
|
Tag '1.6.3' created by Stefan Frey <ste...@we...> at 2012-02-07 11:53 +0000 version 1.6.3 Changes since v1.6.2-2: --- 0 files changed --- |
|
From: Frederick W. <fre...@us...> - 2012-02-05 13:24:18
|
rails/ui/swing/ORWindow.java | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
New commits:
commit 6d5f311591d781cecd4bfe4bb2fcf3e2a9b8be65
Author: Frederick Weld <fre...@gm...>
Date: Sun Feb 5 14:21:31 2012 +0100
Fixed: Externalized panels taken into account when close/open OR window
Stefan had observed that externalized panels were not correctly
restored when closing / re-opening the OR Window.
diff --git a/rails/ui/swing/ORWindow.java b/rails/ui/swing/ORWindow.java
index b35bc3e..441be07 100644
--- a/rails/ui/swing/ORWindow.java
+++ b/rails/ui/swing/ORWindow.java
@@ -191,7 +191,11 @@ public class ORWindow extends JFrame implements ActionPerformer {
public void windowClosing(WindowEvent e) {
saveDockableLayout();
StatusWindow.uncheckMenuItemBox(StatusWindow.MAP_CMD);
- frame.dispose();
+ if (!isDockablePanelsEnabled()) {
+ frame.dispose();
+ } else {
+ setVisible(false);
+ }
}
});
addComponentListener(new ComponentAdapter() {
|
|
From: Frederick W. <fre...@us...> - 2012-02-05 10:26:18
|
rails/ui/swing/ORWindow.java | 126 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 125 insertions(+), 1 deletion(-)
New commits:
commit 9b2b2d123eee75c646a4e0159f8420b672865504
Author: Frederick Weld <fre...@gm...>
Date: Sun Feb 5 11:16:10 2012 +0100
Added support for docking externalized panels to each other
Solution consists of adding a SplitDockStation in between and fine
tuning the default dockable options (maximize button).
Based on http://forum.byte-welt.de/showthread.php?t=3097&page=2
diff --git a/rails/ui/swing/ORWindow.java b/rails/ui/swing/ORWindow.java
index 5f75ad9..b35bc3e 100644
--- a/rails/ui/swing/ORWindow.java
+++ b/rails/ui/swing/ORWindow.java
@@ -12,13 +12,28 @@ import java.util.Locale;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
+import javax.swing.SwingUtilities;
import org.apache.log4j.Logger;
+import bibliothek.gui.DockController;
+import bibliothek.gui.Dockable;
+import bibliothek.gui.DockStation;
+import bibliothek.gui.dock.ScreenDockStation;
+import bibliothek.gui.dock.SplitDockStation;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CGrid;
+import bibliothek.gui.dock.common.CStation;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
+import bibliothek.gui.dock.common.action.predefined.CBlank;
+import bibliothek.gui.dock.common.event.CDockableStateListener;
+import bibliothek.gui.dock.common.intern.CDockable;
+import bibliothek.gui.dock.common.intern.DefaultCDockable;
+import bibliothek.gui.dock.common.intern.ui.CSingleParentRemover;
+import bibliothek.gui.dock.common.mode.ExtendedMode;
import bibliothek.gui.dock.common.theme.ThemeMap;
+import bibliothek.gui.dock.event.DockStationAdapter;
+import bibliothek.gui.dock.station.LayoutLocked;
import rails.common.GuiDef;
import rails.common.LocalText;
@@ -92,7 +107,11 @@ public class ORWindow extends JFrame implements ActionPerformer {
orWindowControl.setTheme( ThemeMap.KEY_SMOOTH_THEME );
add( orWindowControl.getContentArea() );
CGrid orWindowLayout = new CGrid( orWindowControl );
-
+
+ //ensure that externalized dockables get a split station as parent
+ //necessary, otherwise externalized dockables cannot be docked together
+ alwaysAddStationsToExternalizedDockables(orWindowControl);
+
//set docks tooltip language
if ("en_us".equalsIgnoreCase(Config.get("locale"))) {
//hard setting to default in case of US as this is DockingFrames default language
@@ -350,6 +369,111 @@ public class ORWindow extends JFrame implements ActionPerformer {
orWindowControl.load(getLayoutName());
} catch (Exception e) {} //skip if layout not found
}
+
+ //ensure that all dockables that are externalized according to layout
+ //information don't have the deault maximize button (as it won't work
+ //for the adjusted externalization setup)
+ for (int i = 0 ; i < orWindowControl.getCDockableCount() ; i++ ) {
+ CDockable d = orWindowControl.getCDockable(i);
+ if (d instanceof DefaultCDockable) {
+ DefaultCDockable dd = (DefaultCDockable)d;
+ if (ExtendedMode.EXTERNALIZED.equals(d.getExtendedMode())) {
+ dd.putAction( CDockable.ACTION_KEY_MAXIMIZE, CBlank.BLANK );
+ }
+ }
+ }
+ }
+
+ /**
+ * The behavior of the specified CControl is altered by the following:
+ * If a dockable is detached / externalized, it would normally put directly
+ * under the ScreenDockStation - thus inhibiting any docking to/from this
+ * dockable. This is changed such that a split station (that would allow for
+ * that) is put in between the ScreenDockStation and the Dockable.
+ */
+ private void alwaysAddStationsToExternalizedDockables(CControl cc) {
+
+ // access the DockStation which shows our detached (externalized) items
+ CStation<?> screen = (CStation<?>)
+ cc.getStation( CControl.EXTERNALIZED_STATION_ID );
+
+ // remove the standard maximize action when externalizing
+ // and adds it back when unexternalizing
+ // (as maximize won't work for the adjusted externalization setup)
+ cc.addStateListener( new CDockableStateListener() {
+ public void visibilityChanged( CDockable cd ){
+ // ignore
+ }
+
+ public void extendedModeChanged( CDockable cd, ExtendedMode mode ){
+ if( cd instanceof DefaultCDockable ) {
+ DefaultCDockable dockable = (DefaultCDockable) cd;
+ if( mode.equals( ExtendedMode.EXTERNALIZED ) ) {
+ dockable.putAction( CDockable.ACTION_KEY_MAXIMIZE, CBlank.BLANK );
+ }
+ else {
+ dockable.putAction( CDockable.ACTION_KEY_MAXIMIZE, null );
+ }
+ }
+ }
+ });
+
+ // if a Dockable is added to that station...
+ screen.getStation().addDockStationListener( new ScreenDockStationListener());
+
+ // make sure a SplitDockStation with one child and a parent
+ // that is a ScreenDockStation does not get removed
+ cc.intern().getController().setSingleParentRemover(
+ new CSingleParentRemover( cc ){
+ @Override
+ protected boolean shouldTest( DockStation station ){
+ if( station instanceof SplitDockStation ) {
+ SplitDockStation split = (SplitDockStation) station;
+ if( split.getDockParent() instanceof ScreenDockStation ) {
+ // but we want to remove the station if it does
+ // not have any children at all
+ return split.getDockableCount() == 0;
+ }
+ }
+ return super.shouldTest( station );
+ }
+ } );
}
+ @LayoutLocked(locked = false)
+ private class ScreenDockStationListener extends DockStationAdapter {
+ public void dockableAdded( DockStation station, final Dockable dockable ){
+ // ... and the new child is not a SplitDockStation ...
+ if( !(dockable instanceof SplitDockStation) ) {
+ SwingUtilities.invokeLater( new Runnable(){
+ public void run(){
+ checkAndReplace( dockable );
+ }
+ } );
+ }
+ }
+ private void checkAndReplace( Dockable dockable ){
+ DockStation station = dockable.getDockParent();
+ if( !(station instanceof ScreenDockStation) ) {
+ // cancel
+ return;
+ }
+
+ // .. then we just insert a SplitDockStation
+ SplitDockStation split = new SplitDockStation();
+ DockController controller = station.getController();
+
+ try {
+ // disable events while rearranging our layout
+ controller.freezeLayout();
+
+ station.replace( dockable, split );
+ split.drop( dockable );
+ }
+ finally {
+ // and enable events after we finished
+ controller.meltLayout();
+ }
+ }
+ }
}
|
|
From: Frederick W. <fre...@us...> - 2012-02-05 06:35:36
|
LocalisedText.properties | 3 +++
data/Properties.xml | 2 ++
rails/game/GameManager.java | 4 ++++
rails/game/GameManagerI.java | 2 ++
rails/sound/SoundConfig.java | 6 ++++--
rails/sound/SoundEventInterpreter.java | 28 ++++++++++++++++++++++++++--
6 files changed, 41 insertions(+), 4 deletions(-)
New commits:
commit 4439e439edd8982aca87b35c0ea64e331a4981cb
Author: Frederick Weld <fre...@gm...>
Date: Sun Feb 5 07:28:16 2012 +0100
Added new sfx options (gameOverPending and "laid last available tile")
diff --git a/LocalisedText.properties b/LocalisedText.properties
index 071d381..6aaa145 100644
--- a/LocalisedText.properties
+++ b/LocalisedText.properties
@@ -178,6 +178,7 @@ Config.infoText.sound.backgroundMusic=The only music file type supported is mp3.
Config.infoText.sound.backgroundMusic.stockRound=<html>Enter assignment of music files to phases.<ul><li>Separate the assignments by commas.<li>Each assignment has the syntax phaseName=complete file path<li>Default music is defined by omitting "phaseName=" in the assignment.</ul><strong>Examples:</strong><ul><li>Set default music: <br><code>c:\SR-default.mp3</code><li>Set phase-dependent music and a default (for trains above 6): <br><code>2=c:\SR-2.mp3,3=c:\SR-3.mp3,4=c:\SR-4.mp3,5=c:\SR-5.mp3,6=c:\SR-6.mp3,c:\SR-D.mp3</code></ul> </html>
Config.infoText.sound.backgroundMusic.operatingRound=<html>Enter assignment of music files to phases.<ul><li>Separate the assignments by commas.<li>Each assignment has the syntax phaseName=complete file path<li>Default music is defined by omitting "phaseName=" in the assignment.</ul><strong>Examples:</strong><ul><li>Set default music: <br><code>c:\OR-default.mp3</code><li>Set phase-dependent music and a default (for trains above 6): <br><code>2=c:\OR-2.mp3,3=c:\OR-3.mp3,4=c:\OR-4.mp3,5=c:\OR-5.mp3,6=c:\OR-6.mp3,c:\OR-D.mp3</code></ul> </html>
Config.infoText.sound.sfx=The only sound effects file type supported is mp3.
+Config.infoText.sound.sfx.gen.gameOverPending=<html>Sound effect is played in case of any event that triggers the end of the game. Examples:<ul><li>Bank is broken.<li>Share price reaches maximum (only game-end trigger for some 18xx variants).</ul></html>
Config.infoText.sound.sfx.gen.newCurrentPlayer=<html>Enter assignment of sound effect files to player names.<br>The assigned sound is played if the player becomes the active one - meaning, the user interface is responsive for this player's commands.<ul><li>Separate the assignments by commas.<li>Each assignment has the syntax playerName=complete file path<li>Default sound effect is defined by omitting "playerName=" in the assignment.</ul><strong>Examples:</strong><ul><li>Set default sound effect: <br><code>c:\ChangeActivePlayer.mp3</code><li>Set player-dependent sound effect and a default (for all other players): <br><code>Tom=c:\ChangeActivePlayer_Tom.mp3,Sarah=c:\ChangeActivePlayer_Sarah.mp3,c:\ChangeActivePlayer_default.mp3</code></ul> </html>
Config.infoText.sound.sfx.or.buyTrain=<html>Enter assignment of sound effect files to train types.<ul><li>Separate the assignments by commas.<li>Each assignment has the syntax trainName=complete file path<li>Default sound effect is defined by omitting "trainName=" in the assignment.</ul><strong>Examples:</strong><ul><li>Set default sound effect: <br><code>c:\BuyTrain-default.mp3</code><li>Set train-dependent sound effect and a default (for trains above 6): <br><code>2=c:\BuyTrain-2.mp3,3=c:\BuyTrain-3.mp3,4=c:\BuyTrain-4.mp3,5=c:\BuyTrain-5.mp3,6=c:\BuyTrain-6.mp3,c:\BuyTrain-D.mp3</code></ul> </html>
Config.infoText.sound.sfx.or.setRevenue=<html><ul><li>Only the latter portion of this file is played.<ul><li>For an average revenue, the last third is played.</ul><li>The higher the company's revenue the longer this file is played.<ul><li>But the file is at most played once as a whole.</li></ul></html>
@@ -216,6 +217,7 @@ Config.label.sound.backgroundMusic.startRound=Start Round
Config.label.sound.backgroundMusic.stockRound=Stock Round (several files)
Config.label.sound.backgroundMusic.operatingRound=Operating Round (several files)
Config.label.sound.sfx=Sound Effects
+Config.label.sound.sfx.gen.gameOverPending=Imminent Game End
Config.label.sound.sfx.gen.newCurrentPlayer=Change of active player
Config.label.sound.sfx.gen.pass=Pass
Config.label.sound.sfx.gen.select=Select (hexes, click fields)
@@ -228,6 +230,7 @@ Config.label.sound.sfx.or.decision.split=Split Revenue
Config.label.sound.sfx.or.decision.withhold=Withhold Revenue
Config.label.sound.sfx.or.layTile.city=Lay Tile (city)
Config.label.sound.sfx.or.layTile.track=Lay Tile (track, town)
+Config.label.sound.sfx.or.layTile.lastTileLaid=Last available tile is laid
Config.label.sound.sfx.or.layToken=Lay Token
Config.label.sound.sfx.or.rotateTile=Rotate Tile
Config.label.sound.sfx.or.setRevenue=Set Revenue
diff --git a/data/Properties.xml b/data/Properties.xml
index 4802f74..da62099 100644
--- a/data/Properties.xml
+++ b/data/Properties.xml
@@ -77,6 +77,7 @@
<Property name="sound.sfx.gen.pass" type="FILE" />
<Property name="sound.sfx.gen.select" type="FILE" />
<Property name="sound.sfx.gen.newCurrentPlayer" type="STRING" />
+ <Property name="sound.sfx.gen.gameOverPending" type="FILE" />
<Property name="sound.sfx.str.bidStartItem" type="FILE" />
<Property name="sound.sfx.str.buyStartItem" type="FILE" />
<Property name="sound.sfx.sr.openingBell" type="FILE" />
@@ -89,6 +90,7 @@
<Property name="sound.sfx.or.rotateTile" type="FILE" />
<Property name="sound.sfx.or.layTile.track" type="FILE" />
<Property name="sound.sfx.or.layTile.city" type="FILE" />
+ <Property name="sound.sfx.or.layTile.lastTileLaid" type="FILE" />
<Property name="sound.sfx.or.layToken" type="FILE" />
<Property name="sound.sfx.or.setRevenue" type="FILE" />
<Property name="sound.sfx.or.decision.payout" type="FILE" />
diff --git a/rails/sound/SoundConfig.java b/rails/sound/SoundConfig.java
index 6867ddf..5e3aa03 100644
--- a/rails/sound/SoundConfig.java
+++ b/rails/sound/SoundConfig.java
@@ -24,6 +24,7 @@ public class SoundConfig {
public static final String KEY_BGM_OperatingRound = "sound.backgroundMusic.operatingRound";
public static final String KEY_BGM_EndOfGameRound = "sound.backgroundMusic.endOfGameRound";
public static final String KEY_SFX_Enabled = "sound.sfx";
+ public static final String KEY_SFX_GEN_GameOverPending = "sound.sfx.gen.gameOverPending";
public static final String KEY_SFX_GEN_Pass = "sound.sfx.gen.pass";
public static final String KEY_SFX_GEN_Select = "sound.sfx.gen.select";
public static final String KEY_SFX_GEN_NewCurrentPlayer = "sound.sfx.gen.newCurrentPlayer";
@@ -37,8 +38,9 @@ public class SoundConfig {
public static final String KEY_SFX_SR_SellShare_NonPresident = "sound.sfx.sr.sellShare.nonPresident";
public static final String KEY_SFX_SR_CompanyFloats = "sound.sfx.sr.companyFloats";
public static final String KEY_SFX_OR_RotateTile = "sound.sfx.or.rotateTile";
- public static final String KEY_SFX_OR_LayTile_track = "sound.sfx.or.layTile.track";
- public static final String KEY_SFX_OR_LayTile_city = "sound.sfx.or.layTile.city";
+ public static final String KEY_SFX_OR_LayTile_Track = "sound.sfx.or.layTile.track";
+ public static final String KEY_SFX_OR_LayTile_City = "sound.sfx.or.layTile.city";
+ public static final String KEY_SFX_OR_LayTile_LastTileLaid = "sound.sfx.or.layTile.lastTileLaid";
public static final String KEY_SFX_OR_LayToken = "sound.sfx.or.layToken";
public static final String KEY_SFX_OR_SetRevenue = "sound.sfx.or.setRevenue";
public static final String KEY_SFX_OR_Decision_Payout = "sound.sfx.or.decision.payout";
diff --git a/rails/sound/SoundEventInterpreter.java b/rails/sound/SoundEventInterpreter.java
index 48a8df2..889ade6 100644
--- a/rails/sound/SoundEventInterpreter.java
+++ b/rails/sound/SoundEventInterpreter.java
@@ -105,10 +105,14 @@ public class SoundEventInterpreter {
LayTile lt = (LayTile)action;
if (lt.getLaidTile().getNumStations() == 0) {
//track upgrade
- player.playSFXByConfigKey (SoundConfig.KEY_SFX_OR_LayTile_track);
+ player.playSFXByConfigKey (SoundConfig.KEY_SFX_OR_LayTile_Track);
} else {
//city upgrade
- player.playSFXByConfigKey (SoundConfig.KEY_SFX_OR_LayTile_city);
+ player.playSFXByConfigKey (SoundConfig.KEY_SFX_OR_LayTile_City);
+ }
+ if (lt.getLaidTile().countFreeTiles() == 1) {
+ //last available tile is about to be laid
+ player.playSFXByConfigKey (SoundConfig.KEY_SFX_OR_LayTile_LastTileLaid);
}
} else if (action instanceof LayToken) {
@@ -194,6 +198,26 @@ public class SoundEventInterpreter {
});
}
+ //subscribe to changes to game over pending
+ if (gameManager.getGameOverPendingModel() != null) {
+ gameManager.getGameOverPendingModel().addObserver(
+ new Observer() {
+ private boolean gameOverPending = false;
+ public void update(Observable o, Object arg) {
+ if (o instanceof BooleanState) {
+ BooleanState s = (BooleanState)o;
+ if (!gameOverPending && s.booleanValue()) {
+ if (SoundConfig.isSFXEnabled()) {
+ player.playSFXByConfigKey (
+ SoundConfig.KEY_SFX_GEN_GameOverPending);
+ }
+ }
+ gameOverPending = s.booleanValue();
+ }
+ }
+ });
+ }
+
//subscribe to phase changes
if (gameManager.getPhaseManager() != null) {
gameManager.getPhaseManager().getCurrentPhaseModel().addObserver(
commit 2614a3132315acee7b4a2411314b26754accc5c9
Merge: 08f42f7 b16bcfb
Author: Frederick Weld <fre...@gm...>
Date: Sun Feb 5 07:28:05 2012 +0100
Exposed GameManager's GameOverPending BooleanState on interface
commit b16bcfb3f1d186b10fbe6fc6a8bae95019ad15bf
Author: Frederick Weld <fre...@gm...>
Date: Sun Feb 5 07:19:48 2012 +0100
Exposed GameManager's GameOverPending BooleanState on interface
diff --git a/LocalisedText.properties b/LocalisedText.properties
index 071d381..6aaa145 100644
--- a/LocalisedText.properties
+++ b/LocalisedText.properties
@@ -178,6 +178,7 @@ Config.infoText.sound.backgroundMusic=The only music file type supported is mp3.
Config.infoText.sound.backgroundMusic.stockRound=<html>Enter assignment of music files to phases.<ul><li>Separate the assignments by commas.<li>Each assignment has the syntax phaseName=complete file path<li>Default music is defined by omitting "phaseName=" in the assignment.</ul><strong>Examples:</strong><ul><li>Set default music: <br><code>c:\SR-default.mp3</code><li>Set phase-dependent music and a default (for trains above 6): <br><code>2=c:\SR-2.mp3,3=c:\SR-3.mp3,4=c:\SR-4.mp3,5=c:\SR-5.mp3,6=c:\SR-6.mp3,c:\SR-D.mp3</code></ul> </html>
Config.infoText.sound.backgroundMusic.operatingRound=<html>Enter assignment of music files to phases.<ul><li>Separate the assignments by commas.<li>Each assignment has the syntax phaseName=complete file path<li>Default music is defined by omitting "phaseName=" in the assignment.</ul><strong>Examples:</strong><ul><li>Set default music: <br><code>c:\OR-default.mp3</code><li>Set phase-dependent music and a default (for trains above 6): <br><code>2=c:\OR-2.mp3,3=c:\OR-3.mp3,4=c:\OR-4.mp3,5=c:\OR-5.mp3,6=c:\OR-6.mp3,c:\OR-D.mp3</code></ul> </html>
Config.infoText.sound.sfx=The only sound effects file type supported is mp3.
+Config.infoText.sound.sfx.gen.gameOverPending=<html>Sound effect is played in case of any event that triggers the end of the game. Examples:<ul><li>Bank is broken.<li>Share price reaches maximum (only game-end trigger for some 18xx variants).</ul></html>
Config.infoText.sound.sfx.gen.newCurrentPlayer=<html>Enter assignment of sound effect files to player names.<br>The assigned sound is played if the player becomes the active one - meaning, the user interface is responsive for this player's commands.<ul><li>Separate the assignments by commas.<li>Each assignment has the syntax playerName=complete file path<li>Default sound effect is defined by omitting "playerName=" in the assignment.</ul><strong>Examples:</strong><ul><li>Set default sound effect: <br><code>c:\ChangeActivePlayer.mp3</code><li>Set player-dependent sound effect and a default (for all other players): <br><code>Tom=c:\ChangeActivePlayer_Tom.mp3,Sarah=c:\ChangeActivePlayer_Sarah.mp3,c:\ChangeActivePlayer_default.mp3</code></ul> </html>
Config.infoText.sound.sfx.or.buyTrain=<html>Enter assignment of sound effect files to train types.<ul><li>Separate the assignments by commas.<li>Each assignment has the syntax trainName=complete file path<li>Default sound effect is defined by omitting "trainName=" in the assignment.</ul><strong>Examples:</strong><ul><li>Set default sound effect: <br><code>c:\BuyTrain-default.mp3</code><li>Set train-dependent sound effect and a default (for trains above 6): <br><code>2=c:\BuyTrain-2.mp3,3=c:\BuyTrain-3.mp3,4=c:\BuyTrain-4.mp3,5=c:\BuyTrain-5.mp3,6=c:\BuyTrain-6.mp3,c:\BuyTrain-D.mp3</code></ul> </html>
Config.infoText.sound.sfx.or.setRevenue=<html><ul><li>Only the latter portion of this file is played.<ul><li>For an average revenue, the last third is played.</ul><li>The higher the company's revenue the longer this file is played.<ul><li>But the file is at most played once as a whole.</li></ul></html>
@@ -216,6 +217,7 @@ Config.label.sound.backgroundMusic.startRound=Start Round
Config.label.sound.backgroundMusic.stockRound=Stock Round (several files)
Config.label.sound.backgroundMusic.operatingRound=Operating Round (several files)
Config.label.sound.sfx=Sound Effects
+Config.label.sound.sfx.gen.gameOverPending=Imminent Game End
Config.label.sound.sfx.gen.newCurrentPlayer=Change of active player
Config.label.sound.sfx.gen.pass=Pass
Config.label.sound.sfx.gen.select=Select (hexes, click fields)
@@ -228,6 +230,7 @@ Config.label.sound.sfx.or.decision.split=Split Revenue
Config.label.sound.sfx.or.decision.withhold=Withhold Revenue
Config.label.sound.sfx.or.layTile.city=Lay Tile (city)
Config.label.sound.sfx.or.layTile.track=Lay Tile (track, town)
+Config.label.sound.sfx.or.layTile.lastTileLaid=Last available tile is laid
Config.label.sound.sfx.or.layToken=Lay Token
Config.label.sound.sfx.or.rotateTile=Rotate Tile
Config.label.sound.sfx.or.setRevenue=Set Revenue
diff --git a/data/Properties.xml b/data/Properties.xml
index 4802f74..da62099 100644
--- a/data/Properties.xml
+++ b/data/Properties.xml
@@ -77,6 +77,7 @@
<Property name="sound.sfx.gen.pass" type="FILE" />
<Property name="sound.sfx.gen.select" type="FILE" />
<Property name="sound.sfx.gen.newCurrentPlayer" type="STRING" />
+ <Property name="sound.sfx.gen.gameOverPending" type="FILE" />
<Property name="sound.sfx.str.bidStartItem" type="FILE" />
<Property name="sound.sfx.str.buyStartItem" type="FILE" />
<Property name="sound.sfx.sr.openingBell" type="FILE" />
@@ -89,6 +90,7 @@
<Property name="sound.sfx.or.rotateTile" type="FILE" />
<Property name="sound.sfx.or.layTile.track" type="FILE" />
<Property name="sound.sfx.or.layTile.city" type="FILE" />
+ <Property name="sound.sfx.or.layTile.lastTileLaid" type="FILE" />
<Property name="sound.sfx.or.layToken" type="FILE" />
<Property name="sound.sfx.or.setRevenue" type="FILE" />
<Property name="sound.sfx.or.decision.payout" type="FILE" />
diff --git a/rails/game/GameManager.java b/rails/game/GameManager.java
index c4c2289..f35ed6a 100644
--- a/rails/game/GameManager.java
+++ b/rails/game/GameManager.java
@@ -1380,6 +1380,10 @@ public class GameManager implements ConfigurableComponentI, GameManagerI {
return gameOver.booleanValue();
}
+ public ModelObject getGameOverPendingModel() {
+ return gameOverPending;
+ }
+
public void setGameOverReportedUI(boolean b){
gameOverReportedUI = b;
}
diff --git a/rails/game/GameManagerI.java b/rails/game/GameManagerI.java
index f098de6..06b404c 100644
--- a/rails/game/GameManagerI.java
+++ b/rails/game/GameManagerI.java
@@ -80,6 +80,8 @@ public interface GameManagerI extends MoveableHolder, ConfigurableComponentI {
*/
public abstract boolean isGameOver();
+ public ModelObject getGameOverPendingModel();
+
public void setGameOverReportedUI(boolean b);
public boolean getGameOverReportedUI();
diff --git a/rails/sound/SoundConfig.java b/rails/sound/SoundConfig.java
index 6867ddf..5e3aa03 100644
--- a/rails/sound/SoundConfig.java
+++ b/rails/sound/SoundConfig.java
@@ -24,6 +24,7 @@ public class SoundConfig {
public static final String KEY_BGM_OperatingRound = "sound.backgroundMusic.operatingRound";
public static final String KEY_BGM_EndOfGameRound = "sound.backgroundMusic.endOfGameRound";
public static final String KEY_SFX_Enabled = "sound.sfx";
+ public static final String KEY_SFX_GEN_GameOverPending = "sound.sfx.gen.gameOverPending";
public static final String KEY_SFX_GEN_Pass = "sound.sfx.gen.pass";
public static final String KEY_SFX_GEN_Select = "sound.sfx.gen.select";
public static final String KEY_SFX_GEN_NewCurrentPlayer = "sound.sfx.gen.newCurrentPlayer";
@@ -37,8 +38,9 @@ public class SoundConfig {
public static final String KEY_SFX_SR_SellShare_NonPresident = "sound.sfx.sr.sellShare.nonPresident";
public static final String KEY_SFX_SR_CompanyFloats = "sound.sfx.sr.companyFloats";
public static final String KEY_SFX_OR_RotateTile = "sound.sfx.or.rotateTile";
- public static final String KEY_SFX_OR_LayTile_track = "sound.sfx.or.layTile.track";
- public static final String KEY_SFX_OR_LayTile_city = "sound.sfx.or.layTile.city";
+ public static final String KEY_SFX_OR_LayTile_Track = "sound.sfx.or.layTile.track";
+ public static final String KEY_SFX_OR_LayTile_City = "sound.sfx.or.layTile.city";
+ public static final String KEY_SFX_OR_LayTile_LastTileLaid = "sound.sfx.or.layTile.lastTileLaid";
public static final String KEY_SFX_OR_LayToken = "sound.sfx.or.layToken";
public static final String KEY_SFX_OR_SetRevenue = "sound.sfx.or.setRevenue";
public static final String KEY_SFX_OR_Decision_Payout = "sound.sfx.or.decision.payout";
diff --git a/rails/sound/SoundEventInterpreter.java b/rails/sound/SoundEventInterpreter.java
index 48a8df2..889ade6 100644
--- a/rails/sound/SoundEventInterpreter.java
+++ b/rails/sound/SoundEventInterpreter.java
@@ -105,10 +105,14 @@ public class SoundEventInterpreter {
LayTile lt = (LayTile)action;
if (lt.getLaidTile().getNumStations() == 0) {
//track upgrade
- player.playSFXByConfigKey (SoundConfig.KEY_SFX_OR_LayTile_track);
+ player.playSFXByConfigKey (SoundConfig.KEY_SFX_OR_LayTile_Track);
} else {
//city upgrade
- player.playSFXByConfigKey (SoundConfig.KEY_SFX_OR_LayTile_city);
+ player.playSFXByConfigKey (SoundConfig.KEY_SFX_OR_LayTile_City);
+ }
+ if (lt.getLaidTile().countFreeTiles() == 1) {
+ //last available tile is about to be laid
+ player.playSFXByConfigKey (SoundConfig.KEY_SFX_OR_LayTile_LastTileLaid);
}
} else if (action instanceof LayToken) {
@@ -194,6 +198,26 @@ public class SoundEventInterpreter {
});
}
+ //subscribe to changes to game over pending
+ if (gameManager.getGameOverPendingModel() != null) {
+ gameManager.getGameOverPendingModel().addObserver(
+ new Observer() {
+ private boolean gameOverPending = false;
+ public void update(Observable o, Object arg) {
+ if (o instanceof BooleanState) {
+ BooleanState s = (BooleanState)o;
+ if (!gameOverPending && s.booleanValue()) {
+ if (SoundConfig.isSFXEnabled()) {
+ player.playSFXByConfigKey (
+ SoundConfig.KEY_SFX_GEN_GameOverPending);
+ }
+ }
+ gameOverPending = s.booleanValue();
+ }
+ }
+ });
+ }
+
//subscribe to phase changes
if (gameManager.getPhaseManager() != null) {
gameManager.getPhaseManager().getCurrentPhaseModel().addObserver(
|