package open.dolphin.client;
import java.awt.Component;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.swing.BorderFactory;
import javax.swing.JMenuItem;
import javax.swing.JTextField;
import open.dolphin.infomodel.*;
import open.dolphin.ui.MyJPopupMenu;
/**
* DiagnosisDocument のポップアップメニューを一手に引き受ける
* @author pns
*/
public class DiagnosisDocumentPopupMenu extends MouseAdapter implements MouseMotionListener,PropertyChangeListener {
private static final long serialVersionUID = 1L;
private DiagnosisDocument diagnosisDocument;
private DiagnosisDocumentTable diagTable;
private DiagnosisDocumentTableModel diagTableModel;
private JTextField textField;
private JTextField startDateField;
private JTextField endDateField;
private DiagnosisDocument parent;
private int[] lastVisitYmd;
private MyJPopupMenu calendarPopup;
private MyJPopupMenu diagPopup;
private MyJPopupMenu categoryPopup;
private MyJPopupMenu outcomePopup;
private int targetColumn;
private PropertyChangeSupport boundSupport;
// 病名修飾語リスト
private enum DiagnosisPreposition {
RIGHT("右", "2056"), LEFT("左", "2049"), BOTH("両", "2057");
public final String desc;
public final String code;
private DiagnosisPreposition(String desc, String code) {
this.desc = desc;
this.code = code;
}
}
private enum DiagnosisPostposition {
EXACERBATION("の急性増悪", "8061"), INFECTION("の二次感染", "8069"), RECURRENCE("の再発", "8065"),
POSTOPERATIVE("の術後", "8048"), POSTTREATMENT("の治療後", "8075");
public final String desc;
public final String code;
private DiagnosisPostposition(String desc, String code) {
this.desc = desc;
this.code = code;
}
}
public DiagnosisDocumentPopupMenu(DiagnosisDocument parent) {
super();
this.parent = parent;
diagnosisDocument = parent;
createDiagnosisPopupMenu();
createCategoryPopupMenu();
createOutcomePopupMenu();
boundSupport = new PropertyChangeSupport(new Object());
diagTable = parent.getDiagnosisTable();
diagTableModel = (DiagnosisDocumentTableModel) diagTable.getModel();
startDateField = parent.getStartDateField();
endDateField = parent.getEndDateField();
lastVisitYmd = parent.getLastVisitYmd();
addMouseListeners();
}
// コンストラクタ内で this を使うのは危険らしい
private void addMouseListeners() {
diagTable.addMouseListener(this);
startDateField.addMouseListener(this);
endDateField.addMouseListener(this);
}
public PropertyChangeSupport getBoundSupport() {
return boundSupport;
}
@Override
public void mousePressed(MouseEvent e) {
// マウスがクリックされた column を記録
targetColumn = diagTable.columnAtPoint(e.getPoint());
if (e.isPopupTrigger()) rightPressed(e);
else leftPressed(e);
}
// windows では released で popupTrigger が発生するらしい
@Override
public void mouseReleased(MouseEvent e) {
targetColumn = diagTable.columnAtPoint(e.getPoint());
if (e.isPopupTrigger()) rightPressed(e);
}
/**
* 右クリックの処理
* @param e
*/
private void rightPressed(MouseEvent e) {
// マウス位置の行が選択されていなければ,選択し直す
boolean shouldReselect = true;
int[] selectedRows = diagTable.getSelectedRows();
int row = diagTable.rowAtPoint(e.getPoint());
for (int r : selectedRows) {
// 選択とマウスが一致している場合
if (r == row) {
shouldReselect = false;
break;
}
}
if (shouldReselect) {
diagTable.requestFocusInWindow();
diagTable.getSelectionModel().setSelectionInterval(row, row);
}
// source が JTextField で DATE の 場合
Object source = e.getSource();
if (source == startDateField || source == endDateField) {
textField = (JTextField) source;
popupCalendar(e);
return;
}
// CellEditor を立ち上げずに右クリックした場合
int column = diagTable.columnAtPoint(e.getPoint());
switch(column) {
case DiagnosisDocument.DIAGNOSIS_COL:
popupDiagnosis(e);
break;
case DiagnosisDocument.CATEGORY_COL:
popupCategory(e);
break;
case DiagnosisDocument.OUTCOME_COL:
popupOutcome(e);
break;
case DiagnosisDocument.START_DATE_COL:
textField = startDateField;
popupCalendar(e);
break;
case DiagnosisDocument.END_DATE_COL:
textField = endDateField;
popupCalendar(e);
break;
}
}
/**
* 左クリックの処理
* @param e
*/
private void leftPressed(MouseEvent e) {
if (e.getClickCount() == 2) {
// 診断名をダブルクリックしたらエディタを立ち上げることにした thx to masuda sensei
int column = diagTable.getSelectedColumn();
if (column == DiagnosisDocument.DIAGNOSIS_COL) {
int row = diagTable.getSelectedRow();
row = diagTable.convertRowIndexToModel(row);
RegisteredDiagnosisModel model = (RegisteredDiagnosisModel) diagTableModel.getObject(row);
diagnosisDocument.openEditor3(model);
}
}
}
/**
* カレンダーポップアップを出す
* @param e
*/
private void popupCalendar(MouseEvent e) {
calendarPopup = new MyJPopupMenu();
calendarPopup.setBorder(BorderFactory.createEmptyBorder());
GregorianCalendar gc = new GregorianCalendar();
int this_month = gc.get(Calendar.MONTH);
int dif = lastVisitYmd[1] - this_month; //lastVisit, this_month は gc なので,両者とも値が0-11 になる
if (dif > 0) dif -= 12;
CalendarCardPanel cc = new CalendarCardPanel(ClientContext.getEventColorTable(), dif);
cc.addPropertyChangeListener(CalendarCardPanel.PICKED_DATE, this);
cc.setCalendarRange(new int[]{-12, 0});
calendarPopup.insert(cc, 0);
calendarPopup.show(e.getComponent(), e.getX(), e.getY());
}
/**
* PropertyChange のお仕事
* @param e
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
String prop = e.getPropertyName();
// カレンダーで選択した場合
if (CalendarCardPanel.PICKED_DATE.equals(prop)) {
SimpleDate sd = (SimpleDate) e.getNewValue();
String date = SimpleDate.simpleDateToMmldate(sd);
textField.setText(date);
int[] rows = diagTable.getSelectedRows();
for (int r : rows) {
int row = diagTable.convertRowIndexToModel(r);
diagTableModel.setValueAt(date, row, targetColumn);
}
calendarPopup.setVisible(false);
calendarPopup = null;
}
}
/**
* 診断修飾語ポップアップを出す
* @param e
*/
private void popupDiagnosis(final MouseEvent e) {
// diagPopup は最初に作ってあるので show するだけでよい
diagPopup.show(e.getComponent(), e.getX(), e.getY());
}
/**
* 病名修飾ポップアップメニュー作成
*/
private void createDiagnosisPopupMenu() {
diagPopup = new MyJPopupMenu();
// Diagnosis preposition 項目の作成
for (DiagnosisPreposition p : DiagnosisPreposition.values()) {
JMenuItem item = new JMenuItem(p.desc);
item.addActionListener(new DiagAction(p));
diagPopup.add(item);
}
diagPopup.addSeparator();
// Diagnosis postposition 項目の作成
for (DiagnosisPostposition p : DiagnosisPostposition.values()) {
JMenuItem item = new JMenuItem(p.desc);
item.addActionListener(new DiagAction(p));
diagPopup.add(item);
}
}
/**
* DiagnosisInspector で diagPopup を使う
* @return
*/
public MyJPopupMenu getDiagPopup() {
return diagPopup;
}
/**
* DiagnosisInspector で outcomePopup を使う
* @return
*/
public MyJPopupMenu getOutcomePopup() {
return outcomePopup;
}
/**
* DiagnosisInspector で categoryPopup を使う
* @return
*/
public MyJPopupMenu getCategoryPopup() {
return categoryPopup;
}
/**
* 病名修飾の実務 action
*/
private class DiagAction implements ActionListener {
Object modifier;
boolean prep; // preposition or postposition
public DiagAction(DiagnosisPreposition p) {
modifier = p;
prep = true;
}
public DiagAction(DiagnosisPostposition p) {
modifier = p;
prep = false;
}
@Override
public void actionPerformed(ActionEvent e) {
int[] rows = diagTable.getSelectedRows();
for (int r : rows) {
int row = diagTable.convertRowIndexToModel(r);
RegisteredDiagnosisModel rd = (RegisteredDiagnosisModel) diagTableModel.getObject(row);
// 新しく作った診断名を設定
final String newDiagDesc;
String newDiagCode;
if (prep) {
newDiagDesc = ((DiagnosisPreposition)modifier).desc + rd.getDiagnosis();
newDiagCode = ((DiagnosisPreposition)modifier).code + "." + rd.getDiagnosisCode();
} else {
newDiagDesc = rd.getDiagnosis() + ((DiagnosisPostposition)modifier).desc;
newDiagCode = rd.getDiagnosisCode() + "." + ((DiagnosisPostposition)modifier).code;
}
DiagnosisLiteModel newDiag = new DiagnosisLiteModel(rd);
newDiag.setDiagnosisDesc(newDiagDesc);
newDiag.setDiagnosisCode(newDiagCode);
diagTableModel.setValueAt(newDiag, row, DiagnosisDocument.DIAGNOSIS_COL);
// diagnosisInspector にも知らせる
((ChartImpl)parent.getContext()).getDiagnosisInspector().update(diagTableModel);
}
}
}
/**
* 主病名/疑い病名ポップアップを出す
* @param e
*/
private void popupCategory(MouseEvent e) {
categoryPopup.show(e.getComponent(), e.getX(), e.getY());
}
/**
* 転帰ポップアップを出す
* @param e
*/
private void popupOutcome(MouseEvent e) {
outcomePopup.show(e.getComponent(), e.getX(), e.getY());
}
/**
* 主病名/疑い病名ポップアップを作る
*/
private void createCategoryPopupMenu() {
categoryPopup = new MyJPopupMenu();
for (DiagnosisDocument.DiagnosisCategory c : DiagnosisDocument.DiagnosisCategory.values()) {
JMenuItem item = new JMenuItem(c.model.getDiagnosisCategoryDesc());
item.addActionListener(new CategoryOutcomeAction(c.model));
categoryPopup.add(item);
}
}
/**
* 転帰ポップアップを作る
*/
private void createOutcomePopupMenu() {
outcomePopup = new MyJPopupMenu();
for (DiagnosisDocument.DiagnosisOutcome o : DiagnosisDocument.DiagnosisOutcome.values()) {
JMenuItem item = new JMenuItem(o.model.getOutcomeDesc());
item.addActionListener(new CategoryOutcomeAction(o.model));
outcomePopup.add(item);
}
}
/**
* 主病名/疑い病名,転帰の実務
*/
private class CategoryOutcomeAction implements ActionListener {
Object model;
int column;
public CategoryOutcomeAction() {
super();
}
public CategoryOutcomeAction(DiagnosisCategoryModel model) {
this();
this.model = model;
this.column = DiagnosisDocument.CATEGORY_COL;
}
public CategoryOutcomeAction(DiagnosisOutcomeModel model) {
this();
this.model = model;
this.column = DiagnosisDocument.OUTCOME_COL;
}
@Override
public void actionPerformed(ActionEvent e) {
// 処理途中に insert が発生して選択行の行番号が変わってしまうことがあるので hash 処理する
int[] rows = diagTable.getSelectedRows();
int[] hashArray = diagTable.convertViewRowsToHashArray(rows);
for (int hash : hashArray) {
int row = diagTable.convertHashToModelRow(hash);
diagTable.getModel().setValueAt(model, row, column);
}
// diagnosisInspector にも知らせる
((ChartImpl)parent.getContext()).getDiagnosisInspector().update(diagTableModel);
}
}
/**
* 外部からポップアップの action を使うためのメソッド群
*/
public void doClickDiagPopup(String s) {
doClickPopup(diagPopup, s);
}
public void doClickCategoryPopup(String s) {
doClickPopup(categoryPopup, s);
}
public void doClickOutcomePopup(String s) {
doClickPopup(outcomePopup, s);
}
private void doClickPopup(MyJPopupMenu popup, String s) {
JMenuItem m = null;
for(Component c : popup.getComponents()) {
if (c instanceof JMenuItem) {
if (s.equals(((JMenuItem)c).getText())) {
m = (JMenuItem) c;
break;
}
}
}
if (m != null) m.doClick();
}
}