From: <ste...@us...> - 2010-08-14 19:53:49
|
Revision: 1387 http://rails.svn.sourceforge.net/rails/?rev=1387&view=rev Author: stefanfrey Date: 2010-08-14 19:53:42 +0000 (Sat, 14 Aug 2010) Log Message: ----------- Further fixes to the new report window functionality Added user comments Modified Paths: -------------- trunk/18xx/LocalisedText.properties trunk/18xx/rails/game/Game.java trunk/18xx/rails/game/GameManager.java trunk/18xx/rails/game/OperatingRound.java trunk/18xx/rails/game/ReportBuffer.java trunk/18xx/rails/game/move/MoveStack.java trunk/18xx/rails/ui/swing/MessagePanel.java trunk/18xx/rails/ui/swing/ORUIManager.java trunk/18xx/rails/ui/swing/ReportWindowDynamic.java trunk/18xx/rails/util/Util.java Modified: trunk/18xx/LocalisedText.properties =================================================================== --- trunk/18xx/LocalisedText.properties 2010-08-13 16:30:20 UTC (rev 1386) +++ trunk/18xx/LocalisedText.properties 2010-08-14 19:53:42 UTC (rev 1387) @@ -486,8 +486,11 @@ RepayLoans=Repay loan(s) RepayLoan=Repay {0} loan(s) of {1} for {2} REPORT=Report Window -REPORT_MOVE_BACKWARD=<< -REPORT_MOVE_FORWARD=>> +REPORT_MOVE_BACKWARD=< +REPORT_MOVE_FORWARD=> +REPORT_COMMENT=Comment +REPORT_COMMENT_TITLE=Add Comment +REPORT_COMMENT_ASK=Add a comment to the previous action REVENUE=Revenue RevenueCalculation=support for revenue calculation RevenueStations=, Cities = {0}, Towns = {1} Modified: trunk/18xx/rails/game/Game.java =================================================================== --- trunk/18xx/rails/game/Game.java 2010-08-13 16:30:20 UTC (rev 1386) +++ trunk/18xx/rails/game/Game.java 2010-08-14 19:53:42 UTC (rev 1387) @@ -261,18 +261,18 @@ log.debug("Starting to execute loaded actions"); + Object actionObject = null; while (true) { // Single-pass loop. - Object firstActionObject; try { - firstActionObject = ois.readObject(); + actionObject = ois.readObject(); } catch (EOFException e) { // Allow saved file at start of game (with no actions). break; } - if (firstActionObject instanceof List) { + if (actionObject instanceof List) { // Old-style: one List of PossibleActions List<PossibleAction> executedActions = - (List<PossibleAction>) firstActionObject; + (List<PossibleAction>) actionObject; numberOfActions = executedActions.size(); for (PossibleAction action : executedActions) { if (!gameManager.processOnReload(action)) { @@ -281,19 +281,17 @@ break; } } - - } else { + } else if (actionObject instanceof PossibleAction) { // New style: separate PossibleActionsObjects, since Rails 1.3.1 - PossibleAction action = (PossibleAction) firstActionObject; - while (true) { + while (actionObject instanceof PossibleAction) { numberOfActions++; - if (!gameManager.processOnReload(action)) { + if (!gameManager.processOnReload((PossibleAction)actionObject)) { log.error ("Load interrupted"); DisplayBuffer.add(LocalText.getText("LoadInterrupted")); break; } try { - action = (PossibleAction) ois.readObject(); + actionObject = ois.readObject(); } catch (EOFException e) { break; } @@ -301,6 +299,22 @@ } break; } + + // load user comments (is the last + if (actionObject instanceof SortedMap) { + ReportBuffer.setCommentItems((SortedMap<Integer, String>) actionObject); + log.debug("Found sorted map"); + } else { + try { + object = ois.readObject(); + if (object instanceof SortedMap) { + ReportBuffer.setCommentItems((SortedMap<Integer, String>) object); + } + } catch (EOFException e) { + // continue without comments + } + } + ois.close(); game.getGameManager().finishLoading(); Modified: trunk/18xx/rails/game/GameManager.java =================================================================== --- trunk/18xx/rails/game/GameManager.java 2010-08-13 16:30:20 UTC (rev 1386) +++ trunk/18xx/rails/game/GameManager.java 2010-08-14 19:53:42 UTC (rev 1387) @@ -1040,6 +1040,7 @@ for (PossibleAction action : executedActions) { oos.writeObject(action); } + oos.writeObject(ReportBuffer.getCommentItems()); oos.close(); result = true; Modified: trunk/18xx/rails/game/OperatingRound.java =================================================================== --- trunk/18xx/rails/game/OperatingRound.java 2010-08-13 16:30:20 UTC (rev 1386) +++ trunk/18xx/rails/game/OperatingRound.java 2010-08-14 19:53:42 UTC (rev 1387) @@ -803,6 +803,10 @@ moveStack.start(true); + ReportBuffer.add(LocalText.getText("CompanyRevenue", + action.getCompanyName(), + Bank.format(action.getActualRevenue()))); + int remainingAmount = checkForDeductions (action); if (remainingAmount < 0) { // A share selling round will be run to raise cash to pay debts @@ -890,9 +894,6 @@ action.setRevenueAllocation(SetDividend.WITHHOLD); } - ReportBuffer.add(LocalText.getText("CompanyRevenue", - action.getCompanyName(), - Bank.format(amount))); if (amount == 0 && operatingCompany.getNumberOfTrains() == 0) { DisplayBuffer.add(LocalText.getText("RevenueWithNoTrains", operatingCompany.getName(), Modified: trunk/18xx/rails/game/ReportBuffer.java =================================================================== --- trunk/18xx/rails/game/ReportBuffer.java 2010-08-13 16:30:20 UTC (rev 1386) +++ trunk/18xx/rails/game/ReportBuffer.java 2010-08-14 19:53:42 UTC (rev 1387) @@ -27,13 +27,12 @@ /** defines the collection of data that is stored in the report buffer */ private class ReportItem { private List<String> messages = new ArrayList<String>(); - private int index = 0; + private int index = -1; private Player player = null; private RoundI round = null; private void addMessage(String message) { - // ignore undos and redos - messages.add(message); + messages.add(Util.convertToHtml(message)); } private String getMessages() { @@ -44,17 +43,38 @@ return s.toString(); } - private String toHtml() { + /** + * converts messages to html string + * @param activeMessage if true, adds indicator and highlighting for active message + */ + + private String toHtml(boolean activeMessage) { + if (messages.isEmpty()) { + if (activeMessage) { + return ("<span bgcolor=Yellow>" + ACTIVE_MESSAGE_INDICATOR + "</span>" + + NEWLINE_STRING); + } else { + return null; + } + } + StringBuffer s = new StringBuffer(); boolean init = true; for (String message:messages) { if (init) { + if (activeMessage) { + s.append("<span bgcolor=Yellow>" + ACTIVE_MESSAGE_INDICATOR) ; + } s.append("<a href=http://rails:" + index + ">"); s.append(message); - s.append("</a><br> "); // is the linefeed character to induce line feed on copy & paste + s.append("</a>"); + if (activeMessage) { + s.append("</span>"); + } + s.append(NEWLINE_STRING); init = false; } else { - s.append(message + "<br> "); // see above + s.append(message + NEWLINE_STRING); // see above } } return s.toString(); @@ -70,8 +90,25 @@ } } + /* + * All variables below are required for the dynamic preprot window + */ + /** Indicator string to find the active message position in the parsed html document */ + public static final String ACTIVE_MESSAGE_INDICATOR = "(**)"; - /** + /** Newline string + * is the linefeed character to induce line feed on copy & paste + */ + private static final String NEWLINE_STRING = "<br> "; + + /** Archive stack of messages, the integer index corresponds with the moveset items */ + private SortedMap<Integer, ReportItem> reportItems = new TreeMap<Integer, ReportItem>(); + + /** Archive stack of user supplied comments, integer index corresponds with moveset items */ + private SortedMap<Integer, String> commentItems = new TreeMap<Integer, String>(); + + /* + * All variables below are required for the static report window * A stack for displaying messages in the Log Window. Such messages are * intended to record the progress of the rails.game and can be used as a * rails.game report. @@ -81,11 +118,6 @@ /** Another stack for messages that must "wait" for other messages */ private List<String> waitQueue = new ArrayList<String> (); - /** Archive stack, the integer index corresponds with the moveset items */ - private SortedMap<Integer, ReportItem> reportItems = new TreeMap<Integer, ReportItem>(); - /** Indicator string to find the active message position in the parsed html document */ - public static final String ACTIVE_MESSAGE_INDICATOR = "(**)"; - private String reportPathname = null; private PrintWriter report = null; @@ -108,7 +140,7 @@ public ReportBuffer() { - reportItems.put(0, new ReportItem()); + reportItems.put(-1, new ReportItem()); if (!initialQueue.isEmpty()) { for (String s : initialQueue) { addMessage(s, -1); // start of the game @@ -129,7 +161,8 @@ private void addMessage(String message, int moveStackIndex) { if (message != null) { if (message.equals("")) { - message = "---"; // workaround for testing + return; + // message = "---"; // workaround for testing } // legacy report queue reportQueue.add(message); @@ -191,20 +224,25 @@ } } + private void clearFutureItems(int index) { + // delete future items + Set<Integer> deleteIndices = new HashSet<Integer> + (reportItems.tailMap(index + 1).keySet()); + for (Integer i:deleteIndices) { + reportItems.remove(i); + commentItems.remove(i); + } + } + private void addReportItem(int index, Player player, RoundI round) { ReportItem newItem = new ReportItem(); newItem.index = index; newItem.player = player; newItem.round = round; reportItems.put(index, newItem); - Set<Integer> deleteIndices = new HashSet<Integer> - (reportItems.tailMap(index + 1).keySet()); - for (Integer i:deleteIndices) { - reportItems.remove(i); - } } - - /** Movestack calls the report item to update */ + + /** Creates a new report item */ public static void createNewReportItem(int index) { // check availablity GameManagerI gm = GameManager.getInstance(); @@ -219,23 +257,33 @@ Player player = gm.getCurrentPlayer(); RoundI round = gm.getCurrentRound(); instance.addReportItem(index, player, round); + instance.clearFutureItems(index); } public static String getReportItems() { - int index = GameManager.getInstance().getMoveStack().getIndex(); + // activeIndex is the index one before the current index for the next action + int activeIndex = GameManager.getInstance().getMoveStack().getCurrentIndex(); ReportBuffer instance = getInstance(); StringBuffer s = new StringBuffer(); s.append("<html>"); - for (ReportItem item:instance.reportItems.values()) { - if (item.index == index-1) { - s.append("<p bgcolor=Yellow>" + ACTIVE_MESSAGE_INDICATOR) ; + for (Integer index:instance.reportItems.keySet()) { + ReportItem item = instance.reportItems.get(index); + String text = item.toHtml(index == activeIndex); + String comment = instance.commentItems.get(index); + if (text == null && comment == null) continue; + s.append("<p>"); + // comments first + if (comment != null) { + s.append("<span style='color:green;font-size:80%;font-style:italic;'>"); + s.append(item.player.getName() + " says: ' "); + s.append(comment + "'" + NEWLINE_STRING); + s.append("</span>"); } - s.append(item.toHtml()); - if (item.index == (index-1)) { - s.append("</p><"); - } + // text afterwards + if (text != null) s.append(text); + s.append("</p>"); } s.append("</html>"); @@ -273,10 +321,69 @@ instance.reportQueue.add(message); return; } - int moveStackIndex = gm.getMoveStack().getIndex(); + int moveStackIndex = gm.getMoveStack().getCurrentIndex(); instance.addMessage(message, moveStackIndex); } } + + /** Add a user comment to the report window */ + public static void addComment(String comment) { + GameManagerI gm = GameManager.getInstance(); + ReportBuffer instance = null; + if (gm != null) { + instance = gm.getReportBuffer(); + } + if (instance != null) { + int index = gm.getMoveStack().getCurrentIndex(); // add one index before (active) + instance.commentItems.put(index, comment); + log.debug("Added comment = " + comment + " at index = " + index); + } + } + + /** Retrieves the current user comment */ + public static String getComment() { + GameManagerI gm = GameManager.getInstance(); + ReportBuffer instance = null; + if (gm != null) { + instance = gm.getReportBuffer(); + } + String comment = null; + if (instance != null) { + int index = gm.getMoveStack().getCurrentIndex(); + comment = instance.commentItems.get(index); + } + return comment; + } + + /** Retrieves all user comments */ + public static SortedMap<Integer, String> getCommentItems() { + GameManagerI gm = GameManager.getInstance(); + ReportBuffer instance = null; + if (gm != null) { + instance = gm.getReportBuffer(); + } + if (instance != null) { + return instance.commentItems; + } else { + // return empty map + return new TreeMap<Integer, String>(); + } + } + + /** sets user comments */ + public static void setCommentItems(SortedMap<Integer, String> commentItems) { + GameManagerI gm = GameManager.getInstance(); + ReportBuffer instance = null; + if (gm != null) { + instance = gm.getReportBuffer(); + } + if (instance != null) { + instance.commentItems = commentItems; + } + } + + + /** return the current buffer as list */ public static List<String> getAsList() { Modified: trunk/18xx/rails/game/move/MoveStack.java =================================================================== --- trunk/18xx/rails/game/move/MoveStack.java 2010-08-13 16:30:20 UTC (rev 1386) +++ trunk/18xx/rails/game/move/MoveStack.java 2010-08-14 19:53:42 UTC (rev 1387) @@ -48,6 +48,7 @@ while (lastIndex < moveStack.size() - 1) { moveStack.remove(moveStack.size() - 1); } + ReportBuffer.createNewReportItem(getCurrentIndex()); return currentMoveSet; } else { log.warn("MoveSet is already open"); @@ -68,7 +69,6 @@ moveStack.add(currentMoveSet); lastIndex++; currentMoveSet = null; - ReportBuffer.createNewReportItem(this.getIndex()); return true; } } @@ -117,6 +117,7 @@ undoAction = moveStack.get(lastIndex--); undoAction.unexecute(); } while (undoAction.isLinkedToPreviousMove()); + return true; } else { log.error("Invalid undo: index=" + lastIndex + " size=" @@ -165,6 +166,18 @@ return lastIndex + 1; } + /** + * the current index is the one of either the open moveset or + * if none is open of the latest added + */ + public int getCurrentIndex() { + if (isOpen()) { + return lastIndex + 1; + } else { + return lastIndex; + } + } + /** * undo/redo to a given moveStack index */ Modified: trunk/18xx/rails/ui/swing/MessagePanel.java =================================================================== --- trunk/18xx/rails/ui/swing/MessagePanel.java 2010-08-13 16:30:20 UTC (rev 1386) +++ trunk/18xx/rails/ui/swing/MessagePanel.java 2010-08-14 19:53:42 UTC (rev 1387) @@ -62,22 +62,21 @@ messageText.append("</span>"); } if (showDetails) { - messageText.append("<span style='color:blue'>"); + messageText.append("<span style='color:blue; font-size:80%'>"); for (String detail:currentDetails) { messageText.append(detail); } messageText.append("</span>"); } else if (currentDetails.size() != 0) { - messageText.append("<span style='color:blue'>"); + messageText.append("<span style='color:blue; font-size:80%'>"); messageText.append("<BR> Click for more details"); messageText.append("</span>"); } - if (currentMessage != null) { - String text = messageText.toString(); - int lines = text.split("<[Bb][Rr]>").length + 1; - setLines(lines); - message.setText("<html><center>" + text + "</center></html>"); - } + // display + String text = messageText.toString(); + int lines = text.split("<[Bb][Rr]>").length + 1; + setLines(lines); + message.setText("<html><center>" + text + "</center></html>"); } Modified: trunk/18xx/rails/ui/swing/ORUIManager.java =================================================================== --- trunk/18xx/rails/ui/swing/ORUIManager.java 2010-08-13 16:30:20 UTC (rev 1386) +++ trunk/18xx/rails/ui/swing/ORUIManager.java 2010-08-14 19:53:42 UTC (rev 1387) @@ -1419,6 +1419,8 @@ mapRelatedActions.clear(); orPanel.resetActions(); + + messagePanel.setMessage(null); if (actionToComplete != null) { log.debug("ExecutedAction: " + actionToComplete); Modified: trunk/18xx/rails/ui/swing/ReportWindowDynamic.java =================================================================== --- trunk/18xx/rails/ui/swing/ReportWindowDynamic.java 2010-08-13 16:30:20 UTC (rev 1386) +++ trunk/18xx/rails/ui/swing/ReportWindowDynamic.java 2010-08-14 19:53:42 UTC (rev 1387) @@ -7,7 +7,9 @@ import java.net.URL; import java.util.List; +import javax.swing.JButton; import javax.swing.JEditorPane; +import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.UIManager; @@ -40,6 +42,7 @@ private JPanel buttonPanel; private ActionButton forwardButton; private ActionButton backwardButton; + private JButton commentButton; protected static Logger log = Logger.getLogger(ReportWindowDynamic.class.getPackage().getName()); @@ -80,6 +83,29 @@ forwardButton.addActionListener(this); buttonPanel.add(forwardButton); + commentButton = new JButton(LocalText.getText("REPORT_COMMENT")); + commentButton.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + String newComment = (String)JOptionPane.showInputDialog( + ReportWindowDynamic.this, + LocalText.getText("REPORT_COMMENT_ASK"), + LocalText.getText("REPORT_COMMENT_TITLE"), + JOptionPane.PLAIN_MESSAGE, + null, + null, + ReportBuffer.getComment() + ); + if (newComment != null) { + ReportBuffer.addComment(newComment); + updateLog(); + scrollDown(); + } + } + } + ); + buttonPanel.add(commentButton); + super.init(); } Modified: trunk/18xx/rails/util/Util.java =================================================================== --- trunk/18xx/rails/util/Util.java 2010-08-13 16:30:20 UTC (rev 1386) +++ trunk/18xx/rails/util/Util.java 2010-08-14 19:53:42 UTC (rev 1387) @@ -79,7 +79,19 @@ } } + /** + * Convert java string to html string + * Transformations: + * - Converts \n to <br> + */ + public static String convertToHtml(String javaString) { + return javaString.replace("\n", "<br>"); + } + + + + /** * Safely move a list of objects from one holder to another, avoiding * ConcurrentModificationExceptions. * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |