package open.dolphin.impl.pinfo; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Toolkit; import java.awt.datatransfer.StringSelection; import java.awt.event.*; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; import javax.swing.*; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableColumn; import open.dolphin.client.AbstractChartDocument; import open.dolphin.client.ClientContext; import open.dolphin.delegater.PatientDelegater; import open.dolphin.helper.DBTask; import open.dolphin.infomodel.PVTHealthInsuranceModel; import open.dolphin.infomodel.PVTPublicInsuranceItemModel; import open.dolphin.infomodel.PatientModel; import open.dolphin.table.StripeTableCellRenderer; import open.dolphin.util.AgeCalculater; /** * Documet to show Patient and Health Insurance info. * * @author Kazushi Minagawa, Digital Globe, Inc. */ public class PatientInfoDocument extends AbstractChartDocument { // 患者属性名 //s.oh^ 2014/08/29 患者情報の追加 //private static final String[] PATIENT_ATTRS = { // "患者 ID", "氏 名", "カナ", "ローマ字 *","性 別", "生年月日", "国 籍 *", "婚姻状況 *", "郵便番号", "住 所", "電 話", "携帯電話 *", "電子メール *" //}; //private static final String[] PATIENT_ATTRS_TEMP = { // "患者 ID", "氏 名", "カナ", "ローマ字","性 別", "生年月日", "国 籍", "婚姻状況", "郵便番号", "住 所", "電 話", "携帯電話", "電子メール" //}; private final String[] PATIENT_ATTRS; private final String[] PATIENT_ATTRS_TEMP; //s.oh$ private final String INFO; // カラム名 private final String[] COLUMN_NAMES; // 編集可能な行 //s.oh^ 2014/08/29 患者情報の追加 //private static final int[] EDITABLE_ROWS = {3, 6, 7, 11, 12}; private static final int[] EDITABLE_ROWS = {3, 6, 7, 11, 12, 13, 14, 15, 16, 17, 18}; //s.oh$ // 保存ボタン private JButton saveBtn; // テーブルモデル private PatientInfoTableModel pModel; // 属性表示テーブル private JTable pTable; // State Context private StateContext stateMgr; /** * Creates new PatientInfoDocument */ public PatientInfoDocument() { // Resource Injection java.util.ResourceBundle bundle = ClientContext.getMyBundle(PatientInfoDocument.class); setTitle(bundle.getString("title.document")); PATIENT_ATTRS = bundle.getString("attributes.patient").split(","); PATIENT_ATTRS_TEMP = bundle.getString("attributes.patient.tmp").split(","); INFO = bundle.getString("labelText.editing"); COLUMN_NAMES = bundle.getString("columnHeader.table").split(","); } private void initialize() { JComponent compo = createComponent(); // 保存ボタンを生成する JPanel cmdPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); cmdPanel.add(new JLabel(ClientContext.getImageIconArias("icon_info_small"))); cmdPanel.add(new JLabel(INFO)); saveBtn = new JButton(ClientContext.getImageIconArias("icon_save_small")); saveBtn.setEnabled(false); saveBtn.addActionListener((ActionEvent e) -> { save(); }); cmdPanel.add(saveBtn); JPanel content = new JPanel(new BorderLayout()); content.add(cmdPanel, BorderLayout.NORTH); content.add(compo, BorderLayout.CENTER); JPanel myPanel = getUI(); myPanel.setLayout(new BorderLayout()); myPanel.add(content, BorderLayout.CENTER); myPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 11, 11)); stateMgr = new StateContext(); enter(); } @Override public void start() { initialize(); } @Override public void stop() { } @Override public void enter() { super.enter(); if (stateMgr != null) { stateMgr.enter(); } } @Override public boolean isDirty() { if (stateMgr != null) { return stateMgr.isDirtyState(); } else { return super.isDirty(); } } /** * 患者情報を更新する。 */ @Override public void save() { final PatientModel update = getContext().getPatient(); final PatientDelegater pdl = new PatientDelegater(); DBTask task = new DBTask<Void, Void>(getContext()) { @Override public Void doInBackground() throws Exception { pdl.updatePatient(update); return null; } @Override public void succeeded(Void result) { if (boundSupport!=null) { setChartDocDidSave(true); return; } stateMgr.processSavedEvent(); } }; task.execute(); } private JComponent createComponent() { // 患者モデルを取得する PatientModel patient = getContext().getPatient(); Collection<PVTHealthInsuranceModel> insList = patient.getPvtHealthInsurances(); // 患者情報テーブルを生成する pModel = new PatientInfoTableModel(patient, PATIENT_ATTRS, COLUMN_NAMES); pTable = new JTable(pModel); // レンダラ StripeTableCellRenderer rederer = new StripeTableCellRenderer(); rederer.setTable(pTable); rederer.setDefaultRenderer(); // 行の高さ pTable.setRowHeight(ClientContext.getMoreHigherRowHeight()); // spacing pTable.setIntercellSpacing(new Dimension(2,2)); // エディタ TableColumn column = pTable.getColumnModel().getColumn(1); DefaultCellEditor de = new DefaultCellEditor(new JTextField()); de.setClickCountToStart(2); column.setCellEditor(de); // 幅 pTable.getColumnModel().getColumn(0).setPreferredWidth(200); pTable.getColumnModel().getColumn(1).setPreferredWidth(500); //----------------------------------------------- // 家族カルテ機能を実装する^ //----------------------------------------------- // pTable.setTransferHandler(new PatientInfoTableTransferHandler()); //----------------------------------------------- // Copy 機能を実装する //----------------------------------------------- KeyStroke copy = KeyStroke.getKeyStroke(KeyEvent.VK_C, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()); String actionText = ClientContext.getMyBundle(PatientInfoDocument.class).getString("actionText.copy"); final AbstractAction copyAction = new AbstractAction(actionText) { @Override public void actionPerformed(ActionEvent ae) { copyRow(); } }; pTable.getInputMap().put(copy, "Copy"); pTable.getActionMap().put("Copy", copyAction); //------------------------------------------------- // Copy menu を加える //------------------------------------------------- pTable.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent me) { mabeShowPopup(me); } @Override public void mouseReleased(MouseEvent me) { mabeShowPopup(me); } public void mabeShowPopup(MouseEvent e) { if (!e.isPopupTrigger()) { return; } int row = pTable.rowAtPoint(e.getPoint()); if (row < 0) { return; } JPopupMenu contextMenu = new JPopupMenu(); contextMenu.add(new JMenuItem(copyAction)); contextMenu.show(e.getComponent(), e.getX(), e.getY()); } }); // 配置する JPanel panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); panel.add(pTable); // // 健康保険情報テーブルを生成する // if (insList != null) { for (PVTHealthInsuranceModel insurance : insList) { HealthInsuranceTableModel hModel = new HealthInsuranceTableModel( insurance, COLUMN_NAMES); JTable hTable = new JTable(hModel); // spacing hTable.setIntercellSpacing(new Dimension(2,2)); // レンダラ StripeTableCellRenderer sr = new StripeTableCellRenderer(); sr.setTable(hTable); sr.setDefaultRenderer(); // 行の高さ hTable.setRowHeight(ClientContext.getMoreHigherRowHeight()); // 幅 hTable.getColumnModel().getColumn(0).setPreferredWidth(200); hTable.getColumnModel().getColumn(1).setPreferredWidth(500); // 配置する panel.add(Box.createVerticalStrut(7)); panel.add(hTable); } } JScrollPane scroller = new JScrollPane(panel); return scroller; } // // Dropされた患者を家族カルテに登録する // private void importFamily(PatientModel model) { // // final JButton save = new JButton("登 録"); // final JButton cancel = new JButton((String)UIManager.get("OptionPane.cancelButtonText")); // save.setEnabled(false); // // StringBuilder sb = new StringBuilder(); // sb.append(model.getFullName()); // sb.append(" さんを家族として登録します。"); // String msg = sb.toString(); // final String patientId = model.getPatientId(); // // JLabel lbl = new JLabel("続柄:"); //// final String[] relations = new String[]{ //// "", "父", "母", "----","兄", "弟", "姉", "妹","----", "子供", "----", "祖父", "祖母","----","孫", "----","夫", "妻", "----","その他" //// }; // final String[] relations = new String[]{ // "", "兄弟姉妹", "------","親", "子供","------","祖父母","孫","------","夫婦", "------","その他" // }; // final JComboBox cmb = new JComboBox(relations); // cmb.addItemListener(new ItemListener() { // @Override // public void itemStateChanged(ItemEvent e) { // if (e.getStateChange() == ItemEvent.SELECTED) { // save.setEnabled(cmb.getSelectedIndex()!=0); // } // } // }); // JPanel p = new JPanel(); // p.setLayout(new FlowLayout(FlowLayout.LEFT)); // p.add(lbl); // p.add(cmb); // // Object[] message = new Object[2]; // message[0] = msg; // message[1] = p; // // JOptionPane pane = new JOptionPane( // message, // JOptionPane.QUESTION_MESSAGE, // JOptionPane.DEFAULT_OPTION, // null, // new Object[]{save, cancel}, // save); // // final JDialog dialog = pane.createDialog(getUI(), ClientContext.getFrameTitle("家族登録")); // dialog.setModal(true); // // save.addActionListener(new ActionListener() { // @Override // public void actionPerformed(ActionEvent ae) { // dialog.setVisible(false); // dialog.dispose(); // StringBuilder sb = new StringBuilder(); // sb.append((String)cmb.getSelectedItem()); // sb.append("-"); // sb.append(patientId); // System.err.println(sb.toString()); // } // }); // cancel.addActionListener(new ActionListener() { // @Override // public void actionPerformed(ActionEvent ae) { // dialog.setVisible(false); // dialog.dispose(); // } // }); // dialog.setVisible(true); // } /** * 選択されている行をコピーする。 */ public void copyRow() { StringBuilder sb = new StringBuilder(); int numRows = pTable.getSelectedRowCount(); int[] rowsSelected = pTable.getSelectedRows(); int numColumns = pTable.getColumnCount(); for (int i = 0; i < numRows; i++) { StringBuilder s = new StringBuilder(); for (int col = 0; col < numColumns; col++) { Object o = pTable.getValueAt(rowsSelected[i], col); if (o!=null) { //s.append(o.toString()); if(col == 0 && i < rowsSelected.length && rowsSelected[i] < PATIENT_ATTRS_TEMP.length) { s.append(PATIENT_ATTRS_TEMP[rowsSelected[i]]); }else{ s.append(o.toString()); } } s.append(","); } if (s.length()>0) { s.setLength(s.length()-1); } sb.append(s.toString()).append("\n"); } if (sb.length() > 0) { StringSelection stsel = new StringSelection(sb.toString()); Toolkit.getDefaultToolkit().getSystemClipboard().setContents(stsel, stsel); } } /** * 患者情報を表示する TableModel クラス。 */ protected class PatientInfoTableModel extends AbstractTableModel { // 患者モデル private final PatientModel patient; // 属性名の配列 private final String[] attributes; // カラム名の配列 private final String[] columnNames; public PatientInfoTableModel(PatientModel patient, String[] attrs, String[] columnNames) { this.patient = patient; this.attributes = attrs; this.columnNames = columnNames; } @Override public int getColumnCount() { return columnNames.length; } @Override public int getRowCount() { return PATIENT_ATTRS.length; } @Override public boolean isCellEditable(int row, int col) { //minagawa^ 排他制御 // 編集可能な行である場合に true if (getContext().isReadOnly()) { return false; } boolean ret = false; if (col == 1) { for (int i = 0; i < EDITABLE_ROWS.length; i++) { if (row == EDITABLE_ROWS[i]) { ret = true; break; } } } return ret; } @Override public Object getValueAt(int row, int col) { String ret = null; if (col == 0) { // // 属性名を返す // ret = attributes[row]; } else if (col == 1 && patient != null) { // // 患者属性を返す // switch (row) { case 0: ret = patient.getPatientId(); break; case 1: ret = patient.getFullName(); break; case 2: ret = patient.getKanaName(); break; case 3: ret = patient.getRomanName(); break; case 4: ret = patient.getGender(); ret = ret.toLowerCase(); java.util.ResourceBundle bundle = ClientContext.getMyBundle(PatientInfoDocument.class); String male = bundle.getString("text.male"); String female = bundle.getString("text.female"); if (ret.startsWith("m") || ret.startsWith(male)) { ret = male; } else if (ret.startsWith("f") || ret.startsWith(female)) { ret = female; } break; case 5: int[] spec = AgeCalculater.getAgeSpec(patient.getBirthday()); StringBuilder sb = new StringBuilder(); if (spec[0]!=-1) { String fmt = ClientContext.getMyBundle(PatientInfoDocument.class).getString("meesageFormat.age"); MessageFormat msf = new MessageFormat(fmt); sb.append(msf.format(new Object[]{spec[0],spec[1],spec[2]})); } sb.append(" (").append(patient.getBirthday()).append(")"); ret = sb.toString(); break; case 6: ret = patient.getNationality(); break; case 7: ret = patient.getMaritalStatus(); break; case 8: ret = patient.contactZipCode(); break; case 9: ret = patient.contactAddress(); if (ret != null) { ret = ret.replaceAll(" ", " "); } break; case 10: ret = patient.getTelephone(); break; case 11: ret = patient.getMobilePhone(); break; case 12: ret = patient.getEmail(); break; //s.oh^ 2014/08/29 患者情報の追加 case 13: ret = patient.getReserve1(); break; case 14: ret = patient.getReserve2(); break; case 15: ret = patient.getReserve3(); break; case 16: ret = patient.getReserve4(); break; case 17: ret = patient.getReserve5(); break; case 18: ret = patient.getReserve6(); break; //s.oh$ } } return ret; } /** * 属性値を変更する。 * @param value 属性値 * @param row 行 * @param col 列 */ @Override public void setValueAt(Object value, int row, int col) { if (value == null || value.equals("") || col == 0) { return; } String strValue = (String) value; switch (row) { case 3: // // ローマ字 // patient.setRomanName(strValue); stateMgr.processDirtyEvent(); break; case 6: // // 国籍 // patient.setNationality(strValue); stateMgr.processDirtyEvent(); break; case 7: // // 婚姻状況 // patient.setMaritalStatus(strValue); stateMgr.processDirtyEvent(); break; case 11: // // 携帯電話 // patient.setMobilePhone(strValue); stateMgr.processDirtyEvent(); break; case 12: // // 電子メール // patient.setEmail(strValue); stateMgr.processDirtyEvent(); break; //s.oh^ 2014/08/29 患者情報の追加 case 13: patient.setReserve1(strValue); stateMgr.processDirtyEvent(); break; case 14: patient.setReserve2(strValue); stateMgr.processDirtyEvent(); break; case 15: patient.setReserve3(strValue); stateMgr.processDirtyEvent(); break; case 16: patient.setReserve4(strValue); stateMgr.processDirtyEvent(); break; case 17: patient.setReserve5(strValue); stateMgr.processDirtyEvent(); break; case 18: patient.setReserve6(strValue); stateMgr.processDirtyEvent(); break; //s.oh$ } } } /** * 保険情報を表示する TableModel クラス。 */ protected class HealthInsuranceTableModel extends AbstractTableModel { private final String[] columnNames; private final ArrayList<String[]> data; public HealthInsuranceTableModel(PVTHealthInsuranceModel insurance, String[] columnNames) { this.columnNames = columnNames; data = getData(insurance); } private ArrayList getData(PVTHealthInsuranceModel insurance) { if (insurance == null) { return null; } ArrayList<String[]> list = new ArrayList<>(); java.util.ResourceBundle bundle = ClientContext.getMyBundle(PatientInfoDocument.class); String[] rowData = new String[2]; rowData[0] = bundle.getString("hitem.0"); rowData[1] = insurance.getInsuranceClass(); list.add(rowData); rowData = new String[2]; rowData[0] = bundle.getString("hitem.1"); rowData[1] = insurance.getInsuranceClassCode(); list.add(rowData); rowData = new String[2]; rowData[0] = bundle.getString("hitem.2"); rowData[1] = insurance.getInsuranceNumber(); list.add(rowData); rowData = new String[2]; rowData[0] = bundle.getString("hitem.3"); rowData[1] = insurance.getClientGroup(); list.add(rowData); rowData = new String[2]; rowData[0] = bundle.getString("hitem.4"); rowData[1] = insurance.getClientNumber(); list.add(rowData); rowData = new String[2]; rowData[0] = bundle.getString("hitem.5"); String test = insurance.getFamilyClass(); if (test.equals("true")) { test = bundle.getString("hitem.self"); } else { test = bundle.getString("hitem.family"); } rowData[1] = test; list.add(rowData); rowData = new String[2]; rowData[0] = bundle.getString("hitem.6"); rowData[1] = insurance.getStartDate(); list.add(rowData); rowData = new String[2]; rowData[0] = bundle.getString("hitem.7"); rowData[1] = insurance.getExpiredDate(); list.add(rowData); String[] vals = insurance.getContinuedDisease(); if (vals != null) { int count = vals.length; for (int i = 0; i < count; i++) { rowData = new String[2]; rowData[0] = bundle.getString("hitem.8"); rowData[1] = vals[i]; list.add(rowData); } } rowData = new String[2]; rowData[0] = bundle.getString("hitem.9"); rowData[1] = insurance.getPayInRatio(); list.add(rowData); rowData = new String[2]; rowData[0] = bundle.getString("hitem.10"); rowData[1] = insurance.getPayOutRatio(); list.add(rowData); PVTPublicInsuranceItemModel[] pbi = insurance .getPVTPublicInsuranceItem(); if (pbi == null) { return list; } int count = pbi.length; for (int i = 0; i < count; i++) { PVTPublicInsuranceItemModel item = pbi[i]; rowData = new String[2]; rowData[0] = bundle.getString("hitem.11"); rowData[1] = item.getPriority(); list.add(rowData); rowData = new String[2]; rowData[0] = bundle.getString("hitem.12"); rowData[1] = item.getProviderName(); list.add(rowData); rowData = new String[2]; rowData[0] = bundle.getString("hitem.13"); rowData[1] = item.getProvider(); list.add(rowData); rowData = new String[2]; rowData[0] = bundle.getString("hitem.14"); rowData[1] = item.getRecipient(); list.add(rowData); rowData = new String[2]; rowData[0] = bundle.getString("hitem.15"); rowData[1] = item.getStartDate(); list.add(rowData); rowData = new String[2]; rowData[0] = bundle.getString("hitem.16"); rowData[1] = item.getExpiredDate(); list.add(rowData); rowData = new String[2]; rowData[0] = bundle.getString("hitem.17"); rowData[1] = item.getPaymentRatio(); list.add(rowData); rowData = new String[2]; rowData[0] = bundle.getString("hitem.18"); rowData[1] = item.getPaymentRatioType(); list.add(rowData); } return list; } @Override public int getColumnCount() { return columnNames.length; } @Override public int getRowCount() { return data != null ? data.size() : 5; } @Override public Object getValueAt(int row, int col) { if (data == null) { return null; } if (row >= data.size()) { return null; } String[] rowData = (String[]) data.get(row); return (Object) rowData[col]; } } abstract class State { public abstract void enter(); } class CleanState extends State { @Override public void enter() { saveBtn.setEnabled(false); setDirty(false); } } class DirtyState extends State { @Override public void enter() { saveBtn.setEnabled(true); } } class StateContext { private final CleanState cleanState = new CleanState(); private final DirtyState dirtyState = new DirtyState(); private State curState; public StateContext() { curState = cleanState; } public void enter() { curState.enter(); } public void processSavedEvent() { curState = cleanState; this.enter(); } public void processDirtyEvent() { if (!isDirtyState()) { curState = dirtyState; this.enter(); } } public boolean isDirtyState() { return curState == dirtyState; } } }