package open.dolphin.helper;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.KeyStroke;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
import open.dolphin.client.GUIConst;
import open.dolphin.ui.MainFrame;
/**
* Window Menu をサポートするためのクラス。
* Factory method で WindowMenu をもつ JFrame を生成する。
*
* @author Minagawa,Kazushi
*/
public class WindowSupport implements MenuListener {
private static ArrayList<WindowSupport> allWindows = new ArrayList<WindowSupport>();
private static final String WINDOW_MWNU_NAME = "ウインドウ";
//pns^
private static enum State { OPENED, CLOSED };
// frame を整列させるときの初期位置と移動幅
public static int INITIAL_X = 256;
public static int INITIAL_Y = 40;
public static int INITIAL_DX = 192;
public static int INITIAL_DY = 20;
//pns$
// Window support が提供するスタッフ
// フレーム
private MainFrame frame;
// メニューバー
private JMenuBar menuBar;
// ウインドウメニュー
private JMenu windowMenu;
// Window Action
private Action windowAction;
/**
* WindowSupportを生成する。
* @param title フレームタイトル
* @return WindowSupport
*/
public static WindowSupport create(String title) {
// フレームを生成する
final MainFrame frame = new MainFrame(title);
// メニューバーを生成する
JMenuBar menuBar = new JMenuBar();
// Window メニューを生成する
JMenu windowMenu = new JMenu(WINDOW_MWNU_NAME);
// メニューバーへWindow メニューを追加する
menuBar.add(windowMenu);
// フレームにメニューバーを設定する
frame.setJMenuBar(menuBar);
// Windowメニューのアクション
// 選択されたらフレームを前面にする
Action windowAction = new AbstractAction(title) {
public void actionPerformed(ActionEvent e) {
frame.toFront();
}
};
// インスタンスを生成する
final WindowSupport ret
= new WindowSupport(frame, menuBar, windowMenu, windowAction);
// WindowEvent をこのクラスに通知しリストの管理を行う
frame.setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowOpened(java.awt.event.WindowEvent e) {
//pns WindowSupport.windowOpened(ret);
setWindowList(State.OPENED);
}
@Override
public void windowClosed(java.awt.event.WindowEvent e) {
//pns WindowSupport.windowClosed(ret);
setWindowList(State.CLOSED);
}
//pns^
// 同時に windowOpened と windowClosed が集中したとき対策。考えすぎか。
private synchronized void setWindowList(State state) {
if (state == State.OPENED) allWindows.add(ret);
else allWindows.remove(ret);
}
//pns$
});
// windowMenu にメニューリスナを設定しこのクラスで処理をする
windowMenu.addMenuListener(ret);
return ret;
}
public static ArrayList<WindowSupport> getAllWindows() {
return allWindows;
}
/* public static void windowOpened(WindowSupport opened) {
// リストに追加する
allWindows.add(opened);
}
public static void windowClosed(WindowSupport closed) {
// リストから削除する
allWindows.remove(closed);
closed = null;
}
public static boolean contains(WindowSupport toCheck) {
return allWindows.contains(toCheck);
}*/
//pns$
// プライベートコンストラクタ
private WindowSupport(MainFrame frame, JMenuBar menuBar, JMenu windowMenu,
Action windowAction) {
this.frame = frame;
this.menuBar = menuBar;
this.windowMenu = windowMenu;
this.windowAction = windowAction;
//pns^
// インスペクタを整列するアクションだけはあらかじめ入れておく
// こうしておかないと,1回 window メニューを開かないと accelerator が効かないことになる
windowMenu.add(new ArrangeInspectorAction());
//pns$
}
public MainFrame getFrame() {
return frame;
}
public JMenuBar getMenuBar() {
return menuBar;
}
public JMenu getWindowMenu() {
return windowMenu;
}
public Action getWindowAction() {
return windowAction;
}
/**
* ウインドウメニューが選択された場合、現在オープンしているウインドウのリストを使用し、
* それらを選択するための MenuItem を追加する。
* リストをインスペクタとカルテに整理 by pns
*/
public void menuSelected(MenuEvent e) {
// 全てリムーブする
JMenu wm = (JMenu) e.getSource();
wm.removeAll();
// リストから新規に生成する
Action action;
String name;
int count = 0;
// まず,カルテとインスペクタ以外
for (WindowSupport ws : allWindows) {
action = ws.getWindowAction();
name = action.getValue(Action.NAME).toString();
if (!name.contains("インスペクタ") && !name.contains("カルテ")) {
wm.add(action);
count ++;
}
}
// カルテ,インスペクタが開いていない場合はリターン
if (allWindows.size() == count) return;
count = 0;
wm.addSeparator();
// 次にカルテ
for (WindowSupport ws : allWindows) {
action = ws.getWindowAction();
name = action.getValue(Action.NAME).toString();
if (name.contains("カルテ")) {
action.putValue(Action.SMALL_ICON, getIcon(ws.getFrame()));
wm.add(action);
count++;
}
}
if (count != 0) {
wm.addSeparator();
count = 0;
}
// 次にインスペクタ
for (WindowSupport ws : allWindows) {
action = ws.getWindowAction();
name = action.getValue(Action.NAME).toString();
if (name.contains("インスペクタ")) {
action.putValue(Action.SMALL_ICON, getIcon(ws.getFrame()));
wm.add(action);
count++;
}
}
// インスペクタウインドウを整列する
if (count != 0) {
wm.addSeparator();
count = 0;
Action a = new ArrangeInspectorAction();
wm.add(a);
}
}
/**
* インスペクタを整列する action
*/
class ArrangeInspectorAction extends AbstractAction {
public ArrangeInspectorAction() {
putValue(Action.NAME, "インスペクタを整列");
putValue(Action.SMALL_ICON, GUIConst.ICON_WINDOWS_22);
putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_UNDERSCORE, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
}
public void actionPerformed(ActionEvent e) {
JFrame f;
int x = INITIAL_X; int y = INITIAL_Y; int width = 0; int height = 0;
for (WindowSupport ws : allWindows) {
f = ws.getFrame();
if (f.getTitle().contains("インスペクタ")) {
if (width == 0) width = f.getBounds().width;
if (height == 0) height = f.getBounds().height;
f.setBounds(x, y, width, height);
f.toFront();
x += INITIAL_DX; y += INITIAL_DY;
}
}
}
}
//pns$
public void menuDeselected(MenuEvent e) {
}
public void menuCanceled(MenuEvent e) {
}
public static ImageIcon getIcon(JFrame frame) {
if (frame.isActive()) return GUIConst.ICON_STATUS_BUSY_16;
return GUIConst.ICON_STATUS_OFFLINE_16;
}
}