import java.awt.*; import java.awt.event.*; import java.io.*; import javax.swing.*; import javax.swing.border.*; import javax.swing.filechooser.FileNameExtensionFilter; /** * IgoDialog クラスは、囲碁Viewerのメインダイアログを提供します。 */ public class IgoDialog implements IgoView,ActionListener{ private static final int FONTSIZE=29; private static final int MENUBARFONTSIZE=16; private static final int BUTTONFONTSIZE=15; private static final int AUTOPLAYFONTSIZE=12; private static final int MODEFONTSIZE=15; private static final int PLAYERFONTSIZE=17; private static final int PLAYERLABELFONTSIZE=20; private static final int FRAMESIZEX=840; private static final int FRAMESIZEY=700; private static final int BOARDSIZEX=630; private static final int BOARDSIZEY=630; private static final int BUTTONPANELSIZEX=200; private static final int BUTTONPANELSIZEY=144; private static final int PLAYERPANELSIZEX=200; private static final int PLAYERPANELSIZEY=60; private static final Font FONT_MENUBAR=new Font("MS UI Gothic",Font.PLAIN,MENUBARFONTSIZE); private static final Font FONT_MODE=new Font("MS UI Gothic",Font.BOLD,MODEFONTSIZE); private static final Font FONT_BUTTON=new Font("MS UI Gothic",Font.PLAIN,BUTTONFONTSIZE); private static final Font FONT_EXAM=new Font("MS UI Gothic",Font.BOLD,BUTTONFONTSIZE); private static final Font FONT_AUTOPLAY=new Font("MS UI Gothic",Font.BOLD,AUTOPLAYFONTSIZE); private static final Font FONT_PLAYER=new Font("MS UI Gothic",Font.BOLD,PLAYERFONTSIZE); private static final Font FONT_PLAYERLABEL=new Font("MS UI Gothic",Font.PLAIN,PLAYERLABELFONTSIZE); private static final Color color1=new Color(230,230,250); private IgoModel controller; private JFrame jf; private JMenuBar jmb; private JMenu jmFile; private JMenuItem jmiOpen; private JMenuItem jmiRecord; private JMenuItem jmiSave; private JMenuItem jmiSaveAs; private JMenuItem jmiClose; private JMenuItem jmiExit; private JMenu jmEdit; private JMenuItem jmiStartEdit; private JMenuItem jmiOpenGameInfo; private JMenu jmView; private JMenu jmBoard; private JMenuItem jmiGraphicBoard; private JMenuItem jmiImageBoard; private JMenuItem jmiTextBoard; private IgoPanel jp_ban; private IgoGraphicPanel graphicBan; private IgoImagePanel imageBan; private IgoTextPanel textBan; private JPanel jp_button; private JPanel jpBlack; private JLabel jlBlackPlayer; private JLabel jlBlackAgehama; private JPanel jpWhite; private JLabel jlWhitePlayer; private JLabel jlWhiteAgehama; private JButton bt_back; private JButton bt_forward; private JButton bt_back5; private JButton bt_forward5; private JButton bt_backAll; private JButton bt_forwardAll; private JButton bt_pass; private JButton bt_examine; private JLabel jlMode; private JLabel jlNumOfMoves; private JLabel jlDummy; private JButton bt_autoPlay; private JButton bt_playSpeed; private File lastDir; private String eventName,gameName; /** * 空のインスタンスを生成します。 */ IgoDialog(){ eventName=new String(""); gameName=new String(""); } /** * インスタンスを初期化します。 * @param controller コントローラー */ public void initialize(IgoModel controller){ try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); }catch(Exception exc){ System.err.println("Error loading L&F: " + exc); } this.controller=controller; lastDir=new File("."); initializePanel(); initializeContentPane(); } private void initializePanel(){ bt_back=new JButton("<"); bt_forward=new JButton(">"); bt_back5=new JButton("<<"); bt_forward5=new JButton(">>"); bt_backAll=new JButton("|<"); bt_forwardAll=new JButton(">|"); bt_pass=new JButton("パス"); bt_examine=new JButton("検討"); bt_autoPlay=new JButton("自動再生"); bt_playSpeed=new JButton("再生速度"); jlMode=new JLabel("",JLabel.CENTER); jlMode.setOpaque(true); jlMode.setBackground(new Color(238,238,238)); jlMode.setBorder(new EtchedBorder(EtchedBorder.LOWERED)); jlNumOfMoves=new JLabel("",JLabel.CENTER); jlNumOfMoves.setOpaque(true); jlNumOfMoves.setBackground(new Color(238,238,238)); jlNumOfMoves.setBorder(new EtchedBorder(EtchedBorder.LOWERED)); jlDummy=new JLabel("",JLabel.CENTER); jlDummy.setOpaque(false); bt_back.addActionListener(this); bt_forward.addActionListener(this); bt_back5.addActionListener(this); bt_forward5.addActionListener(this); bt_backAll.addActionListener(this); bt_forwardAll.addActionListener(this); bt_pass.addActionListener(this); bt_examine.addActionListener(this); bt_autoPlay.addActionListener(this); bt_playSpeed.addActionListener(this); bt_back.setFont(FONT_BUTTON); bt_forward.setFont(FONT_BUTTON); bt_back5.setFont(FONT_BUTTON); bt_forward5.setFont(FONT_BUTTON); bt_backAll.setFont(FONT_BUTTON); bt_forwardAll.setFont(FONT_BUTTON); bt_pass.setFont(FONT_BUTTON); bt_examine.setFont(FONT_BUTTON); jlMode.setFont(FONT_MODE); jlNumOfMoves.setFont(FONT_MODE); bt_autoPlay.setFont(FONT_BUTTON); bt_playSpeed.setFont(FONT_BUTTON); jp_button=new JPanel(); jp_button.setOpaque(false); jp_button.setSize(BUTTONPANELSIZEX,BUTTONPANELSIZEY); jp_button.setLocation(BOARDSIZEX,PLAYERPANELSIZEY*2); jp_button.setLayout(new GridLayout(6,2)); jp_button.add(bt_back); jp_button.add(bt_forward); jp_button.add(bt_back5); jp_button.add(bt_forward5); jp_button.add(bt_backAll); jp_button.add(bt_forwardAll); jp_button.add(bt_pass); jp_button.add(bt_autoPlay); jp_button.add(bt_examine); jp_button.add(bt_playSpeed); jp_button.add(jlMode); jp_button.add(jlNumOfMoves); // jp_button.add(jlDummy); graphicBan=new IgoGraphicPanel(); imageBan=new IgoImagePanel(); textBan=new IgoTextPanel(); jp_ban=graphicBan; setupBoard(); jlBlackPlayer=new JLabel("●"); jlBlackPlayer.setFont(FONT_PLAYER); jlBlackPlayer.setOpaque(false); jlBlackAgehama=new JLabel(""); jlBlackAgehama.setFont(FONT_PLAYER); jlBlackAgehama.setOpaque(true); jlBlackAgehama.setBackground(Color.white); jlBlackAgehama.setHorizontalAlignment(JLabel.CENTER); jpBlack=new JPanel(); jpBlack.setOpaque(false); jpBlack.setLayout(new GridLayout(2,1)); jpBlack.setSize(PLAYERPANELSIZEX,PLAYERPANELSIZEY); jpBlack.setLocation(BOARDSIZEX,0); jpBlack.add(jlBlackPlayer); jpBlack.add(jlBlackAgehama); jlWhitePlayer=new JLabel("○"); jlWhitePlayer.setFont(FONT_PLAYER); jlWhitePlayer.setOpaque(false); jlWhiteAgehama=new JLabel(""); jlWhiteAgehama.setFont(FONT_PLAYER); jlWhiteAgehama.setOpaque(true); jlWhiteAgehama.setBackground(Color.white); jlWhiteAgehama.setHorizontalAlignment(JLabel.CENTER); jpWhite=new JPanel(); jpWhite.setOpaque(false); jpWhite.setLayout(new GridLayout(2,1)); jpWhite.setSize(PLAYERPANELSIZEX,PLAYERPANELSIZEY); jpWhite.setLocation(BOARDSIZEX,PLAYERPANELSIZEY); jpWhite.add(jlWhitePlayer); jpWhite.add(jlWhiteAgehama); } private void setupBoard(){ jp_ban.setSize(BOARDSIZEX,BOARDSIZEY); jp_ban.setLocation(0,0); jp_ban.setIgoGameController(controller); } private void initializeContentPane(){ jf=new JFrame("囲碁Viewer"); jf.setSize(FRAMESIZEX,FRAMESIZEY); jf.setLocation(200,30); jf.getContentPane().setBackground(new Color(230,230,250)); jmb=new JMenuBar(); jmFile=new JMenu("ファイル"); jmFile.setFont(FONT_MENUBAR); jmiOpen=new JMenuItem("開く"); jmiOpen.setFont(FONT_MENUBAR); jmiRecord=new JMenuItem("新規作成"); jmiRecord.setFont(FONT_MENUBAR); jmiSave=new JMenuItem("上書き保存"); jmiSave.setFont(FONT_MENUBAR); jmiSave.setEnabled(false); jmiSaveAs=new JMenuItem("名前を付けて保存"); jmiSaveAs.setFont(FONT_MENUBAR); jmiSaveAs.setEnabled(false); jmiClose=new JMenuItem("閉じる"); jmiClose.setFont(FONT_MENUBAR); jmiClose.setEnabled(false); jmiExit=new JMenuItem("終了"); jmiExit.setFont(FONT_MENUBAR); jmb.add(jmFile); jmFile.add(jmiOpen); jmFile.add(jmiRecord); jmFile.addSeparator(); jmFile.add(jmiSave); jmFile.add(jmiSaveAs); jmFile.addSeparator(); jmFile.add(jmiClose); jmFile.add(jmiExit); jmEdit=new JMenu("編集"); jmEdit.setFont(FONT_MENUBAR); jmiStartEdit=new JMenuItem("現在の棋譜を編集"); jmiStartEdit.setFont(FONT_MENUBAR); jmiStartEdit.setEnabled(false); jmiOpenGameInfo=new JMenuItem("対局情報"); jmiOpenGameInfo.setFont(FONT_MENUBAR); jmiOpenGameInfo.setEnabled(false); jmb.add(jmEdit); jmEdit.add(jmiOpenGameInfo); jmEdit.add(jmiStartEdit); jmView=new JMenu("表示"); jmView.setFont(FONT_MENUBAR); jmBoard=new JMenu("碁盤 "); jmBoard.setFont(FONT_MENUBAR); jmiGraphicBoard=new JMenuItem("グラフィック碁盤"); jmiGraphicBoard.setFont(FONT_MENUBAR); jmiGraphicBoard.setEnabled(true); jmiImageBoard=new JMenuItem("イメージ碁盤"); jmiImageBoard.setFont(FONT_MENUBAR); jmiImageBoard.setEnabled(true); jmiTextBoard=new JMenuItem("テキスト碁盤"); jmiTextBoard.setFont(FONT_MENUBAR); jmiTextBoard.setEnabled(true); jmb.add(jmView); jmView.add(jmBoard); jmBoard.add(jmiGraphicBoard); jmBoard.add(jmiImageBoard); jmBoard.add(jmiTextBoard); jmiOpen.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ controller.open(); } }); jmiRecord.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ controller.record(); } }); jmiSave.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ controller.save(); } }); jmiSaveAs.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ controller.saveAs(); } }); jmiExit.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ controller.exit(); } }); jmiStartEdit.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ controller.startEdit(); } }); jmiClose.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ controller.close(); } }); jmiOpenGameInfo.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ controller.displayGameInfo(); } }); jmiGraphicBoard.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ changeBoard(IgoPanel.GRAPHIC_BOARD); } }); jmiImageBoard.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ changeBoard(IgoPanel.IMAGE_BOARD); } }); jmiTextBoard.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ changeBoard(IgoPanel.TEXT_BOARD); } }); jf.getRootPane().setJMenuBar(jmb); jf.getContentPane().setLayout(null); jf.getContentPane().add(jp_ban); jf.getContentPane().add(jp_button); jf.getContentPane().add(jpBlack); jf.getContentPane().add(jpWhite); jf.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); jf.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ controller.exit(); } }); } /** * フレームを取得します。 * @return フレーム */ public JFrame getFrame(){ return jf; } /** * 指定されたコントローラーに変更します。 * @param controller コントローラー */ public void changeController(IgoModel controller){ this.controller=controller; jp_ban.setIgoGameController(controller); } /** * 指定されたパラメータに従って、ビューを更新します。 * @param mode 動作モード * @param isExam 検討モードかどうかの真偽値 * @param intBoard 盤面データ * @param gameInfo 対局情報 * @param numOfMoves 手数 */ public void updateView(Mode mode,boolean isExam,IntBoard intBoard, GameInformation gameInfo,int numOfMoves){ jlBlackPlayer.setText("● " + gameInfo.getBlackPlayer() + " " + gameInfo.getBlackRank()); jlBlackAgehama.setText(Integer.toString(intBoard.getBhama())); jlWhitePlayer.setText("○ " + gameInfo.getWhitePlayer() + " " + gameInfo.getWhiteRank()); jlWhiteAgehama.setText(Integer.toString(intBoard.getWhama())); jf.setTitle("囲碁Viewer " + gameInfo.getEvent() + gameInfo.getGameName()); jp_ban.update(intBoard); eventName=gameInfo.getEvent(); gameName=gameInfo.getGameName(); if(isExam){ bt_examine.setForeground(Color.red); bt_examine.setFont(FONT_EXAM); bt_examine.setText("検討中"); }else{ bt_examine.setForeground(Color.black); bt_examine.setFont(FONT_BUTTON); bt_examine.setText("検討"); } int dispNum=numOfMoves + 1; switch(mode.getMode()){ case Mode.MODE_INIT: jlMode.setText(""); jlMode.setBackground(new Color(238,238,238)); jmiOpen.setEnabled(true); jmiRecord.setEnabled(true); jmiStartEdit.setEnabled(false); jmiSave.setEnabled(false); jmiSaveAs.setEnabled(false); jmiClose.setEnabled(false); jmiOpenGameInfo.setEnabled(false); jlNumOfMoves.setText(""); break; case Mode.MODE_PLAY: jlMode.setText("再生中"); jlMode.setBackground(new Color(153,255,255)); jmiOpen.setEnabled(true); jmiRecord.setEnabled(true); jmiSave.setEnabled(false); jmiSaveAs.setEnabled(false); jmiClose.setEnabled(true); jmiOpenGameInfo.setEnabled(true); jlNumOfMoves.setText(dispNum + "手"); if(isExam){ jmiStartEdit.setEnabled(false); }else{ jmiStartEdit.setEnabled(true); } break; case Mode.MODE_NEW: jlMode.setText("新規作成中"); jlMode.setBackground(new Color(255,182,193)); jmiOpen.setEnabled(false); jmiRecord.setEnabled(false); jmiSave.setEnabled(false); jmiSaveAs.setEnabled(true); jmiStartEdit.setEnabled(false); jmiClose.setEnabled(true); jmiOpenGameInfo.setEnabled(true); jlNumOfMoves.setText(dispNum + "手"); break; case Mode.MODE_MOD: jlMode.setText("更新中"); jlMode.setBackground(new Color(255,182,193)); jmiOpen.setEnabled(false); jmiRecord.setEnabled(false); jmiSave.setEnabled(true); jmiSaveAs.setEnabled(true); jmiStartEdit.setEnabled(false); jmiClose.setEnabled(true); jmiOpenGameInfo.setEnabled(true); jlNumOfMoves.setText(dispNum + "手"); break; } } /** * 指定されたパラメータに従って、ビューを更新します。 * @param mode 動作モード * @param isExam 検討モードかどうかの真偽値 * @param intBoard 盤面データ * @param gameInfo 対局情報 * @param numOfMoves 手数 * @param isAutoPlay 自動再生かどうかの真偽値 */ public void updateView(Mode mode,boolean isExam,IntBoard intBoard, GameInformation gameInfo,int numOfMoves,boolean isAutoPlay){ updateView(mode,isExam,intBoard,gameInfo,numOfMoves); if(isAutoPlay){ bt_autoPlay.setForeground(Color.red); bt_autoPlay.setFont(FONT_AUTOPLAY); bt_autoPlay.setText("自動再生中"); }else{ bt_autoPlay.setForeground(Color.black); bt_autoPlay.setFont(FONT_BUTTON); bt_autoPlay.setText("自動再生"); } } /** * アクションが発生すると呼び出されます。 * 選択されたアクション(ボタン操作等)に従った処理を行います。 */ public void actionPerformed(ActionEvent ae){ if ((JButton)ae.getSource()==bt_back) { controller.back();} if ((JButton)ae.getSource()==bt_forward) { controller.forward();} if ((JButton)ae.getSource()==bt_back5) { controller.back5();} if ((JButton)ae.getSource()==bt_forward5) { controller.forward5();} if ((JButton)ae.getSource()==bt_backAll) { controller.backAll();} if ((JButton)ae.getSource()==bt_forwardAll) { controller.forwardAll();} if ((JButton)ae.getSource()==bt_pass) { controller.pass();} if ((JButton)ae.getSource()==bt_autoPlay) { controller.autoPlay();} if ((JButton)ae.getSource()==bt_playSpeed) { controller.updateInterval();} if ((JButton)ae.getSource()==bt_examine) { controller.examine();} } /** * 「閉じる」「終了」の操作確認をするダイアログを表示します。 * @return 確認のダイアログで選択された結果コードを表す int */ public int askClosedOperation(){ ClosedOperationDialog dialog=new ClosedOperationDialog(); dialog.setLocation(300,200); return dialog.showClosedDialog(jf,"囲碁Viewer"); } /** * 「開く」のダイアログを表示します。 * @return ファイル名(フルパス指定)を表す String */ public String showOpenDialog(){ String fileName=new String(""); JFileChooser jfc=new JFileChooser(lastDir); FileNameExtensionFilter filter = new FileNameExtensionFilter("SGF Text", "sgf"); jfc.setFileFilter(filter); if (jfc.showOpenDialog(jf)==JFileChooser.APPROVE_OPTION){ //「開く」ボタン押下時 File file=jfc.getSelectedFile(); fileName=file.getPath(); lastDir=file.getParentFile(); } return fileName; } /** * 「上書き保存」のダイアログを表示します。 * @return ファイル名(フルパス指定)を表す String */ public String showSaveDialog(){ String fileName=new String(""); JFileChooser jfc=new JFileChooser(lastDir); FileNameExtensionFilter filter = new FileNameExtensionFilter("SGF Text", "sgf"); jfc.setFileFilter(filter); jfc.setSelectedFile(new File(lastDir,eventName + gameName + ".sgf")); if(jfc.showSaveDialog(jf)==JFileChooser.APPROVE_OPTION){ File file=jfc.getSelectedFile(); fileName=file.getPath(); lastDir=file.getParentFile(); } return fileName; } /** * 再生速度ボタンが押下されたときに呼び出します。 * @return 再生速度(秒数) */ public int askIntervalTime(){ SelectIntervalDialog dialog=new SelectIntervalDialog(jf,"再生速度",true); dialog.setLocation(850,320); return dialog.showIntervalDialog(); } /** * 対局情報ダイアログを表示します。 * @param gameInfo 対局情報を表す GameInformation */ public void showGameInfoDialog(GameInformation gameInfo){ GameInfoDialog gameInfoDialog=new GameInfoDialog(jf,"対局情報",true,controller); gameInfoDialog.showDialog(gameInfo); } //------------------------------------------------------------------------ private void changeBoard(int boardType){ switch(boardType){ case IgoPanel.GRAPHIC_BOARD: jf.getContentPane().remove(jp_ban); jp_ban=graphicBan; setupBoard(); jf.getContentPane().add(jp_ban); jf.getContentPane().validate(); break; case IgoPanel.IMAGE_BOARD: jf.getContentPane().remove(jp_ban); jp_ban=imageBan; setupBoard(); jf.getContentPane().add(jp_ban); jf.getContentPane().validate(); break; case IgoPanel.TEXT_BOARD: jf.getContentPane().remove(jp_ban); jp_ban=textBan; setupBoard(); jf.getContentPane().add(jp_ban); jf.getContentPane().validate(); break; } jf.repaint(); controller.doUpdateView(); } }