package open.dolphin.client;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.datatransfer.StringSelection;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import javax.swing.*;
import javax.swing.table.TableColumn;
import open.dolphin.delegater.DocumentDelegater;
import open.dolphin.helper.DBTask;
import open.dolphin.infomodel.IInfoModel;
import open.dolphin.infomodel.ModelUtils;
import open.dolphin.infomodel.ObservationModel;
import open.dolphin.infomodel.PhysicalModel;
import open.dolphin.project.Project;
import open.dolphin.table.ListTableModel;
import open.dolphin.table.StripeTableCellRenderer;
/**
* 身長体重インスペクタクラス。
*
* @author Kazushi Minagawa, Digital Globe, Inc.
*/
public final class PhysicalInspector {
private ListTableModel<PhysicalModel> tableModel;
private PhysicalView view;
private final ChartImpl context;
/**
* PhysicalInspectorオブジェクトを生成する。
* @param context
*/
public PhysicalInspector(ChartImpl context) {
this.context = context;
initComponents();
update();
}
public Chart getContext() {
return context;
}
public void clear() {
tableModel.clear();
}
/**
* レイアウトパネルを返す。
* @return レイアウトパネル
*/
public JPanel getPanel() {
return (JPanel) view;
}
/**
* GUIコンポーネントを初期化する。
*/
private void initComponents() {
view = new PhysicalView();
java.util.ResourceBundle bundle = ClientContext.getMyBundle(PhysicalInspector.class);
// カラム名 & 属性値を取得するためのメソッド名
String columsLine = bundle.getString("columnsLine.table");
String methodsLine = bundle.getString("methodsLine.table");
String[] columnNames = columsLine.split(",");
String[] methodNames = methodsLine.split(",");
// 身長体重テーブルを生成する
tableModel = new ListTableModel<>(columnNames, 0, methodNames, null);
view.getTable().setModel(tableModel);
view.getTable().setFillsViewportHeight(true);
view.getTable().getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
//s.oh^ 2014/04/02 閲覧権限の制御
if(!context.isReadOnly()) {
String toolTipText = bundle.getString("tooTipText.table");
view.getTable().setToolTipText(toolTipText);
}
//s.oh$
//OddEvenRowRenderer heightR = new OddEvenRowRenderer();
StripeTableCellRenderer heightR = new StripeTableCellRenderer();
heightR.setHorizontalAlignment(SwingConstants.LEFT);
heightR.setTable(view.getTable());
view.getTable().getColumnModel().getColumn(0).setCellRenderer(heightR);
//OddEvenRowRenderer weightR = new OddEvenRowRenderer();
StripeTableCellRenderer weightR = new StripeTableCellRenderer();
weightR.setHorizontalAlignment(SwingConstants.LEFT);
weightR.setTable(view.getTable());
view.getTable().getColumnModel().getColumn(1).setCellRenderer(weightR);
//BMIRenderer bmiR = new BMIRenderer();
StripeTableCellRenderer bmiR = new StripeTableCellRenderer();
bmiR.setHorizontalAlignment(SwingConstants.LEFT);
bmiR.setTable(view.getTable());
view.getTable().getColumnModel().getColumn(2).setCellRenderer(bmiR);
StripeTableCellRenderer rendere = new StripeTableCellRenderer();
rendere.setTable(view.getTable());
view.getTable().getColumnModel().getColumn(3).setCellRenderer(rendere);
view.getTable().setRowHeight(ClientContext.getHigherRowHeight());
// 列幅を調整する カット&トライ
int[] cellWidth = new int[]{50,50,50,110};
for (int i = 0; i < cellWidth.length; i++) {
TableColumn column = view.getTable().getColumnModel().getColumn(i);
column.setPreferredWidth(cellWidth[i]);
}
//-----------------------------------------------
// Copy 機能を実装する
//-----------------------------------------------
KeyStroke copy = KeyStroke.getKeyStroke(KeyEvent.VK_C, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
String copyText = bundle.getString("actionText.copy");
final AbstractAction copyAction = new AbstractAction(copyText) {
@Override
public void actionPerformed(ActionEvent ae) {
copyRow();
}
};
view.getTable().getInputMap().put(copy, "Copy");
view.getTable().getActionMap().put("Copy", copyAction);
// 右クリックによる追加削除のメニューを登録する
if (!context.isReadOnly()) {
view.getTable().addMouseListener(new MouseAdapter() {
private void mabeShowPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
JPopupMenu pop = new JPopupMenu();
String addText = bundle.getString("menuText.add");
JMenuItem item = new JMenuItem(addText);
pop.add(item);
item.addActionListener((ActionEvent e1) -> {
PhysicalEditor npe = new PhysicalEditor(PhysicalInspector.this);
});
final int row = view.getTable().rowAtPoint(e.getPoint());
if (tableModel.getObject(row) != null) {
pop.add(new JSeparator());
JMenuItem item2 = new JMenuItem(copyAction);
pop.add(item2);
pop.add(new JSeparator());
String deleteText = bundle.getString("menuText.delete");
JMenuItem item3 = new JMenuItem(deleteText);
pop.add(item3);
item3.addActionListener((ActionEvent e1) -> {
delete(row);
});
}
pop.show(e.getComponent(), e.getX(), e.getY());
}
}
@Override
public void mousePressed(MouseEvent e) {
mabeShowPopup(e);
}
@Override
public void mouseReleased(MouseEvent e) {
mabeShowPopup(e);
}
});
}
}
private void scroll(boolean ascending) {
int cnt = tableModel.getObjectCount();
if (cnt > 0) {
int row = 0;
if (ascending) {
row = cnt - 1;
}
Rectangle r = view.getTable().getCellRect(row, row, true);
view.getTable().scrollRectToVisible(r);
}
}
/**
* 身長体重データを表示する。
*/
public void update() {
List<PhysicalModel> listH = context.getKarte().getHeights();
List<PhysicalModel> listW = context.getKarte().getWeights();
List<PhysicalModel> list = new ArrayList<>();
// 身長体重ともある場合
if (listH != null && listW != null) {
for (int i = 0; i < listH.size(); i++) {
PhysicalModel h = (PhysicalModel) listH.get(i);
String memo = h.getMemo();
if (memo == null) {
memo = h.getIdentifiedDate();
}
//
// 体重のメモが一致するものを見つける
//
PhysicalModel found = null;
for (int j = 0; j < listW.size(); j++) {
PhysicalModel w = (PhysicalModel) listW.get(j);
String memo2 = w.getMemo();
if (memo2 == null) {
memo2 = w.getIdentifiedDate();
}
if (memo2.equals(memo)) {
found = w;
PhysicalModel m = new PhysicalModel();
m.setHeightId(h.getHeightId());
m.setHeight(h.getHeight());
m.setWeightId(w.getWeightId());
m.setWeight(w.getWeight());
m.setIdentifiedDate(h.getIdentifiedDate());
m.setMemo(memo);
list.add(m);
break;
}
}
if (found != null) {
// 一致する体重はリストから除く
listW.remove(found);
} else {
// なければ身長のみを加える
list.add(h);
}
}
// 体重のリストが残っていればループする
if (listW.size() > 0) {
listW.stream().forEach((listW1) -> {
list.add(listW1);
});
}
} else if (listH != null) {
// 身長だけの場合
listH.stream().forEach((listH1) -> {
list.add(listH1);
});
} else if (listW != null) {
// 体重だけの場合
listW.stream().forEach((listW1) -> {
list.add(listW1);
});
}
if (list.isEmpty()) {
return;
}
boolean asc = Project.getBoolean(Project.DOC_HISTORY_ASCENDING, false);
if (asc) {
Collections.sort(list);
} else {
Collections.sort(list, Collections.reverseOrder());
}
tableModel.setDataProvider(list);
scroll(asc);
}
/**
* 身長体重データを追加する。
* @param model
*/
public void add(final PhysicalModel model) {
// 同定日
String confirmedStr = model.getIdentifiedDate();
Date confirmed = ModelUtils.getDateTimeAsObject(confirmedStr + "T00:00:00");
// 記録日
Date recorded = new Date();
final List<ObservationModel> addList = new ArrayList<>(2);
if (model.getHeight() != null) {
ObservationModel observation = new ObservationModel();
observation.setKarteBean(context.getKarte());
observation.setUserModel(Project.getUserModel());
observation.setObservation(IInfoModel.OBSERVATION_PHYSICAL_EXAM);
observation.setPhenomenon(IInfoModel.PHENOMENON_BODY_HEIGHT);
observation.setValue(model.getHeight());
observation.setUnit(IInfoModel.UNIT_BODY_HEIGHT);
observation.setConfirmed(confirmed); // 確定(同定日)
observation.setStarted(confirmed); // 適合開始日
observation.setRecorded(recorded); // 記録日
observation.setStatus(IInfoModel.STATUS_FINAL);
//observation.setMemo(model.getMemo());
addList.add(observation);
}
if (model.getWeight() != null) {
ObservationModel observation = new ObservationModel();
observation.setKarteBean(context.getKarte());
observation.setUserModel(Project.getUserModel());
observation.setObservation(IInfoModel.OBSERVATION_PHYSICAL_EXAM);
observation.setPhenomenon(IInfoModel.PHENOMENON_BODY_WEIGHT);
observation.setValue(model.getWeight());
observation.setUnit(IInfoModel.UNIT_BODY_WEIGHT);
observation.setConfirmed(confirmed); // 確定(同定日)
observation.setStarted(confirmed); // 適合開始日
observation.setRecorded(recorded); // 記録日
observation.setStatus(IInfoModel.STATUS_FINAL);
//observation.setMemo(model.getMemo());
addList.add(observation);
}
if (addList.isEmpty()) {
return;
}
DBTask task = new DBTask<List<Long>, Void>(context) {
@Override
protected List<Long> doInBackground() throws Exception {
java.util.logging.Logger.getLogger(this.getClass().getName()).fine("physical add doInBackground");
DocumentDelegater pdl = new DocumentDelegater();
List<Long> ids = pdl.addObservations(addList);
return ids;
}
@Override
protected void succeeded(List<Long> result) {
java.util.logging.Logger.getLogger(this.getClass().getName()).fine("physical add succeeded");
if (model.getHeight() != null && model.getWeight() != null) {
model.setHeightId(result.get(0));
model.setWeightId(result.get(1));
} else if (model.getHeight() != null) {
model.setHeightId(result.get(0));
} else {
model.setWeightId(result.get(0));
}
boolean asc = Project.getBoolean(Project.DOC_HISTORY_ASCENDING, false);
if (asc) {
tableModel.addObject(model);
} else {
tableModel.addObject(0, model);
}
scroll(asc);
}
};
task.execute();
}
/**
* 選択されている行をコピーする。
*/
public void copyRow() {
StringBuilder sb = new StringBuilder();
int numRows = view.getTable().getSelectedRowCount();
int[] rowsSelected = view.getTable().getSelectedRows();
for (int i = 0; i < numRows; i++) {
PhysicalModel pm = tableModel.getObject(rowsSelected[i]);
if (pm!=null) {
sb.append(pm.toString()).append("\n");
}
// 最後の改行を除く
if (sb.length()>0) {
sb.setLength(sb.length()-1);
}
}
if (sb.length() > 0) {
StringSelection stsel = new StringSelection(sb.toString());
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(stsel, stsel);
}
}
/**
* テーブルで選択した身長体重データを削除する。
* @param row
*/
public void delete(final int row) {
PhysicalModel model = (PhysicalModel)tableModel.getObject(row);
if (model == null) {
return;
}
final List<Long> list = new ArrayList<>(2);
if (model.getHeight() != null) {
list.add(model.getHeightId());
}
if (model.getWeight() != null) {
list.add(model.getWeightId());
}
DBTask task = new DBTask<Void, Void>(context) {
@Override
protected Void doInBackground() throws Exception {
java.util.logging.Logger.getLogger(this.getClass().getName()).fine("physical delete doInBackground");
DocumentDelegater ddl = new DocumentDelegater();
ddl.removeObservations(list);
return null;
}
@Override
protected void succeeded(Void result) {
java.util.logging.Logger.getLogger(this.getClass().getName()).fine("physical delete succeeded");
tableModel.deleteAt(row);
}
};
task.execute();
}
}