Here is a patch for cancelling the odds calculator. (http://sourceforge.net/tracker/index.php?func=detail&aid=1910223&group_id=44492&atid=439737)

Sean recommended I change to a volatile variable instead of interuppting the thread. I'll do that when I get a chance, but if possible could that patch be applied to limit any regressions with other code changes.

Index: src/games/strategy/engine/framework/ui/background/WaitDialog.java
===================================================================
---
src/games/strategy/engine/framework/ui/background/WaitDialog.java (revision
2293)
+++
src/games/strategy/engine/framework/ui/background/WaitDialog.java (working
copy)
@@ -2,21 +2,32 @@

import java.awt.*;

+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
import javax.swing.*;

-public class WaitDialog extends JDialog
-{
+public class WaitDialog extends JDialog {

- public WaitDialog(Component parent, String waitMessage)
- {
- super(JOptionPane.getFrameForComponent(parent), "Please Wait" ,
true);
+ public WaitDialog(Component parent, String waitMessage) {
+ super(JOptionPane.getFrameForComponent(parent), "Please Wait",
true);
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
WaitPanel panel = new WaitPanel(waitMessage);
setLayout(new BorderLayout());
add(panel, BorderLayout.CENTER);
-
}
-
-
-
+
+ public WaitDialog(Component parent, String waitMessage, final
Runnable cancel) {
+ this(parent, waitMessage);
+ Button cancelButton = new Button("Cancel");
+ add(cancelButton);
+
+ cancelButton.addActionListener(
+ new ActionListener() {
+
+ public void actionPerformed(ActionEvent e) {
+ cancel.run();
+ }
+ });
+
+ }
}
Index: src/games/strategy/triplea/oddsCalculator/ta/OddsCalculator.java
===================================================================
---
src/games/strategy/triplea/oddsCalculator/ta/OddsCalculator.java (revision
2293)
+++
src/games/strategy/triplea/oddsCalculator/ta/OddsCalculator.java (working
copy)
@@ -91,8 +91,9 @@
long start = System.currentTimeMillis();
AggregateResults rVal = new AggregateResults(count);
BattleTracker battleTracker = new BattleTracker();
-
- for(int i =0; i < count; i++)
+
+ // The dialog may be cancelled which causes the running thread to
be markes as interruppted.
+ for(int i =0; i < count && !Thread.interrupted(); i++)
{
final CompositeChange allChanges = new CompositeChange();
DummyDelegateBridge bridge1 = new
DummyDelegateBridge(m_attacker, m_data, allChanges,
m_keepOneAttackingLandUnit);
Index:
src/games/strategy/triplea/oddsCalculator/ta/OddsCalculatorPanel.java
===================================================================
---
src/games/strategy/triplea/oddsCalculator/ta/OddsCalculatorPanel.java (revision
2293)
+++
src/games/strategy/triplea/oddsCalculator/ta/OddsCalculatorPanel.java (working
copy)
@@ -249,24 +249,40 @@
});

}
-
+ // Holds a Thread in a final object so we can pass it to an inner
thread.
+ class ThreadPointer
+ {
+ public Thread thread = null;
+ }
+
private void updateStats()
{
- final WaitDialog dialog = new WaitDialog(this, "Calculating
Odds");
+ // Hack to work with the inner threads.
+ final ThreadPointer threadPointer = new ThreadPointer();
+
+ // Create a canceable wait dialog.
+ final WaitDialog dialog = new WaitDialog(this, "Calculating
Odds",
+ new Runnable() {
+ public void run() {
+ if ( threadPointer.thread != null ) {
+ threadPointer.thread.interrupt();
+ }
+
+ }
+ });
dialog.pack();
dialog.setLocationRelativeTo(this);
-
+
final AtomicReference<AggregateResults> results = new
AtomicReference<AggregateResults>();
-
- new Thread(new Runnable()
- {
-
+
+ threadPointer.thread = new Thread(new Runnable() {
+
public void run()
{
try
{
OddsCalculator calculator = new OddsCalculator();
-
+
// find a territory to fight in
Territory location = null;
for (Territory t : m_data.getMap())
@@ -279,7 +295,7 @@
}
if(location == null)
throw new IllegalStateException("No territory
found that is land:" + isLand());
-
+
List<Unit> defending =
m_defendingUnitsPanel.getUnits();
List<Unit> attacking =
m_attackingUnitsPanel.getUnits();
List<Unit> bombarding = new ArrayList<Unit>();
@@ -288,33 +304,35 @@
bombarding = Match.getMatches(attacking,
Matches.unitCanBombard(getAttacker()));
attacking.removeAll(bombarding);
}
-
+
if(m_landBattle.isSelected() &&
m_keepOneAttackingLandUnitCombo.isSelected())
calculator.setKeepOneAttackingLandUnit(true);
else
calculator.setKeepOneAttackingLandUnit(false);
-
+
results.set(calculator.calculate(m_data,
getAttacker(), getDefender(), location, attacking, defending, bombarding,
m_numRuns.getValue()));
-
+
}
finally
{
SwingUtilities.invokeLater(new Runnable()
{
-
+
public void run()
{
dialog.setVisible(false);
dialog.dispose();
}
-
+
});
-
+
}
-
+
}
-
- }, "Odds calc thread").start();
+ }, "Odds calc thread");
+
+ // Actually start thread.
+ threadPointer.thread.start();

if(results.get() == null)
dialog.setVisible(true);