-/*\r
- * Account panel\r
- *\r
- * Copyright(c) 2008 olyutorskii\r
- * $Id: AccountPanel.java 956 2009-12-13 15:14:07Z olyutorskii $\r
- */\r
-\r
-package jp.sourceforge.jindolf;\r
-\r
-import java.awt.BorderLayout;\r
-import java.awt.Container;\r
-import java.awt.Frame;\r
-import java.awt.GridBagConstraints;\r
-import java.awt.GridBagLayout;\r
-import java.awt.Insets;\r
-import java.awt.event.ActionEvent;\r
-import java.awt.event.ActionListener;\r
-import java.awt.event.ItemEvent;\r
-import java.awt.event.ItemListener;\r
-import java.io.IOException;\r
-import java.util.HashMap;\r
-import java.util.Map;\r
-import javax.swing.BorderFactory;\r
-import javax.swing.JButton;\r
-import javax.swing.JComboBox;\r
-import javax.swing.JComponent;\r
-import javax.swing.JDialog;\r
-import javax.swing.JLabel;\r
-import javax.swing.JOptionPane;\r
-import javax.swing.JPanel;\r
-import javax.swing.JPasswordField;\r
-import javax.swing.JSeparator;\r
-import javax.swing.JTextArea;\r
-import javax.swing.JTextField;\r
-import javax.swing.border.Border;\r
-import jp.sourceforge.jindolf.corelib.LandState;\r
-\r
-/**\r
- * ログインパネル。\r
- */\r
-@SuppressWarnings("serial")\r
-public class AccountPanel\r
- extends JDialog\r
- implements ActionListener, ItemListener{\r
-\r
- private static final String FRAMETITLE =\r
- "アカウント管理 - " + Jindolf.TITLE;\r
-\r
- private final Map<Land, String> landUserIDMap =\r
- new HashMap<Land, String>();\r
- private final Map<Land, char[]> landPasswordMap =\r
- new HashMap<Land, char[]>();\r
-\r
- private final JComboBox landBox = new JComboBox();\r
- private final JTextField idField = new JTextField(15);\r
- private final JPasswordField pwField = new JPasswordField(15);\r
- private final JButton loginButton = new JButton("ログイン");\r
- private final JButton logoutButton = new JButton("ログアウト");\r
- private final JButton closeButton = new JButton("閉じる");\r
- private final JTextArea status = new JTextArea();\r
-\r
- /**\r
- * アカウントパネルを生成。\r
- * @param owner フレームオーナー\r
- * @param landsModel 国モデル\r
- * @throws java.lang.NullPointerException 引数がnull\r
- */\r
- public AccountPanel(Frame owner, LandsModel landsModel)\r
- throws NullPointerException{\r
- super(owner, FRAMETITLE, true);\r
-\r
- if(landsModel == null) throw new NullPointerException();\r
- for(Land land : landsModel.getLandList()){\r
- String userID = "";\r
- char[] password = {};\r
- this.landUserIDMap.put(land, userID);\r
- this.landPasswordMap.put(land, password);\r
- this.landBox.addItem(land);\r
- }\r
-\r
- GUIUtils.modifyWindowAttributes(this, true, false, true);\r
-\r
- this.landBox.setToolTipText("アカウント管理する国を選ぶ");\r
- this.idField.setToolTipText("IDを入力してください");\r
- this.pwField.setToolTipText("パスワードを入力してください");\r
-\r
- Monodizer.monodize(this.idField);\r
- Monodizer.monodize(this.pwField);\r
-\r
- this.idField.setMargin(new Insets(1, 4, 1, 4));\r
- this.pwField.setMargin(new Insets(1, 4, 1, 4));\r
-\r
- this.idField.setComponentPopupMenu(new TextPopup());\r
-\r
- this.landBox.setEditable(false);\r
- this.landBox.addItemListener(this);\r
-\r
- this.status.setEditable(false);\r
- this.status.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));\r
- this.status.setRows(2);\r
- this.status.setLineWrap(true);\r
-\r
- this.loginButton.addActionListener(this);\r
- this.logoutButton.addActionListener(this);\r
- this.closeButton.addActionListener(this);\r
-\r
- getRootPane().setDefaultButton(this.loginButton);\r
-\r
- Container content = getContentPane();\r
- GridBagLayout layout = new GridBagLayout();\r
- GridBagConstraints constraints = new GridBagConstraints();\r
- content.setLayout(layout);\r
-\r
- constraints.gridwidth = GridBagConstraints.REMAINDER;\r
- constraints.weightx = 1.0;\r
- constraints.insets = new Insets(5, 5, 5, 5);\r
-\r
- JComponent accountPanel = createCredential();\r
- JComponent buttonPanel = createButtonPanel();\r
-\r
- constraints.weighty = 0.0;\r
- constraints.fill = GridBagConstraints.HORIZONTAL;\r
- content.add(accountPanel, constraints);\r
-\r
- Border border = BorderFactory.createTitledBorder("ログインステータス");\r
- JPanel panel = new JPanel();\r
- panel.setLayout(new BorderLayout());\r
- panel.add(this.status, BorderLayout.CENTER);\r
- panel.setBorder(border);\r
-\r
- constraints.weighty = 1.0;\r
- constraints.fill = GridBagConstraints.BOTH;\r
- content.add(panel, constraints);\r
-\r
- constraints.weighty = 0.0;\r
- constraints.fill = GridBagConstraints.HORIZONTAL;\r
- content.add(new JSeparator(), constraints);\r
-\r
- content.add(buttonPanel, constraints);\r
-\r
- preSelectActiveLand();\r
-\r
- updateGUI();\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * 認証パネルを生成する。\r
- * @return 認証パネル\r
- */\r
- private JComponent createCredential(){\r
- JPanel credential = new JPanel();\r
-\r
- GridBagLayout layout = new GridBagLayout();\r
- GridBagConstraints constraints = new GridBagConstraints();\r
-\r
- credential.setLayout(layout);\r
-\r
- constraints.insets = new Insets(5, 5, 5, 5);\r
- constraints.fill = GridBagConstraints.NONE;\r
-\r
- constraints.anchor = GridBagConstraints.EAST;\r
- credential.add(new JLabel("国名 :"), constraints);\r
- constraints.anchor = GridBagConstraints.WEST;\r
- credential.add(this.landBox, constraints);\r
-\r
- constraints.gridy = 1;\r
- constraints.anchor = GridBagConstraints.EAST;\r
- constraints.weightx = 0.0;\r
- constraints.fill = GridBagConstraints.NONE;\r
- credential.add(new JLabel("ID :"), constraints);\r
- constraints.anchor = GridBagConstraints.WEST;\r
- constraints.weightx = 1.0;\r
- constraints.fill = GridBagConstraints.HORIZONTAL;\r
- credential.add(this.idField, constraints);\r
-\r
- constraints.gridy = 2;\r
- constraints.anchor = GridBagConstraints.EAST;\r
- constraints.weightx = 0.0;\r
- constraints.fill = GridBagConstraints.NONE;\r
- credential.add(new JLabel("パスワード :"), constraints);\r
- constraints.anchor = GridBagConstraints.WEST;\r
- constraints.weightx = 1.0;\r
- constraints.fill = GridBagConstraints.HORIZONTAL;\r
- credential.add(this.pwField, constraints);\r
-\r
- return credential;\r
- }\r
-\r
- /**\r
- * ボタンパネルの作成。\r
- * @return ボタンパネル\r
- */\r
- private JComponent createButtonPanel(){\r
- JPanel buttonPanel = new JPanel();\r
-\r
- GridBagLayout layout = new GridBagLayout();\r
- GridBagConstraints constraints = new GridBagConstraints();\r
-\r
- buttonPanel.setLayout(layout);\r
-\r
- constraints.fill = GridBagConstraints.NONE;\r
- constraints.anchor = GridBagConstraints.WEST;\r
- constraints.weightx = 0.0;\r
- constraints.weighty = 0.0;\r
-\r
- buttonPanel.add(this.loginButton, constraints);\r
-\r
- constraints.insets = new Insets(0, 5, 0, 0);\r
- buttonPanel.add(this.logoutButton, constraints);\r
-\r
- constraints.anchor = GridBagConstraints.EAST;\r
- constraints.weightx = 1.0;\r
- constraints.insets = new Insets(0, 15, 0, 0);\r
- buttonPanel.add(this.closeButton, constraints);\r
-\r
- return buttonPanel;\r
- }\r
-\r
- /**\r
- * 現在コンボボックスで選択中の国を返す。\r
- * @return 現在選択中のLand\r
- */\r
- private Land getSelectedLand(){\r
- Land land = (Land)( this.landBox.getSelectedItem() );\r
- return land;\r
- }\r
-\r
- /**\r
- * ACTIVEな最初の国がコンボボックスで既に選択されている状態にする。\r
- */\r
- private void preSelectActiveLand(){\r
- for(int index = 0; index < this.landBox.getItemCount(); index++){\r
- Object item = this.landBox.getItemAt(index);\r
- Land land = (Land) item;\r
- LandState state = land.getLandDef().getLandState();\r
- if(state == LandState.ACTIVE){\r
- this.landBox.setSelectedItem(land);\r
- return;\r
- }\r
- }\r
- return;\r
- }\r
-\r
- /**\r
- * 指定された国のユーザIDを返す。\r
- * @param land 国\r
- * @return ユーザID\r
- */\r
- private String getUserID(Land land){\r
- return this.landUserIDMap.get(land);\r
- }\r
-\r
- /**\r
- * 指定された国のパスワードを返す。\r
- * @param land 国\r
- * @return パスワード\r
- */\r
- private char[] getPassword(Land land){\r
- return this.landPasswordMap.get(land);\r
- }\r
-\r
- /**\r
- * ネットワークエラーを通知するモーダルダイアログを表示する。\r
- * OKボタンを押すまでこのメソッドは戻ってこない。\r
- * @param e ネットワークエラー\r
- */\r
- protected void showNetworkError(IOException e){\r
- Jindolf.logger().warn(\r
- "アカウント処理中にネットワークのトラブルが発生しました", e);\r
-\r
- Land land = getSelectedLand();\r
- ServerAccess server = land.getServerAccess();\r
- String message =\r
- land.getLandDef().getLandName()\r
- +"を運営するサーバとの間の通信で"\r
- +"何らかのトラブルが発生しました。\n"\r
- +"相手サーバのURLは [ " + server.getBaseURL() + " ] だよ。\n"\r
- +"Webブラウザでも遊べないか確認してみてね!\n";\r
-\r
- JOptionPane pane = new JOptionPane(message,\r
- JOptionPane.WARNING_MESSAGE,\r
- JOptionPane.DEFAULT_OPTION );\r
-\r
- JDialog dialog = pane.createDialog(this,\r
- "通信異常発生 - " + Jindolf.TITLE);\r
-\r
- dialog.pack();\r
- dialog.setVisible(true);\r
- dialog.dispose();\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * アカウントエラーを通知するモーダルダイアログを表示する。\r
- * OKボタンを押すまでこのメソッドは戻ってこない。\r
- */\r
- protected void showIllegalAccountDialog(){\r
- Land land = getSelectedLand();\r
- String message =\r
- land.getLandDef().getLandName()\r
- +"へのログインに失敗しました。\n"\r
- +"ユーザ名とパスワードは本当に正しいかな?\n"\r
- +"あなたは本当に [ " + getUserID(land) + " ] さんかな?\n"\r
- +"WebブラウザによるID登録手続きは本当に完了してるかな?\n"\r
- +"Webブラウザでもログインできないか試してみて!\n"\r
- +"…ユーザ名やパスワードにある種の特殊文字を使っている人は"\r
- +"問題があるかも。";\r
-\r
- JOptionPane pane = new JOptionPane(message,\r
- JOptionPane.WARNING_MESSAGE,\r
- JOptionPane.DEFAULT_OPTION );\r
-\r
- JDialog dialog =\r
- pane.createDialog(this, "ログイン認証失敗 - " + Jindolf.TITLE);\r
-\r
- dialog.pack();\r
- dialog.setVisible(true);\r
- dialog.dispose();\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * 入力されたアカウント情報を基に現在選択中の国へログインする。\r
- * @return ログインに成功すればtrueを返す。\r
- */\r
- protected boolean login(){\r
- Land land = getSelectedLand();\r
- ServerAccess server = land.getServerAccess();\r
-\r
- String id = this.idField.getText();\r
- char[] password = this.pwField.getPassword();\r
- this.landUserIDMap.put(land, id);\r
- this.landPasswordMap.put(land, password);\r
-\r
- boolean result = false;\r
- try{\r
- result = server.login(id, password);\r
- }catch(IOException e){\r
- showNetworkError(e);\r
- return false;\r
- }\r
-\r
- if( ! result ){\r
- showIllegalAccountDialog();\r
- }\r
-\r
- return result;\r
- }\r
-\r
- /**\r
- * 現在選択中の国からログアウトする。\r
- */\r
- protected void logout(){\r
- try{\r
- logoutInternal();\r
- }catch(IOException e){\r
- showNetworkError(e);\r
- }\r
- return;\r
- }\r
-\r
- /**\r
- * 現在選択中の国からログアウトする。\r
- * @throws java.io.IOException ネットワークエラー\r
- */\r
- protected void logoutInternal() throws IOException{\r
- Land land = getSelectedLand();\r
- ServerAccess server = land.getServerAccess();\r
- server.logout();\r
- return;\r
- }\r
-\r
- /**\r
- * 現在選択中の国のログイン状態に合わせてGUIを更新する。\r
- */\r
- private void updateGUI(){\r
- Land land = getSelectedLand();\r
- LandState state = land.getLandDef().getLandState();\r
- ServerAccess server = land.getServerAccess();\r
- boolean hasLoggedIn = server.hasLoggedIn();\r
-\r
- if(state != LandState.ACTIVE){\r
- this.status.setText(\r
- "この国は既に募集を停止しました。\n"\r
- +"ログインは無意味です" );\r
- this.idField.setEnabled(false);\r
- this.pwField.setEnabled(false);\r
- this.loginButton.setEnabled(false);\r
- this.logoutButton.setEnabled(false);\r
- }else if(hasLoggedIn){\r
- this.status.setText("ユーザ [ " + getUserID(land) + " ] として\n"\r
- +"現在ログイン中です");\r
- this.idField.setEnabled(false);\r
- this.pwField.setEnabled(false);\r
- this.loginButton.setEnabled(false);\r
- this.logoutButton.setEnabled(true);\r
- }else{\r
- this.status.setText("現在ログインしていません");\r
- this.idField.setEnabled(true);\r
- this.pwField.setEnabled(true);\r
- this.loginButton.setEnabled(true);\r
- this.logoutButton.setEnabled(false);\r
- }\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * ボタン操作のリスナ。\r
- * @param event イベント {@inheritDoc}\r
- */\r
- // TODO Return キー押下によるログインもサポートしたい\r
- public void actionPerformed(ActionEvent event){\r
- Object source = event.getSource();\r
-\r
- if(source == this.closeButton){\r
- setVisible(false);\r
- dispose();\r
- return;\r
- }\r
-\r
- if(source == this.loginButton){\r
- login();\r
- }else if(source == this.logoutButton){\r
- logout();\r
- }\r
-\r
- updateGUI();\r
-\r
- return;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- * コンボボックス操作のリスナ。\r
- * @param event イベント {@inheritDoc}\r
- */\r
- public void itemStateChanged(ItemEvent event){\r
- Object source = event.getSource();\r
- if(source != this.landBox) return;\r
-\r
- Land land = (Land) event.getItem();\r
- String id;\r
- char[] password;\r
-\r
- switch(event.getStateChange()){\r
- case ItemEvent.SELECTED:\r
- id = getUserID(land);\r
- password = getPassword(land);\r
- this.idField.setText(id);\r
- this.pwField.setText(new String(password));\r
- updateGUI();\r
- break;\r
- case ItemEvent.DESELECTED:\r
- id = this.idField.getText();\r
- password = this.pwField.getPassword();\r
- this.landUserIDMap.put(land, id);\r
- this.landPasswordMap.put(land, password);\r
- break;\r
- default:\r
- assert false;\r
- return;\r
- }\r
-\r
- return;\r
- }\r
-\r
- // TODO IDかパスワードが空の場合はログインボタンを無効にしたい\r
-}\r
+/*
+ * Account panel
+ *
+ * License : The MIT License
+ * Copyright(c) 2008 olyutorskii
+ */
+
+package jp.sfjp.jindolf.view;
+
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.JSeparator;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.border.Border;
+import jp.sfjp.jindolf.VerInfo;
+import jp.sfjp.jindolf.data.Land;
+import jp.sfjp.jindolf.data.LandsModel;
+import jp.sfjp.jindolf.dxchg.TextPopup;
+import jp.sfjp.jindolf.net.ServerAccess;
+import jp.sfjp.jindolf.util.GUIUtils;
+import jp.sfjp.jindolf.util.Monodizer;
+import jp.sourceforge.jindolf.corelib.LandState;
+
+/**
+ * ログインパネル。
+ */
+@SuppressWarnings("serial")
+public class AccountPanel
+ extends JDialog
+ implements ActionListener, ItemListener{
+
+ private static final Logger LOGGER = Logger.getAnonymousLogger();
+
+
+ private final Map<Land, String> landUserIDMap =
+ new HashMap<>();
+ private final Map<Land, char[]> landPasswordMap =
+ new HashMap<>();
+
+ private final JComboBox<Land> landBox = new JComboBox<>();
+ private final JTextField idField = new JTextField(15);
+ private final JPasswordField pwField = new JPasswordField(15);
+ private final JButton loginButton = new JButton("ログイン");
+ private final JButton logoutButton = new JButton("ログアウト");
+ private final JButton closeButton = new JButton("閉じる");
+ private final JTextArea status = new JTextArea();
+
+ /**
+ * アカウントパネルを生成。
+ * @param owner フレームオーナー
+ */
+ @SuppressWarnings("LeakingThisInConstructor")
+ public AccountPanel(Frame owner){
+ super(owner);
+ setModal(true);
+
+ GUIUtils.modifyWindowAttributes(this, true, false, true);
+
+ this.landBox.setToolTipText("アカウント管理する国を選ぶ");
+ this.idField.setToolTipText("IDを入力してください");
+ this.pwField.setToolTipText("パスワードを入力してください");
+
+ Monodizer.monodize(this.idField);
+ Monodizer.monodize(this.pwField);
+
+ this.idField.setMargin(new Insets(1, 4, 1, 4));
+ this.pwField.setMargin(new Insets(1, 4, 1, 4));
+
+ this.idField.setComponentPopupMenu(new TextPopup());
+
+ this.landBox.setEditable(false);
+ this.landBox.addItemListener(this);
+
+ this.status.setEditable(false);
+ this.status.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+ this.status.setRows(2);
+ this.status.setLineWrap(true);
+
+ this.loginButton.addActionListener(this);
+ this.logoutButton.addActionListener(this);
+ this.closeButton.addActionListener(this);
+
+ getRootPane().setDefaultButton(this.loginButton);
+
+ Container content = getContentPane();
+ GridBagLayout layout = new GridBagLayout();
+ GridBagConstraints constraints = new GridBagConstraints();
+ content.setLayout(layout);
+
+ constraints.gridwidth = GridBagConstraints.REMAINDER;
+ constraints.weightx = 1.0;
+ constraints.insets = new Insets(5, 5, 5, 5);
+
+ JComponent accountPanel = createCredential();
+ JComponent buttonPanel = createButtonPanel();
+
+ constraints.weighty = 0.0;
+ constraints.fill = GridBagConstraints.HORIZONTAL;
+ content.add(accountPanel, constraints);
+
+ Border border = BorderFactory.createTitledBorder("ログインステータス");
+ JPanel panel = new JPanel();
+ panel.setLayout(new BorderLayout());
+ panel.add(this.status, BorderLayout.CENTER);
+ panel.setBorder(border);
+
+ constraints.weighty = 1.0;
+ constraints.fill = GridBagConstraints.BOTH;
+ content.add(panel, constraints);
+
+ constraints.weighty = 0.0;
+ constraints.fill = GridBagConstraints.HORIZONTAL;
+ content.add(new JSeparator(), constraints);
+
+ content.add(buttonPanel, constraints);
+
+ return;
+ }
+
+ /**
+ * 認証パネルを生成する。
+ * @return 認証パネル
+ */
+ private JComponent createCredential(){
+ JPanel credential = new JPanel();
+
+ GridBagLayout layout = new GridBagLayout();
+ GridBagConstraints constraints = new GridBagConstraints();
+
+ credential.setLayout(layout);
+
+ constraints.insets = new Insets(5, 5, 5, 5);
+ constraints.fill = GridBagConstraints.NONE;
+
+ constraints.anchor = GridBagConstraints.EAST;
+ credential.add(new JLabel("国名 :"), constraints);
+ constraints.anchor = GridBagConstraints.WEST;
+ credential.add(this.landBox, constraints);
+
+ constraints.gridy = 1;
+ constraints.anchor = GridBagConstraints.EAST;
+ constraints.weightx = 0.0;
+ constraints.fill = GridBagConstraints.NONE;
+ credential.add(new JLabel("ID :"), constraints);
+ constraints.anchor = GridBagConstraints.WEST;
+ constraints.weightx = 1.0;
+ constraints.fill = GridBagConstraints.HORIZONTAL;
+ credential.add(this.idField, constraints);
+
+ constraints.gridy = 2;
+ constraints.anchor = GridBagConstraints.EAST;
+ constraints.weightx = 0.0;
+ constraints.fill = GridBagConstraints.NONE;
+ credential.add(new JLabel("パスワード :"), constraints);
+ constraints.anchor = GridBagConstraints.WEST;
+ constraints.weightx = 1.0;
+ constraints.fill = GridBagConstraints.HORIZONTAL;
+ credential.add(this.pwField, constraints);
+
+ return credential;
+ }
+
+ /**
+ * ボタンパネルの作成。
+ * @return ボタンパネル
+ */
+ private JComponent createButtonPanel(){
+ JPanel buttonPanel = new JPanel();
+
+ GridBagLayout layout = new GridBagLayout();
+ GridBagConstraints constraints = new GridBagConstraints();
+
+ buttonPanel.setLayout(layout);
+
+ constraints.fill = GridBagConstraints.NONE;
+ constraints.anchor = GridBagConstraints.WEST;
+ constraints.weightx = 0.0;
+ constraints.weighty = 0.0;
+
+ buttonPanel.add(this.loginButton, constraints);
+
+ constraints.insets = new Insets(0, 5, 0, 0);
+ buttonPanel.add(this.logoutButton, constraints);
+
+ constraints.anchor = GridBagConstraints.EAST;
+ constraints.weightx = 1.0;
+ constraints.insets = new Insets(0, 15, 0, 0);
+ buttonPanel.add(this.closeButton, constraints);
+
+ return buttonPanel;
+ }
+
+ /**
+ * 現在コンボボックスで選択中の国を返す。
+ * @return 現在選択中のLand
+ */
+ private Land getSelectedLand(){
+ Land land = (Land) ( this.landBox.getSelectedItem() );
+ return land;
+ }
+
+ /**
+ * ACTIVEな最初の国がコンボボックスで既に選択されている状態にする。
+ */
+ private void preSelectActiveLand(){
+ for(int index = 0; index < this.landBox.getItemCount(); index++){
+ Object item = this.landBox.getItemAt(index);
+ Land land = (Land) item;
+ LandState state = land.getLandDef().getLandState();
+ if(state == LandState.ACTIVE){
+ this.landBox.setSelectedItem(land);
+ return;
+ }
+ }
+ return;
+ }
+
+ /**
+ * 指定された国のユーザIDを返す。
+ * @param land 国
+ * @return ユーザID
+ */
+ private String getUserID(Land land){
+ return this.landUserIDMap.get(land);
+ }
+
+ /**
+ * 指定された国のパスワードを返す。
+ * @param land 国
+ * @return パスワード
+ */
+ private char[] getPassword(Land land){
+ return this.landPasswordMap.get(land);
+ }
+
+ /**
+ * ネットワークエラーを通知するモーダルダイアログを表示する。
+ * OKボタンを押すまでこのメソッドは戻ってこない。
+ * @param e ネットワークエラー
+ */
+ protected void showNetworkError(IOException e){
+ LOGGER.log(Level.WARNING,
+ "アカウント処理中にネットワークのトラブルが発生しました", e);
+
+ Land land = getSelectedLand();
+ ServerAccess server = land.getServerAccess();
+ String message =
+ land.getLandDef().getLandName()
+ +"を運営するサーバとの間の通信で"
+ +"何らかのトラブルが発生しました。\n"
+ +"相手サーバのURLは [ " + server.getBaseURL() + " ] だよ。\n"
+ +"Webブラウザでも遊べないか確認してみてね!\n";
+
+ JOptionPane pane = new JOptionPane(message,
+ JOptionPane.WARNING_MESSAGE,
+ JOptionPane.DEFAULT_OPTION );
+
+ String title = VerInfo.getFrameTitle("通信異常発生");
+ JDialog dialog = pane.createDialog(this, title);
+
+ dialog.pack();
+ dialog.setVisible(true);
+ dialog.dispose();
+
+ return;
+ }
+
+ /**
+ * アカウントエラーを通知するモーダルダイアログを表示する。
+ * OKボタンを押すまでこのメソッドは戻ってこない。
+ */
+ protected void showIllegalAccountDialog(){
+ Land land = getSelectedLand();
+ String message =
+ land.getLandDef().getLandName()
+ +"へのログインに失敗しました。\n"
+ +"ユーザ名とパスワードは本当に正しいかな?\n"
+ +"あなたは本当に [ " + getUserID(land) + " ] さんかな?\n"
+ +"WebブラウザによるID登録手続きは本当に完了してるかな?\n"
+ +"Webブラウザでもログインできないか試してみて!\n"
+ +"…ユーザ名やパスワードにある種の特殊文字を使っている人は"
+ +"問題があるかも。";
+
+ JOptionPane pane = new JOptionPane(message,
+ JOptionPane.WARNING_MESSAGE,
+ JOptionPane.DEFAULT_OPTION );
+
+ String title = VerInfo.getFrameTitle("ログイン認証失敗");
+ JDialog dialog = pane.createDialog(this, title);
+
+ dialog.pack();
+ dialog.setVisible(true);
+ dialog.dispose();
+
+ return;
+ }
+
+ /**
+ * 入力されたアカウント情報を基に現在選択中の国へログインする。
+ * @return ログインに成功すればtrueを返す。
+ */
+ protected boolean login(){
+ Land land = getSelectedLand();
+ ServerAccess server = land.getServerAccess();
+
+ String id = this.idField.getText();
+ char[] password = this.pwField.getPassword();
+ this.landUserIDMap.put(land, id);
+ this.landPasswordMap.put(land, password);
+
+ boolean result = false;
+ try{
+ result = server.login(id, password);
+ }catch(IOException e){
+ showNetworkError(e);
+ return false;
+ }
+
+ if( ! result ){
+ showIllegalAccountDialog();
+ }
+
+ return result;
+ }
+
+ /**
+ * 現在選択中の国からログアウトする。
+ */
+ protected void logout(){
+ try{
+ logoutInternal();
+ }catch(IOException e){
+ showNetworkError(e);
+ }
+ return;
+ }
+
+ /**
+ * 現在選択中の国からログアウトする。
+ * @throws java.io.IOException ネットワークエラー
+ */
+ protected void logoutInternal() throws IOException{
+ Land land = getSelectedLand();
+ ServerAccess server = land.getServerAccess();
+ server.logout();
+ return;
+ }
+
+ /**
+ * 現在選択中の国のログイン状態に合わせてGUIを更新する。
+ */
+ private void updateGUI(){
+ Land land = getSelectedLand();
+ if(land == null) return;
+
+ LandState state = land.getLandDef().getLandState();
+ ServerAccess server = land.getServerAccess();
+ boolean hasLoggedIn = server.hasLoggedIn();
+
+ if(state != LandState.ACTIVE){
+ this.status.setText(
+ "この国は既に募集を停止しました。\n"
+ +"ログインは無意味です" );
+ this.idField.setEnabled(false);
+ this.pwField.setEnabled(false);
+ this.loginButton.setEnabled(false);
+ this.logoutButton.setEnabled(false);
+ }else if(hasLoggedIn){
+ this.status.setText("ユーザ [ " + getUserID(land) + " ] として\n"
+ +"現在ログイン中です");
+ this.idField.setEnabled(false);
+ this.pwField.setEnabled(false);
+ this.loginButton.setEnabled(false);
+ this.logoutButton.setEnabled(true);
+ }else{
+ this.status.setText("現在ログインしていません");
+ this.idField.setEnabled(true);
+ this.pwField.setEnabled(true);
+ this.loginButton.setEnabled(true);
+ this.logoutButton.setEnabled(false);
+ }
+
+ return;
+ }
+
+ /**
+ * 国情報を設定する。
+ * @param model 国情報
+ * @throws NullPointerException 引数がnull
+ */
+ public void setModel(LandsModel model) throws NullPointerException{
+ if(model == null) throw new NullPointerException();
+
+ this.landUserIDMap.clear();
+ this.landPasswordMap.clear();
+ this.landBox.removeAllItems();
+
+ for(Land land : model.getLandList()){
+ String userID = "";
+ char[] password = {};
+ this.landUserIDMap.put(land, userID);
+ this.landPasswordMap.put(land, password);
+ this.landBox.addItem(land);
+ }
+
+ preSelectActiveLand();
+ updateGUI();
+
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * ボタン操作のリスナ。
+ * @param event イベント {@inheritDoc}
+ */
+ // TODO Return キー押下によるログインもサポートしたい
+ @Override
+ public void actionPerformed(ActionEvent event){
+ Object source = event.getSource();
+
+ if(source == this.closeButton){
+ setVisible(false);
+ dispose();
+ return;
+ }
+
+ if(source == this.loginButton){
+ login();
+ }else if(source == this.logoutButton){
+ logout();
+ }
+
+ updateGUI();
+
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * コンボボックス操作のリスナ。
+ * @param event イベント {@inheritDoc}
+ */
+ @Override
+ public void itemStateChanged(ItemEvent event){
+ Object source = event.getSource();
+ if(source != this.landBox) return;
+
+ Land land = (Land) event.getItem();
+ String id;
+ char[] password;
+
+ switch(event.getStateChange()){
+ case ItemEvent.SELECTED:
+ id = getUserID(land);
+ password = getPassword(land);
+ this.idField.setText(id);
+ this.pwField.setText(new String(password));
+ updateGUI();
+ break;
+ case ItemEvent.DESELECTED:
+ id = this.idField.getText();
+ password = this.pwField.getPassword();
+ this.landUserIDMap.put(land, id);
+ this.landPasswordMap.put(land, password);
+ break;
+ default:
+ assert false;
+ return;
+ }
+
+ return;
+ }
+
+ // TODO IDかパスワードが空の場合はログインボタンを無効にしたい
+}