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();
}
}