package open.dolphin.client;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.IndexColorModel;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.XMLDecoder;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.FileNameMap;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.FileImageInputStream;
import javax.swing.*;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.Element;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledEditorKit;
import open.dolphin.client.ChartMediator.CompState;
import open.dolphin.delegater.OrcaDelegater;
import open.dolphin.delegater.OrcaDelegaterFactory;
import open.dolphin.delegater.StampDelegater;
import open.dolphin.helper.DBTask;
import open.dolphin.helper.ImageHelper;
import open.dolphin.helper.UserDocumentHelper;
import open.dolphin.infomodel.*;
import open.dolphin.order.AbstractStampEditor;
import open.dolphin.order.StampEditor;
import open.dolphin.plugin.PluginLoader;
import open.dolphin.project.Project;
import open.dolphin.util.BeanUtils;
import open.dolphin.util.HashUtil;
/**
* Karte Pane
*
* @author Kazushi Minagawa, Digital Globe, inc.
*/
public class KartePane implements DocumentListener, MouseListener,
CaretListener, PropertyChangeListener {
// 文書に付けるタイトルを自動で取得する時の長さ
private static final int TITLE_LENGTH = 15;
// Schema/Image 設定用定数
private static final String MEDIA_TYPE_IMAGE_JPEG = "image/jpeg";
private static final String DEFAULT_IMAGE_TITLE = "Schema Image";
private static final String JPEG_EXT = ".jpg";
private static final String MEDIA_TYPE_IMAGE_PNG = "image/png";
private static final String PNG_EXT = ".png";
// JTextPane
private JTextPane textPane;
// SOA または P のロール
private String myRole;
// この KartePaneのオーナ
private ChartDocument parent;
private int stampId;
// Dirty Flag
private boolean dirty;
// Selection Flag
private boolean hasSelection;
private CompState curState;
// 初期化された時のDocumentの長さ
private int initialLength;
// ChartMediator(MenuSupport)
private ChartMediator mediator;
// このオブジェクトで生成する文書DocumentModelの文書ID
private String docId;
// 保存後及びブラウズ時の編集不可を表すカラー
private Color uneditableColor;
// このペインからDragg及びDroppされたスタンプの情報
private ComponentHolder[] drragedStamp;
private int draggedCount;
private int droppedCount;
//s.oh^ 2014/01/27 スタンプのテキストコピー機能拡張
private String patID;
//s.oh$
/**
* Creates new KartePane2
*/
public KartePane() {
}
public void setMargin(Insets margin) {
textPane.setMargin(margin);
}
public void setPreferredSize(Dimension size) {
textPane.setPreferredSize(size);
}
public void setSize(Dimension size) {
textPane.setMinimumSize(size);
textPane.setMaximumSize(size);
}
/**
* このPaneのオーナを設定する。
* @param parent KarteEditorオーナ
*/
public void setParent(ChartDocument parent) {
this.parent = parent;
}
/**
* このPaneのオーナを返す。
* @return KarteEditorオーナ
*/
public ChartDocument getParent() {
return parent;
}
/**
* 編集不可を表すカラーを設定する。
* @param uneditableColor 編集不可を表すカラー
*/
public void setUneditableColor(Color uneditableColor) {
this.uneditableColor = uneditableColor;
}
/**
* 編集不可を表すカラーを返す。
* @return 編集不可を表すカラー
*/
public Color getUneditableColor() {
return uneditableColor;
}
/**
* このPaneで生成するDocumentModelの文書IDを設定する。
* @param docId 文書ID
*/
protected void setDocId(String docId) {
this.docId = docId;
}
/**
* このPaneで生成するDocumentModelの文書IDを返す。
* @return 文書ID
*/
protected String getDocId() {
return docId;
}
/**
* ChartMediatorを設定する。
* @param mediator ChartMediator
*/
protected void setMediator(ChartMediator mediator) {
this.mediator = mediator;
}
/**
* ChartMediatorを返す。
* @return ChartMediator
*/
protected ChartMediator getMediator() {
return mediator;
}
/**
* このPaneのロールを設定する。
* @param myRole SOAまたはPのロール
*/
public void setMyRole(String myRole) {
this.myRole = myRole;
}
/**
* このPaneのロールを返す。
* @return SOAまたはPのロール
*/
public String getMyRole() {
return myRole;
}
/**
* JTextPaneを設定する。
* @param textPane JTextPane
*/
public void setTextPane(JTextPane textPane) {
this.textPane = textPane;
if (this.textPane != null) {
KarteStyledDocument doc = new KarteStyledDocument();
this.textPane.setDocument(doc);
this.textPane.putClientProperty("karteCompositor", this);
doc.setParent(this);
}
}
/**
* JTextPaneを返す。
* @return JTextPane
*/
public JTextPane getTextPane() {
return textPane;
}
/**
* JTextPaneのStyledDocumentを返す。
* @return JTextPaneのStyledDocument
*/
protected KarteStyledDocument getDocument() {
return (KarteStyledDocument) getTextPane().getDocument();
}
/**
* 初期長を設定する。
* @param initialLength
*/
public void setInitialLength(int initialLength) {
this.initialLength = initialLength;
}
/**
* 初期長を返す。
* @return Documentの初期長
*/
public int getInitialLength() {
return initialLength;
}
/**
* このPaneからDragされたスタンプ数を返す。
* @return このPaneからDragされたスタンプ数
*/
protected int getDraggedCount() {
return draggedCount;
}
/**
* このPaneからDragされたスタンプ数を設定する。
* @param draggedCount このPaneからDragされたスタンプ数
*/
protected void setDraggedCount(int draggedCount) {
this.draggedCount = draggedCount;
}
/**
* このPaneにDropされたスタンプ数を返す。
* @return このPaneにDropされたスタンプ数
*/
protected int getDroppedCount() {
return droppedCount;
}
/**
* このPaneにDropされたスタンプ数を設定する。
* @param droppedCount このPaneにDropされたスタンプ数
*/
protected void setDroppedCount(int droppedCount) {
this.droppedCount = droppedCount;
}
/**
* このPaneからDragされたスタンプを返す。
* @return このPaneからDragされたスタンプ配列
*/
protected ComponentHolder[] getDrragedStamp() {
return drragedStamp;
}
/**
* このPaneからDragされたスタンプを設定(記録)する。
* @param drragedStamp このPaneからDragされたスタンプ配列
*/
protected void setDrragedStamp(ComponentHolder[] drragedStamp) {
this.drragedStamp = drragedStamp;
}
/**
* 初期化する。
* @param editable 編集可能かどうかのフラグ
* @param mediator チャートメディエータ(実際にはメニューサポート)
*/
public void init(boolean editable, ChartMediator mediator) {
// Mediatorを保存する
setMediator(mediator);
// Drag は editable に関係なく可能
getTextPane().setDragEnabled(true);
// リスナを登録する
getTextPane().addMouseListener(this);
getTextPane().addCaretListener(this);
// Editable Property を設定する
setEditableProp(editable);
}
/**
* 編集可否を設定する。それに応じてリスナの登録または取り除きを行う。
* @param editable 編集可の時 true
*/
public void setEditableProp(boolean editable) {
getTextPane().setEditable(editable);
if (editable) {
getTextPane().getDocument().addDocumentListener(this);
getTextPane().addFocusListener(AutoKanjiListener.getInstance());
getTextPane().getDocument().addUndoableEditListener(mediator);
if (myRole.equals(IInfoModel.ROLE_SOA)) {
SOACodeHelper helper = new SOACodeHelper(this, getMediator());
} else {
PCodeHelper helper = new PCodeHelper(this, getMediator());
}
getTextPane().setBackground(Color.WHITE);
getTextPane().setOpaque(true);
} else {
getTextPane().getDocument().removeDocumentListener(this);
getTextPane().removeFocusListener(AutoKanjiListener.getInstance());
getTextPane().getDocument().removeUndoableEditListener(mediator);
setBackgroundUneditable();
}
}
// JTextPaneへの挿入でdirtyかどうかを判定する
@Override
public void insertUpdate(DocumentEvent e) {
SwingUtilities.invokeLater(() -> {
boolean newDirty = getDocument().getLength() > getInitialLength();
setDirty(newDirty);
});
}
// 削除が起こった時dirtyかどうかを判定する
@Override
public void removeUpdate(DocumentEvent e) {
SwingUtilities.invokeLater(() -> {
boolean newDirty = getDocument().getLength() >= getInitialLength();
setDirty(newDirty);
});
}
@Override
public void changedUpdate(DocumentEvent e) {
}
@Override
public void caretUpdate(CaretEvent e) {
boolean newSelection = (e.getDot() != e.getMark());
if (newSelection != hasSelection) {
hasSelection = newSelection;
// テキスト選択の状態へ遷移する
if (hasSelection) {
curState = getMyRole().equals(IInfoModel.ROLE_SOA) ? CompState.SOA_TEXT : CompState.P_TEXT;
} else {
curState = getMyRole().equals(IInfoModel.ROLE_SOA) ? CompState.SOA : CompState.P;
}
controlMenus(mediator.getActions());
}
}
/**
* リソースをclearする。
*/
public void clear() {
getTextPane().getDocument().removeDocumentListener(this);
getTextPane().removeMouseListener(this);
getTextPane().removeFocusListener(AutoKanjiListener.getInstance());
getTextPane().removeCaretListener(this);
try {
KarteStyledDocument doc = getDocument();
doc.remove(0, doc.getLength());
} catch (Exception e) {
e.printStackTrace(System.err);
}
setTextPane(null);
}
/**
* メニューを制御する。
*
*/
private void controlMenus(ActionMap map) {
// 各Stateはenableになる条件だけを管理する
switch (curState) {
case NONE:
break;
case SOA:
// SOAPaneにFocusがありテキスト選択がない状態
if (getTextPane().isEditable()) {
map.get(GUIConst.ACTION_PASTE).setEnabled(canPaste());
map.get(GUIConst.ACTION_INSERT_TEXT).setEnabled(true);
map.get(GUIConst.ACTION_INSERT_SCHEMA).setEnabled(true);
map.get(GUIConst.ACTION_ATTACHMENT).setEnabled(true);
}
break;
case SOA_TEXT:
// SOAPaneにFocusがありテキスト選択がある状態
map.get(GUIConst.ACTION_CUT).setEnabled(getTextPane().isEditable());
map.get(GUIConst.ACTION_COPY).setEnabled(true);
boolean pasteOk = (getTextPane().isEditable() && canPaste());
map.get(GUIConst.ACTION_PASTE).setEnabled(pasteOk);
break;
case P:
// PPaneにFocusがありテキスト選択がない状態
if (getTextPane().isEditable()) {
map.get(GUIConst.ACTION_PASTE).setEnabled(canPaste());
map.get(GUIConst.ACTION_INSERT_TEXT).setEnabled(true);
map.get(GUIConst.ACTION_INSERT_STAMP).setEnabled(true);
}
break;
case P_TEXT:
// PPaneにFocusがありテキスト選択がある状態
map.get(GUIConst.ACTION_CUT).setEnabled(getTextPane().isEditable());
map.get(GUIConst.ACTION_COPY).setEnabled(true);
pasteOk = (getTextPane().isEditable() && canPaste());
map.get(GUIConst.ACTION_PASTE).setEnabled(pasteOk);
break;
}
}
// ペイン内の右クリックメニューを生成する
protected JPopupMenu createMenus() {
final JPopupMenu contextMenu = new JPopupMenu();
// cut, copy, paste メニューを追加する
contextMenu.add(mediator.getAction(GUIConst.ACTION_CUT));
contextMenu.add(mediator.getAction(GUIConst.ACTION_COPY));
contextMenu.add(mediator.getAction(GUIConst.ACTION_PASTE));
// Attachment
if (getTextPane().isEditable() && getMyRole().equals(IInfoModel.ROLE_SOA)) {
contextMenu.addSeparator();
mediator.getAction(GUIConst.ACTION_ATTACHMENT).setEnabled(true);
contextMenu.add(mediator.getAction(GUIConst.ACTION_ATTACHMENT));
}
// テキストカラーメニューを追加する
if (getTextPane().isEditable()) {
ColorChooserComp ccl = new ColorChooserComp();
ccl.addPropertyChangeListener(ColorChooserComp.SELECTED_COLOR, (PropertyChangeEvent e) -> {
Color selected = (Color) e.getNewValue();
Action action = new StyledEditorKit.ForegroundAction("selected", selected);
action.actionPerformed(new ActionEvent(getTextPane(), ActionEvent.ACTION_PERFORMED, "foreground"));
contextMenu.setVisible(false);
});
JLabel l = new JLabel(ClientContext.getMyBundle(KartePane.class).getString("label.color.text"));
JPanel p = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 5));
p.add(l);
p.add(ccl);
contextMenu.addSeparator();
contextMenu.add(p);
}
// PPane の場合は処方日数変更とStampMenuを追加する
if (getMyRole().equals(IInfoModel.ROLE_P)) {
contextMenu.addSeparator();
contextMenu.add(mediator.getAction(GUIConst.ACTION_CHANGE_NUM_OF_DATES_ALL));
contextMenu.addSeparator();
mediator.addStampMenu(contextMenu, this);
} else {
// TextMenuを追加する
contextMenu.addSeparator();
mediator.addTextMenu(contextMenu);
}
return contextMenu;
}
private void mabeShowPopup(final MouseEvent e) {
if (e.isPopupTrigger()) {
//masuda^ textPaneにフォーカスを当ててからにする
//JPopupMenu contextMenu = createMenus();
//contextMenu.show(e.getComponent(), e.getX(), e.getY());
textPane.requestFocusInWindow();
SwingUtilities.invokeLater(() -> {
JPopupMenu contextMenu = createMenus();
contextMenu.show(e.getComponent(), e.getX(), e.getY());
});
//masuda$
}
}
@Override
public void mousePressed(MouseEvent e) {
mabeShowPopup(e);
}
@Override
public void mouseReleased(MouseEvent e) {
mabeShowPopup(e);
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
/**
* 背景を編集不可カラーに設定する。
*/
protected void setBackgroundUneditable() {
getTextPane().setBackground(GUIConst.KARTE_UNEDITABLE_BK_COLOR);
getTextPane().setOpaque(true);
}
/**
* ロールとパートナを設定する。
* @param role このペインのロール
*/
public void setRole(String role) {
setMyRole(role);
}
/**
* Dirtyかどうかを返す。
* @return dirty の時 true
*/
protected boolean isDirty() {
return getTextPane().isEditable() ? dirty : false;
}
protected void setDirty(boolean newDirty) {
if (newDirty != dirty) {
dirty = newDirty;
getParent().setDirty(dirty);
}
}
/**
* 保存時につけるドキュメントのタイトルをDocument Objectから抽出する。
* @return 先頭から指定された長さを切り出した文字列
*/
protected String getTitle() {
try {
KarteStyledDocument doc = getDocument();
int len = doc.getLength();
int freeTop = 0; // doc.getFreeTop();
int freeLen = len - freeTop;
freeLen = freeLen < TITLE_LENGTH ? freeLen : TITLE_LENGTH;
return getTextPane().getText(freeTop, freeLen).trim();
} catch (Exception e) {
e.printStackTrace(System.err);
}
return null;
}
/**
* Documentの段落スタイルを設定する。
* @param str スタイル
*/
public void setLogicalStyle(String str) {
getDocument().setLogicalStyle(str);
}
/**
* Documentの段落論理スタイルをクリアする。
*/
public void clearLogicalStyle() {
getDocument().clearLogicalStyle();
}
/**
* 段落を構成する。
*/
public void makeParagraph() {
getDocument().makeParagraph();
}
/**
* Documentに文字列を挿入する。
* @param s
* @param a
*/
public void insertFreeString(String s, AttributeSet a) {
getDocument().insertFreeString(s, a);
}
/**
* このペインに Stamp を挿入する。
* @param stamp
*/
public void stamp(final ModuleModel stamp) {
if (stamp != null) {
EventQueue.invokeLater(() -> {
// 処方の場合、同じ用法であれば一つにまとめる
boolean drop = true;
//s.oh^ 2014/02/10 スタンプめとめる不具合
////minagawa^ LSC Test
// boolean selfDrag = (getDraggedCount()>0 && getDrragedStamp()!=null);
////minagawa$
boolean selfDrag = (getDraggedCount()>0 && getDrragedStamp()!=null && getDroppedCount()>0);
//s.oh$
String entity = stamp.getModuleInfoBean().getEntity();
//minagawa^ LSC Test
//if (entity.equals(IInfoModel.ENTITY_MED_ORDER) && Project.getBoolean("merge.rp.with.sameAdmin")) {
if (!selfDrag && entity.equals(IInfoModel.ENTITY_MED_ORDER) && Project.getBoolean("merge.rp.with.sameAdmin")) {
//minagawa$
StampHolder sh = findCanMergeRp(stamp);
if (sh!=null) {
BundleMed med = (BundleMed)sh.getStamp().getModel();
ClaimItem[] items = ((BundleMed)stamp.getModel()).getClaimItem();
sh.addItems(items);
drop = false;
textPane.revalidate();
textPane.repaint();
}
}
//s.oh^ 2014/01/27 同じ検体検査をまとめる
// if (!selfDrag && entity.equals(IInfoModel.ENTITY_LABO_TEST) && Project.getBoolean(Project.KARTE_MERGE_WITH_LABTEST, false)) {
// StampHolder sh = findCanMergeLabTest(stamp);
//
// if (sh!=null) {
// BundleDolphin lab = (BundleDolphin)sh.getStamp().getModel();
// ClaimItem[] items = ((BundleDolphin)stamp.getModel()).getClaimItem();
// sh.addItems(items);
// drop = false;
// textPane.revalidate();
// textPane.repaint();
// }
// }
//s.oh$
if (drop) {
StampHolder h = new StampHolder(KartePane.this, stamp);
h.setTransferHandler(new StampHolderTransferHandler(KartePane.this, h));
KarteStyledDocument doc = getDocument();
doc.stamp(h);
}
});
}
}
/**
* このペインに Stamp を挿入する。
* @param stamp
*/
public void flowStamp(ModuleModel stamp) {
if (stamp != null) {
StampHolder h = new StampHolder(this, stamp);
h.setTransferHandler(new StampHolderTransferHandler(KartePane.this, h));
KarteStyledDocument doc = getDocument();
doc.flowStamp(h);
}
}
/**
* このペインにシェーマを挿入する。
* @param schema シェーマ
*/
public void stampSchema(final SchemaModel schema) {
if (schema != null) {
EventQueue.invokeLater(() -> {
SchemaHolder h = new SchemaHolder(KartePane.this, schema);
h.setTransferHandler(new SchemaHolderTransferHandler(KartePane.this, h));
KarteStyledDocument doc = getDocument();
doc.stampSchema(h);
});
}
}
/**
* このペインにシェーマを挿入する。
* @param schema シェーマ
*/
public void flowSchema(SchemaModel schema) {
if (schema != null) {
SchemaHolder h = new SchemaHolder(this, schema);
h.setTransferHandler(new SchemaHolderTransferHandler(KartePane.this, h));
KarteStyledDocument doc = (KarteStyledDocument) getTextPane().getDocument();
doc.flowSchema(h);
}
}
/**
* このペインにアタッチメントを挿入する。
* @param att
*/
public void stampAttachment(final AttachmentModel att) {
if (att != null) {
EventQueue.invokeLater(() -> {
AttachmentHolder h = new AttachmentHolder(KartePane.this, att);
h.setTransferHandler(new AttachmentHolderTransferHandler(KartePane.this, h));
KarteStyledDocument doc = getDocument();
doc.stampAttachment(h);
});
}
}
/**
* このペインにアタッチメントを挿入する。
* @param att
*/
public void flowAttachment(AttachmentModel att) {
if (att != null) {
AttachmentHolder h = new AttachmentHolder(this, att);
h.setTransferHandler(new AttachmentHolderTransferHandler(KartePane.this, h));
KarteStyledDocument doc = (KarteStyledDocument)getTextPane().getDocument();
doc.flowAttachment(h);
}
}
/**
* このペインに TextStamp を挿入する。
* @param s
*/
public void insertTextStamp(final String s) {
EventQueue.invokeLater(() -> {
KarteStyledDocument doc = getDocument();
doc.insertTextStamp(s);
});
}
/**
* StampInfoがDropされた時、そのデータをペインに挿入する。
* @param stampInfo ドロップされたスタンプ情報
*/
public void stampInfoDropped(ModuleInfoBean stampInfo) {
// Drop された StampInfo の属性に応じて処理を振分ける
String entity = stampInfo.getEntity();
String role = stampInfo.getStampRole();
//------------------------------------
// 病名の場合は2号カルテペインには展開しない
//------------------------------------
if (entity.equals(IInfoModel.ENTITY_DIAGNOSIS)) {
Toolkit.getDefaultToolkit().beep();
return;
}
//------------------------------------
// Text スタンプを挿入する
//------------------------------------
if (entity.equals(IInfoModel.ENTITY_TEXT)) {
applyTextStamp(stampInfo);
return;
}
//------------------------------------
// ORCA 入力セットの場合
//------------------------------------
if (role.equals(IInfoModel.ROLE_ORCA_SET)) {
applyOrcaSet(stampInfo);
return;
}
//------------------------------------
// データベースに保存されているスタンプを挿入する
//------------------------------------
if (stampInfo.isSerialized()) {
applySerializedStamp(stampInfo);
return;
}
//------------------------------------
// Stamp エディタを起動する
//------------------------------------
ModuleModel stamp = new ModuleModel();
stamp.setModuleInfoBean(stampInfo);
StampEditor se = new StampEditor(stamp, this);
}
/**
* StampInfoがDropされた時、そのデータをペインに挿入する。
* @param addList スタンプ情報のリスト
*/
public void stampInfoDropped(final ArrayList<ModuleInfoBean> addList) {
DBTask task = new DBTask<List<StampModel>, Void>(parent.getContext()) {
@Override
protected List<StampModel> doInBackground() throws Exception {
StampDelegater sdl = new StampDelegater();
List<StampModel> list = sdl.getStamp(addList);
return list;
}
@Override
public void succeeded(List<StampModel> list) {
if (list != null) {
for (int i = 0; i < list.size(); i++) {
ModuleInfoBean stampInfo = addList.get(i);
StampModel theModel = list.get(i);
IInfoModel model = (IInfoModel) BeanUtils.xmlDecode(theModel.getStampBytes());
if (model != null) {
//s.oh^ 2014/08/01 パス対応
//ModuleModel stamp = new ModuleModel();
//stamp.setModel(model);
//stamp.setModuleInfoBean(stampInfo);
//stamp(stamp);
if(stampInfo.getEntity().equals(IInfoModel.ENTITY_TEXT)) {
insertTextStamp(model.toString() + "\n");
}else{
ModuleModel stamp = new ModuleModel();
stamp.setModel(model);
stamp.setModuleInfoBean(stampInfo);
stamp(stamp);
}
//s.oh$
}
}
}
}
};
task.execute();
}
/**
* TextStampInfo が Drop された時の処理を行なう。
* @param addList
*/
public void textStampInfoDropped(final ArrayList<ModuleInfoBean> addList) {
DBTask task = new DBTask<List<StampModel>, Void>(parent.getContext()) {
@Override
protected List<StampModel> doInBackground() throws Exception {
StampDelegater sdl = new StampDelegater();
List<StampModel> list = sdl.getStamp(addList);
return list;
}
@Override
public void succeeded(List<StampModel> list) {
if (list != null) {
for (StampModel theModel : list) {
IInfoModel model = (IInfoModel) BeanUtils.xmlDecode(theModel.getStampBytes());
if (model != null) {
insertTextStamp(model.toString() + "\n");
}
}
}
}
};
task.execute();
}
/**
* TextStamp をこのペインに挿入する。
*/
private void applyTextStamp(final ModuleInfoBean stampInfo) {
DBTask task = new DBTask<StampModel, Void>(parent.getContext()) {
@Override
protected StampModel doInBackground() throws Exception {
StampDelegater sdl = new StampDelegater();
StampModel getStamp = sdl.getStamp(stampInfo.getStampId());
return getStamp;
}
@Override
public void succeeded(StampModel result) {
if (result != null) {
try {
byte[] bytes = result.getStampBytes();
IInfoModel model;
try (XMLDecoder d = new XMLDecoder(new BufferedInputStream(new ByteArrayInputStream(bytes)))) {
model = (IInfoModel) d.readObject();
}
if (model != null) {
insertTextStamp(model.toString());
}
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
}
};
task.execute();
}
/**
* 永続化されているスタンプを取得してこのペインに展開する。
*/
private void applySerializedStamp(final ModuleInfoBean stampInfo) {
DBTask task = new DBTask<StampModel, Void>(parent.getContext()) {
@Override
protected StampModel doInBackground() throws Exception {
StampDelegater sdl = new StampDelegater();
StampModel getStamp = sdl.getStamp(stampInfo.getStampId());
return getStamp;
}
@Override
public void succeeded(StampModel result) {
if (result != null) {
IInfoModel model = (IInfoModel) BeanUtils.xmlDecode(result.getStampBytes());
ModuleModel stamp = new ModuleModel();
stamp.setModel(model);
stamp.setModuleInfoBean(stampInfo);
stamp(stamp);
}
}
};
task.execute();
}
/**
* ORCA の入力セットを取得してこのペインに展開する。
*/
private void applyOrcaSet(final ModuleInfoBean stampInfo) {
DBTask task = new DBTask<List<ModuleModel>, Void>(parent.getContext()) {
@Override
protected List<ModuleModel> doInBackground() throws Exception {
OrcaDelegater sdl = OrcaDelegaterFactory.create();
List<ModuleModel> models = sdl.getStamp(stampInfo);
return models;
}
@Override
public void succeeded(List<ModuleModel> models) {
if (models != null) {
models.stream().forEach((stamp) -> {
stamp(stamp);
});
}
}
};
task.execute();
}
private boolean showMaxSizeMessage() {
java.util.ResourceBundle bundle = ClientContext.getMyBundle(KartePane.class);
String width = bundle.getString("image.max.width");
String height = bundle.getString("image.max.height");
int maxImageWidth = Integer.parseInt(width);
int maxImageHeight = Integer.parseInt(height);
String title = bundle.getString("title.aboutImageSize");
String msg = bundle.getString("message.aboutImageSize");
MessageFormat msft = new MessageFormat(msg);
JLabel msg1 = new JLabel(msft.format(new Object[]{maxImageWidth, maxImageHeight}));
String question = bundle.getString("question.resizeImage");
JLabel msg2 = new JLabel(question);
String suppress = bundle.getString("suppress.imageSize.message");
final JCheckBox cb = new JCheckBox(suppress);
cb.setFont(new Font("Dialog", Font.PLAIN, 10));
cb.addActionListener((ActionEvent e) -> {
Project.setBoolean("showImageSizeMessage", !cb.isSelected());
});
JPanel p1 = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 3));
p1.add(msg1);
JPanel p2 = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 3));
p2.add(msg2);
JPanel p3 = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 3));
p3.add(cb);
JPanel box = new JPanel();
box.setLayout(new BoxLayout(box, BoxLayout.Y_AXIS));
box.add(p1);
box.add(p2);
box.add(p3);
box.setBorder(BorderFactory.createEmptyBorder(0, 0, 11, 11));
Window w = SwingUtilities.getWindowAncestor(getTextPane());
String optionResize = bundle.getString("option.resize");
int option = JOptionPane.showOptionDialog(w,
new Object[]{box},
ClientContext.getFrameTitle(title),
JOptionPane.DEFAULT_OPTION,
JOptionPane.INFORMATION_MESSAGE,
ClientContext.getImageIconArias("icon_info"),
new String[]{optionResize, GUIFactory.getCancelButtonText()}, optionResize);
return option == 0;
}
private void showNoReaderMessage() {
Window w = SwingUtilities.getWindowAncestor(getTextPane());
java.util.ResourceBundle bundle = ClientContext.getMyBundle(KartePane.class);
String msg = bundle.getString("warning.noAvailable.reader");
String title = bundle.getString("title.imageImport");
JOptionPane.showMessageDialog(w,
msg,
ClientContext.getFrameTitle(title),
JOptionPane.WARNING_MESSAGE);
}
/**
* ImageTable から ImageEntry が drop された時の処理を行う。
* entry の URL からイメージをロードし、SchemaEditorへ表示する。
* @param entry カルテに展開する ImageEntry Object
*/
public void imageEntryDropped(final ImageEntry entry) {
DBTask task = new DBTask<BufferedImage, Void>(parent.getContext()) {
@Override
protected BufferedImage doInBackground() throws Exception {
URL url = new URL(entry.getUrl());
BufferedImage importImage = ImageIO.read(url);
return importImage;
}
@Override
public void succeeded(BufferedImage importImage) {
if (importImage != null) {
int maxImageWidth = ClientContext.getInt("image.max.width");
int maxImageHeight = ClientContext.getInt("image.max.height");
if (importImage.getWidth() > maxImageWidth || importImage.getHeight()> maxImageHeight) {
boolean ok = true;
if (Project.getBoolean("showImageSizeMessage", true)) {
ok = showMaxSizeMessage();
}
if (ok) {
importImage = ImageHelper.getFirstScaledInstance(importImage, maxImageWidth);
} else {
return;
}
}
ImageIcon icon = new ImageIcon(importImage);
SchemaModel schema = new SchemaModel();
schema.setIcon(icon);
// IInfoModel として ExtRef を保持している
ExtRefModel ref = new ExtRefModel();
schema.setExtRefModel(ref);
ref.setContentType(MEDIA_TYPE_IMAGE_JPEG); // MIME
ref.setTitle(DEFAULT_IMAGE_TITLE); //
ref.setUrl(entry.getUrl()); // 元画像のURL
// href=docID-stampId.jpg
stampId++;
StringBuilder sb = new StringBuilder();
sb.append(getDocId());
sb.append("-");
sb.append(stampId);
sb.append(JPEG_EXT);
String fileName = sb.toString();
schema.setFileName(fileName); // href
ref.setHref(fileName); // href
PluginLoader<SchemaEditor> loader
= PluginLoader.load(SchemaEditor.class);
Iterator<SchemaEditor> iter = loader.iterator();
if (iter.hasNext()) {
final SchemaEditor editor = iter.next();
editor.setSchema(schema);
editor.setEditable(true);
editor.addPropertyChangeListener(KartePane.this);
Runnable awt = () -> {
editor.start();
};
EventQueue.invokeLater(awt);
}
}
}
};
task.execute();
}
/**
* AttachmentModelの情報を表示し、添付するかインライン挿入(画像の場合のみ)するか選択させる。
* @param attachment AttachmentModel
*/
private void showFileInfo(final AttachmentModel attachment) {
// 画像かどうか
final String ext = attachment.getExtension().toLowerCase();
boolean fileIsImage = UserDocumentHelper.isImage(ext);
// View
final AttachmentOrInlineView view = new AttachmentOrInlineView();
ButtonGroup bg = new ButtonGroup();
bg.add(view.getAttachmentRadio());
bg.add(view.getInlineRadio());
// 添付またはインライン展開のActionListener
ActionListener al = (ActionEvent ae) -> {
boolean attIsSelected = view.getAttachmentRadio().isSelected();
view.getTitleFld().setEnabled(attIsSelected);
};
view.getAttachmentRadio().addActionListener(al);
view.getInlineRadio().addActionListener(al);
// 情報を設定する
view.getFileNameLbl().setText(attachment.getFileName());
view.getLocationLbl().setText(attachment.getLocation());
view.getTypeLbl().setText(attachment.getContentType());
// 添付の場合の容量を制限する 1TB とか添付する人がいるので...
int maxSize = Project.getInt("attachment.max.size"); // Default = 1MB
int attSize = (int)attachment.getContentSize();
boolean canAttach = (attSize <= maxSize);
java.util.ResourceBundle bundle = ClientContext.getMyBundle(KartePane.class);
if (canAttach) {
String byesInfo = bundle.getString("info.fileSize");
MessageFormat msft = new MessageFormat(byesInfo);
view.getSizeLbl().setText(msft.format(new Object[]{String.valueOf(attSize)}));
} else {
String tooLarge = bundle.getString("warning.tooLargeFile");
MessageFormat msft = new MessageFormat(tooLarge);
view.getSizeLbl().setText(msft.format(new Object[]{Project.getString("attachment.max.size.display")}));
view.getSizeLbl().setForeground(Color.red);
}
view.getLastModifiedLbl().setText(millisToTime(attachment.getLastModified()));
view.getDigestLbl().setText(attachment.getDigest());
view.getTitleFld().setText(attachment.getTitle());
// Option
String okText = (String)UIManager.get("OptionPane.okButtonText");
String cancelText = (String)UIManager.get("OptionPane.cancelButtonText");
final JButton okBtn = new JButton(okText);
final JButton cancelBtn = new JButton(cancelText);
Object[] options = new JButton[]{okBtn, cancelBtn};
view.getTitleFld().getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent de) {
boolean enabled = (!view.getTitleFld().getText().equals(""));
okBtn.setEnabled(enabled);
}
@Override
public void removeUpdate(DocumentEvent de) {
boolean enabled = (!view.getTitleFld().getText().equals(""));
okBtn.setEnabled(enabled);
}
@Override
public void changedUpdate(DocumentEvent de) {
}
});
//--------------------------------------
// 添付可能かどうかでボタンを制御する
//--------------------------------------
view.getAttachmentRadio().setEnabled(canAttach);
view.getInlineRadio().setEnabled(fileIsImage);
if (canAttach && fileIsImage) {
view.getAttachmentRadio().doClick();
} else if (canAttach &&(!fileIsImage)) {
view.getAttachmentRadio().doClick();
} else if ((!canAttach) && fileIsImage) {
view.getInlineRadio().doClick();
} else if ((!canAttach) && (!fileIsImage)) {
// 1TB は無理、もちろん 100GB も
view.getTitleFld().setEnabled(false);
okBtn.setEnabled(false);
}
// Dialogを表示する
Window w = SwingUtilities.getWindowAncestor(getTextPane());
JOptionPane pane = new JOptionPane(view,
JOptionPane.PLAIN_MESSAGE,
JOptionPane.DEFAULT_OPTION,
attachment.getIcon(),
options,
okBtn);
String title = bundle.getString("title.attacheOrInsertImage");
final JDialog dialog = pane.createDialog(w, ClientContext.getFrameTitle(title));
dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
dialog.addWindowListener(new WindowAdapter() {
@Override
public void windowOpened(WindowEvent we) {
view.getTitleFld().requestFocusInWindow();
}
@Override
public void windowClosing(WindowEvent we) {
dialog.setVisible(false);
dialog.dispose();
}
});
cancelBtn.addActionListener((ActionEvent ae) -> {
dialog.setVisible(false);
dialog.dispose();
});
okBtn.addActionListener((ActionEvent ae) -> {
dialog.setVisible(false);
dialog.dispose();
if (view.getInlineRadio().isSelected()) {
imageFileDropped(attachment);
} else {
attachment.setTitle(view.getTitleFld().getText().trim());
stampAttachment(attachment);
}
});
dialog.setVisible(true);
}
private String millisToTime(long l) {
Date d = new Date(l);
String timeFmt = ClientContext.getMyBundle(KartePane.class).getString("timeFormat.lastModified");
SimpleDateFormat sdf = new SimpleDateFormat(timeFmt);
return sdf.format(d);
}
/**
* このpaneにファイルがDropされた時の処理を行う。
* ファイルの情報を取得し、AttachmentModelを生成する。それを次の処理showFileInfoに渡す。
* @param file Dropされたファイル
*/
public void fileDropped(final File file) {
SwingWorker worker = new SwingWorker<AttachmentModel, Void>() {
@Override
protected AttachmentModel doInBackground() throws Exception {
long len;
byte[] data;
try ( // Content を読み込む
FileInputStream in = new FileInputStream(file); FileChannel fChan = in.getChannel()) {
len = fChan.size();
data = new byte[(int)len];
ByteBuffer buf = ByteBuffer.allocate((int)len);
fChan.read(buf);
buf.rewind();
buf.get(data);
}
// Extension & Icon
String fileName = file.getName();
int index = fileName.lastIndexOf(".");
String ext = null;
if (index>=0) {
ext = fileName.substring(index+1);
}
// 拡張子を除き添付ファイルの場合のタイトルの初期値にする
fileName = fileName.substring(0, index);
// Paper Clip icon
ImageIcon icon = ClientContext.getImageIconArias("icon_attachment");
// MIME type
FileNameMap fileNameMap = URLConnection.getFileNameMap();
String type = fileNameMap.getContentTypeFor(file.getName());
type = type !=null ? type : ext;
// Attachment を生成する
AttachmentModel attachment = new AttachmentModel();
attachment.setFileName(file.getName()); // file name
attachment.setLocation(file.getParent()); // location
attachment.setContentType(type); // mime type
attachment.setContentSize(len); // length
attachment.setLastModified(file.lastModified()); // lastmodified
attachment.setDigest(HashUtil.MD5(data)); // md5
attachment.setTitle(fileName); // title
attachment.setIcon(icon); // icon
attachment.setExtension(ext); // extension
attachment.setBytes(data); // data bytes
//attachment.setMemo(""); // memo
// URI 暫定(保存時に再設定をする)
stampId++;
StringBuilder sb = new StringBuilder();
sb.append(getDocId());
sb.append("-");
sb.append(stampId);
sb.append(".");
sb.append(ext);
String uri = sb.toString();
attachment.setUri(uri); // uri
return attachment;
}
@Override
protected void done() {
try {
AttachmentModel attachment = get();
showFileInfo(attachment);
} catch (InterruptedException | ExecutionException ex) {
java.util.logging.Logger.getLogger(KartePane.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
worker.execute();
}
/**
* ファイルのDropを受け、イメージをカルテに挿入する。
* @param attachment
*/
public void imageFileDropped(AttachmentModel attachment) {
final File file = new File(attachment.getLocation(), attachment.getFileName());
DBTask task = new DBTask<BufferedImage, Void>(parent.getContext()) {
@Override
protected BufferedImage doInBackground() throws Exception {
URL url = file.toURI().toURL();
BufferedImage importImage = ImageIO.read(url);
return importImage;
}
@Override
public void succeeded(BufferedImage importImage) {
if (importImage != null) {
int maxImageWidth = ClientContext.getInt("image.max.width");
int maxImageHeight = ClientContext.getInt("image.max.height");
if (importImage.getWidth() > maxImageWidth || importImage.getHeight()> maxImageHeight) {
boolean ok = true;
if (Project.getBoolean("showImageSizeMessage", true)) {
ok = showMaxSizeMessage();
}
if (ok) {
importImage = ImageHelper.getFirstScaledInstance(importImage, maxImageWidth);
} else {
return;
}
}
ImageIcon icon = new ImageIcon(importImage);
SchemaModel schema = new SchemaModel();
schema.setIcon(icon);
// IInfoModel として ExtRef を保持している
ExtRefModel ref = new ExtRefModel();
schema.setExtRefModel(ref);
ref.setContentType(MEDIA_TYPE_IMAGE_JPEG); // MIME
ref.setTitle(DEFAULT_IMAGE_TITLE); //
try {
ref.setUrl(file.toURI().toURL().toString()); // 元画像のURL
} catch (MalformedURLException ex) {
}
// href=docID-stampId.jpg
stampId++;
StringBuilder sb = new StringBuilder();
sb.append(getDocId());
sb.append("-");
sb.append(stampId);
sb.append(JPEG_EXT);
String fileName = sb.toString();
schema.setFileName(fileName); // href
ref.setHref(fileName); // href
PluginLoader<SchemaEditor> loader
= PluginLoader.load(SchemaEditor.class);
Iterator<SchemaEditor> iter = loader.iterator();
if (iter.hasNext()) {
final SchemaEditor editor = iter.next();
editor.setSchema(schema);
editor.setEditable(true);
editor.addPropertyChangeListener(KartePane.this);
Runnable awt = () -> {
editor.start();
};
EventQueue.invokeLater(awt);
}
}
}
@Override
public void failed(Throwable e) {
}
};
task.execute();
}
public void importImage(final byte[] img, final String sop, final String ext) {
if(getTextPane() == null || !getTextPane().isEditable()) return;
if (img==null) {
throw new RuntimeException("importImage: 無効な引数");
}
SwingWorker task = new SwingWorker<BufferedImage, Void>() {
@Override
protected BufferedImage doInBackground() throws Exception {
BufferedImage importImage = ImageIO.read(new ByteArrayInputStream(img));
return importImage;
}
@Override
public void done() {
try {
BufferedImage importImage = get();
if (importImage!=null) {
if(importImage.getHeight() > 512 || importImage.getWidth() > 512) {
importImage = createAdjustAndCompositeImage(importImage, new Dimension(512, 512));
}
ImageIcon icon = new ImageIcon(importImage);
SchemaModel schema = new SchemaModel();
schema.setIcon(icon);
// IInfoModel として ExtRef を保持している
ExtRefModel ref = new ExtRefModel();
schema.setExtRefModel(ref);
ref.setContentType(MEDIA_TYPE_IMAGE_PNG); // MIME
ref.setUrl(sop); // 元画像のURL
ref.setMedicalRole(""); // medicalRole=modality
ref.setSop(sop); // SOP
ref.setExtension(ext); // extension
// href=docID-stampId.jpg
stampId++;
StringBuilder sb = new StringBuilder();
sb.append(getDocId());
sb.append("-");
sb.append(stampId);
sb.append(PNG_EXT);
String fileName = sb.toString();
schema.setFileName(fileName); // href
ref.setHref(fileName); // href
stampSchema(schema);
}
} catch (InterruptedException | ExecutionException ex) {
ex.printStackTrace(System.err);
}
}
};
task.execute();
}
/**
* Xronos連携
* @param image
* @param dim
* @return
*/
//private Image createAdjustAndCompositeImage(BufferedImage image, Dimension dim, String text) {
public BufferedImage createAdjustAndCompositeImage(BufferedImage image, Dimension dim) {
int newWidth = image.getWidth();
int newHeight = image.getHeight();
float width = (float)newWidth;
float height = (float)newHeight;
float dimW = (float)dim.width;
float dimH = (float)dim.height;
boolean bResize = false;
// 縦長画像の時
if (height>width) {
// 画像の高さがラベルより大きい時、画像の高さを dim.height にする
if (height>dimH) {
newHeight = (int)dimH;
float ratio = dimH/height;
newWidth = (int)(ratio*width);
bResize = true;
}
} // 横長画像の時
else {
// 画像の幅がラベルより大きい時、画像の幅を dim.width にする
if (width>dimW) {
newWidth = (int)dimW;
float ratio = dimW/width;
newHeight = (int)(ratio*height);
bResize = true;
}
}
// 縮小する
BufferedImage resized = (bResize) ? rescaleImage(image, newWidth, newHeight) : image;
return resized;
}
/**
* Xronos連携
* @param srcImage
* @param dstWidth
* @param dstHeight
* @return
*/
public BufferedImage rescaleImage(BufferedImage srcImage, int dstWidth, int dstHeight) {
BufferedImage dstImage;
if(srcImage.getColorModel() instanceof IndexColorModel) {
dstImage = new BufferedImage(dstWidth, dstHeight, srcImage.getType(), (IndexColorModel)srcImage.getColorModel());
}else{
if(srcImage.getType() == 0) {
dstImage = new BufferedImage(dstWidth, dstHeight, BufferedImage.TYPE_4BYTE_ABGR_PRE);
}else{
dstImage = new BufferedImage(dstWidth, dstHeight, srcImage.getType());
}
}
double x = (double) dstWidth / srcImage.getWidth();
double y = (double) dstHeight / srcImage.getHeight();
AffineTransform af = AffineTransform.getScaleInstance(x, y);
if(dstImage.getColorModel().hasAlpha() && dstImage.getColorModel() instanceof IndexColorModel) {
int pixel = ((IndexColorModel) dstImage.getColorModel()).getTransparentPixel();
for(int i = 0; i < dstImage.getWidth(); ++i) {
for(int j = 0; j < dstImage.getHeight(); ++j) {
dstImage.setRGB(i, j, pixel);
}
}
}
Graphics2D g2 = (Graphics2D)dstImage.createGraphics();
g2.drawImage(srcImage, af, null);
g2.dispose();
return dstImage;
}
/**
* Schema が DnD された場合、シェーマエディタを開いて編集する。
* @param path
*/
public void insertImage(String path) {
if (path == null) {
return;
}
String suffix = path.toLowerCase();
int index = suffix.lastIndexOf('.');
if (index == 0) {
showNoReaderMessage();
return;
}
suffix = suffix.substring(index+1);
Iterator readers = ImageIO.getImageReadersBySuffix(suffix);
if (!readers.hasNext()) {
showNoReaderMessage();
return;
}
ImageReader reader = (ImageReader) readers.next();
int width;
int height;
String name;
try {
File file = new File(path);
name = file.getName();
reader.setInput(new FileImageInputStream(file), true);
width = reader.getWidth(0);
height = reader.getHeight(0);
} catch (Exception e) {
java.util.logging.Logger.getLogger(this.getClass().getName()).warning(e.getMessage());
return;
}
ImageEntry entry = new ImageEntry();
entry.setPath(path);
entry.setFileName(name);
entry.setNumImages(1);
entry.setWidth(width);
entry.setHeight(height);
imageEntryDropped(entry);
}
/**
* StampEditor の編集が終了するとここへ通知される。
* 通知されたスタンプをペインに挿入する。
* @param e
*/
@Override
public void propertyChange(PropertyChangeEvent e) {
String prop = e.getPropertyName();
// SchemaEditorからの通知
if (prop.equals("imageProp")) {
SchemaModel schema = (SchemaModel)e.getNewValue();
// 編集されたシェーマをこのペインに挿入する
if (schema != null) {
stampSchema(schema);
}
}
// Editorから発行...からの通知
else if (prop.equals(AbstractStampEditor.VALUE_PROP)) {
Object o = e.getNewValue();
// 編集された Stamp をこのペインに挿入する
if (o!=null && o instanceof ModuleModel) {
ModuleModel stamp = (ModuleModel) o;
stamp(stamp);
}
}
}
/**
* メニュー制御のため、ペースト可能かどうかを返す。
* @return ペースト可能な時 true
*/
protected boolean canPaste() {
boolean ret = false;
Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
if (t == null) {
return false;
}
if (t.isDataFlavorSupported(DataFlavor.stringFlavor)) {
return true;
}
if (getMyRole().equals(IInfoModel.ROLE_P)) {
if (t.isDataFlavorSupported(OrderListTransferable.orderListFlavor) ||
t.isDataFlavorSupported(LocalStampTreeNodeTransferable.localStampTreeNodeFlavor)) {
ret = true;
}
} else {
if (t.isDataFlavorSupported(SchemaListTransferable.schemaListFlavor) ||
t.isDataFlavorSupported(LocalStampTreeNodeTransferable.localStampTreeNodeFlavor) ||
t.isDataFlavorSupported(DataFlavor.javaFileListFlavor) ||
t.isDataFlavorSupported(AttachmentTransferable.attachmentFlavor)) {
ret = true;
}
}
return ret;
}
/**
* このペインからスタンプを削除する。
* @param sh 削除するスタンプのホルダ
* @param savePos
*/
//s.oh^ 2013/11/26 スクロールバーのリセット
//public void removeStamp(StampHolder sh) {
public void removeStamp(StampHolder sh, boolean savePos) {
//s.oh$
//getDocument().removeStamp(sh.getStartPos(), 2);
//masuda^ editableの場合のみ削除
if (!getTextPane().isEditable()) {
return;
}
//masuda$
KarteStyledDocument doc = getDocument();
Element root = doc.getDefaultRootElement();
//s.oh^ 2013/11/26 スクロールバーのリセット
//deleteStamp(root, sh);
deleteStamp(root, sh, savePos);
//s.oh$
}
/**
* このペインからスタンプを削除する。
* @param sh 削除するスタンプのホルダリスト
*/
public void removeStamp(StampHolder[] sh) {
if (sh != null && sh.length > 0) {
for (StampHolder sh1 : sh) {
//s.oh^ 2013/11/26 スクロールバーのリセット
//removeStamp(sh[i]);
removeStamp(sh1, false);
//s.oh$
}
}
}
/**
* このペインからシェーマを削除する。
* @param sh 削除するシェーマのホルダ
*/
public void removeSchema(SchemaHolder sh) {
//masuda^ editableの場合のみ削除
if (!getTextPane().isEditable()) {
return;
}
//masuda$
getDocument().removeStamp(sh.getStartPos(), 2);
}
/**
* このペインからシェーマを削除する。
* @param sh 削除するシェーマのホルダリスト
*/
public void removeSchema(SchemaHolder[] sh) {
if (sh != null && sh.length > 0) {
for (SchemaHolder sh1 : sh) {
removeSchema(sh1);
}
}
}
/**
* このペインからシAttachmentを削除する。
* @param ah
*/
public void removeAttachment(AttachmentHolder ah) {
getDocument().removeStamp(ah.getStartPos(), 2);
}
/**
* 処方日数を一括変更する。
* @param number 日数
*/
public void changeAllRPNumDates(int number) {
List<StampHolder> list = getStamps(IInfoModel.ENTITY_MED_ORDER);
if (list.isEmpty()) {
Toolkit.getDefaultToolkit().beep();
return;
}
String numStr = String.valueOf(number);
for (StampHolder sh : list) {
ModuleModel module = sh.getStamp();
IInfoModel model = module.getModel();
if (model!=null && (model instanceof BundleMed)) {
BundleMed med = (BundleMed)model;
if (med.getClassCode().startsWith("21")) {// changed 12>-2
med.setBundleNumber(numStr);
sh.setStamp(module);
}
}
}
this.setDirty(true);
this.getTextPane().validate();
this.getTextPane().repaint();
//s.oh^ 2014/10/06 処方日数変更修正
if(mergeAllRpHolder()) {
this.getTextPane().validate();
this.getTextPane().repaint();
}
//s.oh$
}
//s.oh^ 2014/10/06 処方日数変更修正
private boolean mergeAllRpHolder() {
if(Project.getBoolean("merge.rp.with.sameAdmin")) {
List<StampHolder> list = getStamps(IInfoModel.ENTITY_MED_ORDER);
for(StampHolder tmp : list) {
StampHolder sh = findCanMergeRpHolder(tmp);
if(sh != null) {
tmp.addItems(((BundleMed)sh.getStamp().getModel()).getClaimItem());
removeStamp(sh, false);
mergeAllRpHolder();
return true;
}
}
}
return false;
}
//s.oh$
public boolean hasRP() {
if ((!getTextPane().isEditable())) {
return false;
}
List<StampHolder> list = getStamps(IInfoModel.ENTITY_MED_ORDER);
return (!list.isEmpty());
}
public boolean hasLabtest() {
if ((!getTextPane().isEditable())) {
return false;
}
//s.oh^ 2014/10/07 検体検査オーダー条件変更
//List<StampHolder> list = getStamps(IInfoModel.ENTITY_LABO_TEST);
//return (!list.isEmpty());
List<ModuleModel> list = getDocument().getStamps();
if(list != null) {
for(ModuleModel mm : list) {
if(mm.getModel() instanceof BundleDolphin) {
String labTest = ClientContext.getMyBundle(KartePane.class).getString("orderName.labTest");
if(((BundleDolphin)mm.getModel()).getOrderName() != null && ((BundleDolphin)mm.getModel()).getOrderName().startsWith(labTest)) {
return true;
}
}
}
}
return false;
//s.oh$
}
private List<StampHolder> getStamps(String entity) {
KarteStyledDocument doc = getDocument();
List<StampHolder> list = doc.getStampHoldersToMatch(entity);
return list;
}
public boolean hasSelection() {
return hasSelection;
}
//s.oh^ 2013/11/26 スクロールバーのリセット
//private void deleteStamp(Element element, StampHolder sh){
private void deleteStamp(Element element, StampHolder sh, boolean savePos){
//s.oh$
if (element==null) {
return;
}
int start = element.getStartOffset();
int end = element.getEndOffset();
boolean deleted = false;
AttributeSet atts = element.getAttributes().copyAttributes();
if (atts!=null) {
Enumeration names = atts.getAttributeNames();
while (names.hasMoreElements()) {
Object nextName = names.nextElement();
if (nextName != StyleConstants.ResolveAttribute) {
if (nextName.toString().startsWith("$")) {
continue;
}
Object attObject = atts.getAttribute(nextName);
if (attObject!=null && (attObject==sh)) {
getDocument().removeStamp(start, end);
//s.oh^ 2013/11/26 スクロールバーのリセット
if(savePos && textPane != null) textPane.setCaretPosition(start);
//s.oh$
deleted = true;
break;
}
}
}
}
int cnt = element.getElementCount();
for (int i = 0; i < cnt; i++) {
Element e = element.getElement(i);
//s.oh^ 2013/11/26 スクロールバーのリセット
//deleteStamp(e, sh);
deleteStamp(e, sh, savePos);
//s.oh$
}
}
/**
* 用法でマージ可能な最初の処方Stampを返す。
* @param target
* @return 処方Stamp
*/
public StampHolder findCanMergeRp(ModuleModel target) {
StampHolder found=null;
List <StampHolder> rps = this.getDocument().getStampHoldersToMatch(IInfoModel.ENTITY_MED_ORDER);
if (!rps.isEmpty()) {
// stampしようとしている stamp
BundleMed targetMed = (BundleMed)target.getModel();
// 処方リストをイテレートし、最初に見つかったものへまとめる
for (StampHolder sh : rps) {
BundleMed med = (BundleMed)sh.getStamp().getModel();
if (med.canMerge(targetMed)) {
found = sh;
break;
}
}
}
return found;
}
/**
* 用法でマージ可能な最初の処方Stampを返す。
* @param target
* @return 処方Stamp
*/
public StampHolder findCanMergeRpHolder(StampHolder target) {
StampHolder found=null;
List <StampHolder> rps = this.getDocument().getStampHoldersToMatch(IInfoModel.ENTITY_MED_ORDER);
if (!rps.isEmpty()) {
// stampしようとしている stamp
BundleMed targetMed = (BundleMed)target.getStamp().getModel();
// 処方リストをイテレートし、最初に見つかったものへまとめる
for (StampHolder sh : rps) {
if (sh==target) {
continue;
}
BundleMed med = (BundleMed)sh.getStamp().getModel();
if (med.canMerge(targetMed)) {
found = sh;
break;
}
}
}
return found;
}
//s.oh^ 2014/01/27 同じ検体検査をまとめる
/**
* 検体検査でマージ可能な最初の処方Stampを返す。
* @param target
* @return 処方Stamp
*/
public StampHolder findCanMergeLabTest(ModuleModel target) {
StampHolder found=null;
List <StampHolder> rps = this.getDocument().getStampHoldersToMatch(IInfoModel.ENTITY_LABO_TEST);
if (!rps.isEmpty()) {
// stampしようとしている stamp
BundleDolphin targetLab = (BundleDolphin)target.getModel();
// 処方リストをイテレートし、最初に見つかったものへまとめる
for (StampHolder sh : rps) {
BundleDolphin lab = (BundleDolphin)sh.getStamp().getModel();
if(targetLab.getBundleNumber() != null && lab.getBundleNumber() != null && targetLab.getBundleNumber().equals(lab.getBundleNumber())) {
//if (lab.canMerge(targetMed)) {
found = sh;
break;
//}
}
}
}
return found;
}
/**
* 検体検査でマージ可能な最初の処方Stampを返す。
* @param target
* @return 処方Stamp
*/
public StampHolder findCanMergeLabTestHolder(StampHolder target) {
StampHolder found=null;
List <StampHolder> rps = this.getDocument().getStampHoldersToMatch(IInfoModel.ENTITY_LABO_TEST);
if (!rps.isEmpty()) {
// stampしようとしている stamp
BundleDolphin targetLab = (BundleDolphin)target.getStamp().getModel();
// 処方リストをイテレートし、最初に見つかったものへまとめる
for (StampHolder sh : rps) {
if (sh==target) {
continue;
}
BundleDolphin lab = (BundleDolphin)sh.getStamp().getModel();
if(targetLab.getBundleNumber() != null && lab.getBundleNumber() != null && targetLab.getBundleNumber().equals(lab.getBundleNumber())) {
//if (lab.canMerge(targetMed)) {
found = sh;
break;
//}
}
}
}
return found;
}
//s.oh$
//s.oh^ 2014/01/27 スタンプのテキストコピー機能拡張
public void setPatID(String patID) {
this.patID = patID;
}
public String getPatID() {
return patID;
}
//s.oh$
}