//****************************************************************************** // PGNViewFrame.java: // //****************************************************************************** import java.awt.*; import com.ms.dxmedia.*; import GameFrame; import java.io.*; import ChessModel; import java.util.Vector; import Game; public class PGNViewFrame extends Frame { // AWT components for the GUI protected Button m_nextButton = new Button("Next Move"); protected Button m_prevButton = new Button("Prev Move"); protected MenuItem m_fileOpen = new MenuItem("Open..."); protected Label m_moveLabel = new Label("Move 0 of 0"); protected Checkbox m_auto = new Checkbox("AutoPlay"); public CheckboxMenuItem m_fileGame = new CheckboxMenuItem("Show Games"); protected GameFrame m_gameFrame = new GameFrame(this); AutoPlayer m_autoThread = new AutoPlayer(this); // DXM stuff protected ChessCanvas m_canvas = null; protected ChessModel m_model = null; // the current game protected Game m_currentGame = null; // the index of which move we are on in tha game protected int m_curMoveIdx = 0; public static void main(String args[]) { // create an instance of the frame PGNViewFrame frame = new PGNViewFrame(); frame.show(); frame.hide(); frame.resize(frame.insets().left + frame.insets().right + 300, frame.insets().top + frame.insets().bottom + 340); frame.show(); // create and start the DXM animation frame.startme(); if (args.length > 0) frame.OpenFile(args[0]); } public PGNViewFrame() { super ("Chess PGN Viewer"); System.err.println("ARG"); DisableButtons(); System.err.println("ARG"); } public void startme() { System.err.println("ARK"); setBackground(Color.lightGray); setForeground(Color.black); //setup the frame's menubar MenuBar bar = new MenuBar(); Menu fileMenu = new Menu("File"); System.err.println("ARK"); fileMenu.add(m_fileOpen); fileMenu.add(new MenuItem("-")); System.err.println("ARK"); fileMenu.add(m_fileGame); //m_fileGame.setState(false); System.err.println("ARK"); bar.add(fileMenu); setMenuBar(bar); //setup the move buttons GridBagLayout layout = new GridBagLayout(); setLayout(layout); GridBagConstraints gbc = new GridBagConstraints(); System.err.println("ARK"); gbc.weightx = 0; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.ipadx = 10; layout.setConstraints(m_prevButton, gbc); add(m_prevButton); System.err.println("ARK"); layout.setConstraints(m_nextButton, gbc); add(m_nextButton); System.err.println("ARK"); // add an autoPlay checkbox gbc.fill = GridBagConstraints.NONE; gbc.ipadx = 0; gbc.insets = new Insets(0,10,0,0); gbc.anchor = GridBagConstraints.EAST; layout.setConstraints(m_auto,gbc); add(m_auto); //add the label giving move information gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.weightx = 1; gbc.insets = new Insets(0,0,0,10); m_moveLabel.setAlignment(Label.RIGHT); layout.setConstraints(m_moveLabel, gbc); add(m_moveLabel); // add the canvas for displaying the DXM Animation gbc.insets = new Insets(0,0,0,0); gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.NORTHWEST; gbc.weighty = 1; gbc.weightx = 1; System.err.println("ART"); m_model = new ChessModel(); m_canvas = new ChessCanvas(m_model); System.err.println("HM!"); m_canvas.resize(350,300); System.err.println("MPH!"); layout.setConstraints(m_canvas, gbc); add(m_canvas); pack(); m_autoThread.start(); } public boolean handleEvent(Event evt) { switch (evt.id) { // Application shutdown (e.g. user chooses Close from the system menu). case Event.WINDOW_DESTROY: dispose(); System.exit(0); return true; default: return super.handleEvent(evt); } } public boolean action(Event evt, Object what) { boolean result = false; // sychronize with the canvas to make sure all the code we execute here // is completed before the next frame of the animation is generated. synchronized(m_canvas){ // callbacks for the menu items and move buttons. if (evt.target == m_nextButton) { Next(); result = true; } else if (evt.target == m_prevButton) { Prev(); result = true; } else if (evt.target == m_fileGame) { if (m_fileGame.getState()){ m_gameFrame.show(); } else { m_gameFrame.hide(); } result = true; } else if (evt.target == m_fileOpen) { OpenFileGUI(); result = true; } else if (evt.target == m_auto) { // System.err.println("WE GO"); AutoPlay(); result = true; } } return result; } protected void Next() { // synchronize again just in case we're called from outside of action() by // the AutoPlayer synchronized (m_canvas) { // if we're at the end of the game, do nothing if (m_curMoveIdx >= m_currentGame.m_moves.size()) return; if (!m_nextButton.isEnabled()) return; // System.err.println("moving NEXT"); // otherwise animate the next move MoveForward((Move)m_currentGame.m_moves.elementAt(m_curMoveIdx)); m_curMoveIdx++; ResetButtons(); } } protected void Prev() { // if we're at the beginning of the game do nothing if (m_curMoveIdx <= 0) return; // otherwise animate the current move backwards m_curMoveIdx--; MoveBackward((Move)m_currentGame.m_moves.elementAt(m_curMoveIdx)); ResetButtons(); } public void ResetGame() { // reset the game to initial state. For simplicity, we'll just create a new // model and canvas remove(m_canvas); m_model = new ChessModel(); m_canvas = new ChessCanvas(m_model); m_canvas.resize(300,300); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.NORTHWEST; gbc.weighty = 1; gbc.weightx = 1; ((GridBagLayout)getLayout()).setConstraints(m_canvas, gbc); add(m_canvas); pack(); m_curMoveIdx = 0; } void DisableButtons() { // disable the buttons so the user can't push buttons that are not appropriate m_prevButton.disable(); m_nextButton.disable(); m_fileGame.disable(); m_gameFrame.hide(); m_auto.disable(); if (m_auto.getState()){ m_autoThread.suspend(); // System.err.println("Suspended autoplayer via open"); m_auto.setState(false); } } void EnableButtons() { m_auto.enable(); m_fileGame.enable(); } void ResetButtons() { // enable/disable the next & prev move buttons based on if we can move forward or back // also update the move label in the corner m_moveLabel.setText("Move " + (m_curMoveIdx + 1)/2 + " of " + (m_currentGame.m_moves.size()+1)/2); if (m_curMoveIdx > 0) m_prevButton.enable(); else m_prevButton.disable(); if (m_curMoveIdx < m_currentGame.m_moves.size()) m_nextButton.enable(); else m_nextButton.disable(); } // load a new file via a FileOpen dialog void OpenFileGUI() { FileDialog dlg = new FileDialog(this, "Open PGN file...", FileDialog.LOAD); dlg.show(); if (dlg.getFile() != null){ OpenFile(dlg.getFile()); } } // open a filename void OpenFile(String filename) { System.out.println(filename); DisableButtons(); try { // parse the game into a format easy to animate. (Game classes) Parser parser = new Parser(); parser.Reset(); m_gameFrame.SetGames(parser.ParseFile(filename)); } catch (Exception e) { System.out.println("ERROR PARSING GAME!!!"); ResetGame(); m_gameFrame.SetGames(null); return; } ResetGame(); EnableButtons(); ResetButtons(); } void SetGame(Game game) { m_currentGame = game; } // animate a Move structure void MoveForward(Move move) { if (move.result != null) { m_model.m_resultLabel.switchText(move.result); return; } // if we are promoting a piece, tell the model to promote it if (move.promote != -1) m_model.PromotePiece(move.xFrom,move.yFrom, move.promote); // if we cature a piece, tell the model to capture it if (move.xCapture != -1) m_model.CapturePiece(move.xCapture, move.yCapture, move.player); // tell the model to animate the move m_model.MovePiece(move.xFrom, move.yFrom, move.xTo, move.yTo); // if we're castling, tell the model to move the second piece if (move.xFrom2 != -1) m_model.MovePiece(move.xFrom2, move.yFrom2, move.xTo2, move.yTo2); } // Animate a move structure backward. undo a MoveForward. void MoveBackward(Move move) { if (move.result != null) { m_model.m_resultLabel.switchText(null); return; } // unpromote if nessecary if (move.promote != -1) m_model.PromotePiece(move.xTo,move.yTo, Piece.PAWN); // move the piece back m_model.MovePiece(move.xTo, move.yTo, move.xFrom, move.yFrom); // uncastle if (move.xFrom2 != -1) m_model.MovePiece(move.xTo2, move.yTo2, move.xFrom2, move.yFrom2); // revive any captured piece if (move.xCapture != -1) m_model.RevivePiece(move.xCapture, move.yCapture, move.player); } // stuff for Autoplay button protected void AutoPlay() { if (m_auto.getState()) { m_autoThread.resume(); } else { m_autoThread.suspend(); } } } class AutoPlayer extends Thread { protected PGNViewFrame m_frame = null; AutoPlayer (PGNViewFrame frame) { m_frame = frame; } public void run() { suspend(); while (true) { try { m_frame.Next(); Thread.sleep(4000); } catch (InterruptedException e){ // do nothing } } } }