4 * License : The MIT License
5 * Copyright(c) 2008 olyutorskii
8 package jp.sourceforge.jindolf;
10 import java.awt.BorderLayout;
11 import java.awt.Container;
12 import java.awt.Frame;
13 import java.awt.GridBagConstraints;
14 import java.awt.GridBagLayout;
15 import java.awt.Insets;
16 import java.awt.event.ActionEvent;
17 import java.awt.event.ActionListener;
18 import java.awt.event.ItemEvent;
19 import java.awt.event.ItemListener;
20 import java.io.IOException;
21 import java.util.HashMap;
23 import javax.swing.BorderFactory;
24 import javax.swing.JButton;
25 import javax.swing.JComboBox;
26 import javax.swing.JComponent;
27 import javax.swing.JDialog;
28 import javax.swing.JLabel;
29 import javax.swing.JOptionPane;
30 import javax.swing.JPanel;
31 import javax.swing.JPasswordField;
32 import javax.swing.JSeparator;
33 import javax.swing.JTextArea;
34 import javax.swing.JTextField;
35 import javax.swing.border.Border;
36 import jp.sourceforge.jindolf.corelib.LandState;
41 @SuppressWarnings("serial")
42 public class AccountPanel
44 implements ActionListener, ItemListener{
46 private static final String FRAMETITLE =
47 "アカウント管理 - " + Jindolf.TITLE;
49 private final Map<Land, String> landUserIDMap =
50 new HashMap<Land, String>();
51 private final Map<Land, char[]> landPasswordMap =
52 new HashMap<Land, char[]>();
54 private final JComboBox landBox = new JComboBox();
55 private final JTextField idField = new JTextField(15);
56 private final JPasswordField pwField = new JPasswordField(15);
57 private final JButton loginButton = new JButton("ログイン");
58 private final JButton logoutButton = new JButton("ログアウト");
59 private final JButton closeButton = new JButton("閉じる");
60 private final JTextArea status = new JTextArea();
64 * @param owner フレームオーナー
65 * @param landsModel 国モデル
66 * @throws java.lang.NullPointerException 引数がnull
68 public AccountPanel(Frame owner, LandsModel landsModel)
69 throws NullPointerException{
70 super(owner, FRAMETITLE, true);
72 if(landsModel == null) throw new NullPointerException();
73 for(Land land : landsModel.getLandList()){
76 this.landUserIDMap.put(land, userID);
77 this.landPasswordMap.put(land, password);
78 this.landBox.addItem(land);
81 GUIUtils.modifyWindowAttributes(this, true, false, true);
83 this.landBox.setToolTipText("アカウント管理する国を選ぶ");
84 this.idField.setToolTipText("IDを入力してください");
85 this.pwField.setToolTipText("パスワードを入力してください");
87 Monodizer.monodize(this.idField);
88 Monodizer.monodize(this.pwField);
90 this.idField.setMargin(new Insets(1, 4, 1, 4));
91 this.pwField.setMargin(new Insets(1, 4, 1, 4));
93 this.idField.setComponentPopupMenu(new TextPopup());
95 this.landBox.setEditable(false);
96 this.landBox.addItemListener(this);
98 this.status.setEditable(false);
99 this.status.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
100 this.status.setRows(2);
101 this.status.setLineWrap(true);
103 this.loginButton.addActionListener(this);
104 this.logoutButton.addActionListener(this);
105 this.closeButton.addActionListener(this);
107 getRootPane().setDefaultButton(this.loginButton);
109 Container content = getContentPane();
110 GridBagLayout layout = new GridBagLayout();
111 GridBagConstraints constraints = new GridBagConstraints();
112 content.setLayout(layout);
114 constraints.gridwidth = GridBagConstraints.REMAINDER;
115 constraints.weightx = 1.0;
116 constraints.insets = new Insets(5, 5, 5, 5);
118 JComponent accountPanel = createCredential();
119 JComponent buttonPanel = createButtonPanel();
121 constraints.weighty = 0.0;
122 constraints.fill = GridBagConstraints.HORIZONTAL;
123 content.add(accountPanel, constraints);
125 Border border = BorderFactory.createTitledBorder("ログインステータス");
126 JPanel panel = new JPanel();
127 panel.setLayout(new BorderLayout());
128 panel.add(this.status, BorderLayout.CENTER);
129 panel.setBorder(border);
131 constraints.weighty = 1.0;
132 constraints.fill = GridBagConstraints.BOTH;
133 content.add(panel, constraints);
135 constraints.weighty = 0.0;
136 constraints.fill = GridBagConstraints.HORIZONTAL;
137 content.add(new JSeparator(), constraints);
139 content.add(buttonPanel, constraints);
141 preSelectActiveLand();
152 private JComponent createCredential(){
153 JPanel credential = new JPanel();
155 GridBagLayout layout = new GridBagLayout();
156 GridBagConstraints constraints = new GridBagConstraints();
158 credential.setLayout(layout);
160 constraints.insets = new Insets(5, 5, 5, 5);
161 constraints.fill = GridBagConstraints.NONE;
163 constraints.anchor = GridBagConstraints.EAST;
164 credential.add(new JLabel("国名 :"), constraints);
165 constraints.anchor = GridBagConstraints.WEST;
166 credential.add(this.landBox, constraints);
168 constraints.gridy = 1;
169 constraints.anchor = GridBagConstraints.EAST;
170 constraints.weightx = 0.0;
171 constraints.fill = GridBagConstraints.NONE;
172 credential.add(new JLabel("ID :"), constraints);
173 constraints.anchor = GridBagConstraints.WEST;
174 constraints.weightx = 1.0;
175 constraints.fill = GridBagConstraints.HORIZONTAL;
176 credential.add(this.idField, constraints);
178 constraints.gridy = 2;
179 constraints.anchor = GridBagConstraints.EAST;
180 constraints.weightx = 0.0;
181 constraints.fill = GridBagConstraints.NONE;
182 credential.add(new JLabel("パスワード :"), constraints);
183 constraints.anchor = GridBagConstraints.WEST;
184 constraints.weightx = 1.0;
185 constraints.fill = GridBagConstraints.HORIZONTAL;
186 credential.add(this.pwField, constraints);
195 private JComponent createButtonPanel(){
196 JPanel buttonPanel = new JPanel();
198 GridBagLayout layout = new GridBagLayout();
199 GridBagConstraints constraints = new GridBagConstraints();
201 buttonPanel.setLayout(layout);
203 constraints.fill = GridBagConstraints.NONE;
204 constraints.anchor = GridBagConstraints.WEST;
205 constraints.weightx = 0.0;
206 constraints.weighty = 0.0;
208 buttonPanel.add(this.loginButton, constraints);
210 constraints.insets = new Insets(0, 5, 0, 0);
211 buttonPanel.add(this.logoutButton, constraints);
213 constraints.anchor = GridBagConstraints.EAST;
214 constraints.weightx = 1.0;
215 constraints.insets = new Insets(0, 15, 0, 0);
216 buttonPanel.add(this.closeButton, constraints);
222 * 現在コンボボックスで選択中の国を返す。
225 private Land getSelectedLand(){
226 Land land = (Land)( this.landBox.getSelectedItem() );
231 * ACTIVEな最初の国がコンボボックスで既に選択されている状態にする。
233 private void preSelectActiveLand(){
234 for(int index = 0; index < this.landBox.getItemCount(); index++){
235 Object item = this.landBox.getItemAt(index);
236 Land land = (Land) item;
237 LandState state = land.getLandDef().getLandState();
238 if(state == LandState.ACTIVE){
239 this.landBox.setSelectedItem(land);
251 private String getUserID(Land land){
252 return this.landUserIDMap.get(land);
260 private char[] getPassword(Land land){
261 return this.landPasswordMap.get(land);
265 * ネットワークエラーを通知するモーダルダイアログを表示する。
266 * OKボタンを押すまでこのメソッドは戻ってこない。
269 protected void showNetworkError(IOException e){
270 Jindolf.logger().warn(
271 "アカウント処理中にネットワークのトラブルが発生しました", e);
273 Land land = getSelectedLand();
274 ServerAccess server = land.getServerAccess();
276 land.getLandDef().getLandName()
278 +"何らかのトラブルが発生しました。\n"
279 +"相手サーバのURLは [ " + server.getBaseURL() + " ] だよ。\n"
280 +"Webブラウザでも遊べないか確認してみてね!\n";
282 JOptionPane pane = new JOptionPane(message,
283 JOptionPane.WARNING_MESSAGE,
284 JOptionPane.DEFAULT_OPTION );
286 JDialog dialog = pane.createDialog(this,
287 "通信異常発生 - " + Jindolf.TITLE);
290 dialog.setVisible(true);
297 * アカウントエラーを通知するモーダルダイアログを表示する。
298 * OKボタンを押すまでこのメソッドは戻ってこない。
300 protected void showIllegalAccountDialog(){
301 Land land = getSelectedLand();
303 land.getLandDef().getLandName()
305 +"ユーザ名とパスワードは本当に正しいかな?\n"
306 +"あなたは本当に [ " + getUserID(land) + " ] さんかな?\n"
307 +"WebブラウザによるID登録手続きは本当に完了してるかな?\n"
308 +"Webブラウザでもログインできないか試してみて!\n"
309 +"…ユーザ名やパスワードにある種の特殊文字を使っている人は"
312 JOptionPane pane = new JOptionPane(message,
313 JOptionPane.WARNING_MESSAGE,
314 JOptionPane.DEFAULT_OPTION );
317 pane.createDialog(this, "ログイン認証失敗 - " + Jindolf.TITLE);
320 dialog.setVisible(true);
327 * 入力されたアカウント情報を基に現在選択中の国へログインする。
328 * @return ログインに成功すればtrueを返す。
330 protected boolean login(){
331 Land land = getSelectedLand();
332 ServerAccess server = land.getServerAccess();
334 String id = this.idField.getText();
335 char[] password = this.pwField.getPassword();
336 this.landUserIDMap.put(land, id);
337 this.landPasswordMap.put(land, password);
339 boolean result = false;
341 result = server.login(id, password);
342 }catch(IOException e){
348 showIllegalAccountDialog();
357 protected void logout(){
360 }catch(IOException e){
368 * @throws java.io.IOException ネットワークエラー
370 protected void logoutInternal() throws IOException{
371 Land land = getSelectedLand();
372 ServerAccess server = land.getServerAccess();
378 * 現在選択中の国のログイン状態に合わせてGUIを更新する。
380 private void updateGUI(){
381 Land land = getSelectedLand();
382 LandState state = land.getLandDef().getLandState();
383 ServerAccess server = land.getServerAccess();
384 boolean hasLoggedIn = server.hasLoggedIn();
386 if(state != LandState.ACTIVE){
390 this.idField.setEnabled(false);
391 this.pwField.setEnabled(false);
392 this.loginButton.setEnabled(false);
393 this.logoutButton.setEnabled(false);
394 }else if(hasLoggedIn){
395 this.status.setText("ユーザ [ " + getUserID(land) + " ] として\n"
397 this.idField.setEnabled(false);
398 this.pwField.setEnabled(false);
399 this.loginButton.setEnabled(false);
400 this.logoutButton.setEnabled(true);
402 this.status.setText("現在ログインしていません");
403 this.idField.setEnabled(true);
404 this.pwField.setEnabled(true);
405 this.loginButton.setEnabled(true);
406 this.logoutButton.setEnabled(false);
415 * @param event イベント {@inheritDoc}
417 // TODO Return キー押下によるログインもサポートしたい
419 public void actionPerformed(ActionEvent event){
420 Object source = event.getSource();
422 if(source == this.closeButton){
428 if(source == this.loginButton){
430 }else if(source == this.logoutButton){
442 * @param event イベント {@inheritDoc}
445 public void itemStateChanged(ItemEvent event){
446 Object source = event.getSource();
447 if(source != this.landBox) return;
449 Land land = (Land) event.getItem();
453 switch(event.getStateChange()){
454 case ItemEvent.SELECTED:
455 id = getUserID(land);
456 password = getPassword(land);
457 this.idField.setText(id);
458 this.pwField.setText(new String(password));
461 case ItemEvent.DESELECTED:
462 id = this.idField.getText();
463 password = this.pwField.getPassword();
464 this.landUserIDMap.put(land, id);
465 this.landPasswordMap.put(land, password);
475 // TODO IDかパスワードが空の場合はログインボタンを無効にしたい