package open.dolphin.project;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.logging.Level;
import javax.swing.*;
import open.dolphin.client.ClientContext;
import open.dolphin.client.GUIFactory;
import open.dolphin.plugin.PluginLoader;
/**
* 環境設定ダイアログ。
*
* @author Kazushi Minagawa, Digital Globe, Inc.
*/
public final class ProjectSettingDialog implements PropertyChangeListener {
// GUI
private JDialog dialog;
private JPanel itemPanel;
private JPanel cardPanel;
private CardLayout cardLayout;
private JButton okButton;
private JButton cancelButton;
//
// 全体のモデル
//
private HashMap<String, AbstractPropertySheet> settingMap;
private ArrayList<AbstractPropertySheet> allSettings;
private ArrayList<JToggleButton> allBtns;
private String startSettingName;
private boolean loginState;
private PropertyChangeSupport boundSupport;
private static final String SETTING_PROP = "SETTING_PROP";
private boolean okState;
/**
* Creates new ProjectSettingDialog
*/
public ProjectSettingDialog() {
}
public void addPropertyChangeListener(String prop, PropertyChangeListener l) {
if (boundSupport == null) {
boundSupport = new PropertyChangeSupport(this);
}
boundSupport.addPropertyChangeListener(prop, l);
}
public void removePropertyChangeListener(String prop, PropertyChangeListener l) {
if (boundSupport == null) {
boundSupport = new PropertyChangeSupport(this);
}
boundSupport.addPropertyChangeListener(prop, l);
}
public boolean getLoginState() {
return loginState;
}
public void setLoginState(boolean b) {
loginState = b;
}
public boolean getValue() {
return Project.getProjectStub().isValid();
}
public void notifyResult() {
if (boundSupport!=null) {
boolean valid = Project.getProjectStub().isValid();
boundSupport.firePropertyChange(SETTING_PROP, !valid, valid);
}
}
/**
* オープン時に表示する設定画面をセットする。
* @param startSettingName
*/
public void setProject(String startSettingName) {
this.startSettingName = startSettingName;
}
/**
* 設定画面を開始する。
*/
public void start() {
Runnable r = () -> {
// モデルを得る
// 全ての設定プラグイン(Reference)を得、リストに格納する
allSettings = new ArrayList<>();
PluginLoader<AbstractPropertySheet> loader = PluginLoader.load(AbstractPropertySheet.class);
Iterator<AbstractPropertySheet> iter = loader.iterator();
while (iter.hasNext()) {
AbstractPropertySheet setting = iter.next();
java.util.logging.Logger.getLogger(this.getClass().getName()).fine(setting.getClass().getName());
allSettings.add(setting);
}
// 設定パネル(AbstractSettingPanel)を格納する Hashtableを生成する
// key=設定プラグインの名前 value=設定プラグイン
settingMap = new HashMap<>();
// GUI を構築しモデルをバインドする
initComponents();
// オープン時に表示する設定画面を決定する
int index = 0;
if (startSettingName != null) {
java.util.logging.Logger.getLogger(this.getClass().getName()).fine("startSettingName = " + startSettingName);
for (AbstractPropertySheet setting : allSettings) {
if (startSettingName.equals(setting.getId())) {
java.util.logging.Logger.getLogger(this.getClass().getName()).fine("found index " + index);
break;
}
index++;
}
}
index = (index >= 0 && index < allSettings.size()) ? index : 0;
// Click the toggle button
allBtns.get(index).doClick();
};
SwingUtilities.invokeLater(r);
}
/**
* Setup the user interface
*/
private void initComponents() {
// Panel contains all toggle buttons
itemPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
// 設定プラグインを起動するためのトグルボタンを生成し
// パネルへ加える
allBtns = new ArrayList<>();
ButtonGroup bg = new ButtonGroup();
for (AbstractPropertySheet setting : allSettings) {
String id = setting.getId();
String text = setting.getTitle();
String iconStr = setting.getIcon();
java.util.logging.Logger.getLogger(this.getClass().getName()).log(Level.FINE, "id = {0}", id);
java.util.logging.Logger.getLogger(this.getClass().getName()).log(Level.FINE, "text = {0}", text);
java.util.logging.Logger.getLogger(this.getClass().getName()).log(Level.FINE, "icon = {0}", iconStr);
ImageIcon icon = ClientContext.getImageIconArias(iconStr);
JToggleButton tb = new JToggleButton(text, icon);
tb.setHorizontalTextPosition(SwingConstants.CENTER);
tb.setVerticalTextPosition(SwingConstants.BOTTOM);
itemPanel.add(tb);
bg.add(tb);
tb.setActionCommand(id); // button の actionCommand=id
allBtns.add(tb);
}
// 設定パネルのコンテナとなるカードパネル
cardPanel = new JPanel();
cardLayout = new CardLayout();
cardPanel.setLayout(cardLayout);
java.util.ResourceBundle bundle = ClientContext.getMyBundle(ProjectSettingDialog.class);
// コマンドボタン
String text = bundle.getString("optionText.save");
okButton = GUIFactory.createButton(text, null, null);
okButton.setEnabled(false);
// Cancel
text = GUIFactory.getCancelButtonText();
cancelButton = GUIFactory.createButton(text, "C", null);
// 全体ダイアログのコンテントパネル
JPanel panel = new JPanel(new BorderLayout(11, 0));
panel.add(itemPanel, BorderLayout.NORTH);
panel.add(cardPanel, BorderLayout.CENTER);
// ダイアログを生成する
String title = bundle.getString("title.settingWindow");
Object[] options = new Object[]{okButton, cancelButton};
JOptionPane jop = new JOptionPane(
panel,
JOptionPane.PLAIN_MESSAGE,
JOptionPane.DEFAULT_OPTION,
null,
options,
okButton);
dialog = jop.createDialog((Frame) null, ClientContext.getFrameTitle(title));
dialog.setResizable(true);
java.util.logging.Logger.getLogger(this.getClass().getName()).fine("dialog created");
// イベント接続を行う
connect();
}
/**
* GUI コンポーネントのイベント接続を行う。
*/
private void connect() {
// 設定項目ボタンに追加するアクションリスナを生成する
ActionListener al = (ActionEvent event) -> {
AbstractPropertySheet theSetting = null;
// Action Command に設定パネルのIDが設定してある
String name = event.getActionCommand();
for (AbstractPropertySheet setting : allSettings) {
String id = setting.getId();
if (id.equals(name)) {
theSetting = setting;
break;
}
}
// ボタンに対応する設定パネルにスタートをかける
if (theSetting != null) {
startSetting(theSetting);
}
};
// 全てのボタンにリスナを追加する
for (JToggleButton btn : allBtns) {
btn.addActionListener(al);
}
//Server-ORCA連携^
// ログインした状態では baseURI とレセコンの設定は不可とする
allBtns.get(0).setEnabled(!getLoginState());
allBtns.get(1).setEnabled(!getLoginState());
//Server-ORCA連携$
// Save
okButton.addActionListener((ActionEvent e) -> {
doOk();
});
okButton.setEnabled(false);
// Cancel
cancelButton.addActionListener((ActionEvent e) -> {
doCancel();
});
// Dialog
dialog.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
doCancel();
}
});
}
/**
* 選択された項目(SettingPanel)の編集を開始する.
*/
private void startSetting(final AbstractPropertySheet sp) {
// 既に生成されている場合はそれを表示する
if (sp.getContext() != null) {
cardLayout.show(cardPanel, sp.getTitle());
return;
}
Runnable r = () -> {
// まだ生成されていない場合は
// 選択された設定パネルを生成しカードに追加する
try {
settingMap.put(sp.getId(), sp);
sp.setContext(ProjectSettingDialog.this);
sp.setProjectStub(Project.getProjectStub());
sp.start();
SwingUtilities.invokeLater(() -> {
cardPanel.add(sp.getUI(), sp.getTitle());
cardLayout.show(cardPanel, sp.getTitle());
dialog.validate();
dialog.pack();
if (!dialog.isVisible()) {
Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
int x = (size.width - dialog.getPreferredSize().width) / 2;
int y = (size.height - dialog.getPreferredSize().height) / 3;
dialog.setLocation(x, y);
dialog.setVisible(true);
} else {
dialog.repaint();
}
});
} catch (Exception e) {
e.printStackTrace(System.err);
}
};
Thread t = new Thread(r);
t.setPriority(Thread.NORM_PRIORITY);
t.start();
}
/**
* SettingPanel の state が変化した場合に通知を受け、
* 全てのカードをスキャンして OK ボタンをコントロールする。
* @param e
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
String prop = e.getPropertyName();
if (!prop.equals(AbstractPropertySheet.STATE_PROP)) {
return;
}
// 全てのカードをスキャンして OK ボタンをコントロールする
boolean newOk = true;
Iterator<AbstractPropertySheet> iter = settingMap.values().iterator();
int cnt = 0;
while (iter.hasNext()) {
cnt++;
AbstractPropertySheet p = iter.next();
if (p.getState().equals(AbstractPropertySheet.State.INVALID_STATE)) {
newOk = false;
break;
}
}
if (okState != newOk) {
okState = newOk;
okButton.setEnabled(okState);
}
}
public void doOk() {
Iterator<AbstractPropertySheet> iter = settingMap.values().iterator();
while (iter.hasNext()) {
AbstractPropertySheet p = iter.next();
java.util.logging.Logger.getLogger(this.getClass().getName()).fine(p.getTitle());
p.save();
}
//----------------------------------------
// UserDefaults 保存 たしかに保存だから
//----------------------------------------
Project.saveUserDefaults();
dialog.setVisible(false);
dialog.dispose();
notifyResult();
}
public void doCancel() {
dialog.setVisible(false);
dialog.dispose();
notifyResult();
}
}