package open.dolphin.stampbox; import java.awt.Color; import java.awt.Component; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.XMLEncoder; import java.io.*; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.logging.Level; import javax.swing.*; import javax.swing.event.TreeModelEvent; import javax.swing.event.TreeModelListener; import javax.swing.tree.*; import open.dolphin.client.ClientContext; import open.dolphin.delegater.StampDelegater; import open.dolphin.helper.SimpleWorker; import open.dolphin.infomodel.*; import open.dolphin.project.Project; import open.dolphin.util.GUIDGenerator; /** * StampTree * * @author Kazushi Minagawa, Digital Globe, Inc. */ public class StampTree extends JTree implements TreeModelListener { public static final String SELECTED_NODE_PROP = "selectedNodeProp"; private static final int TOOLTIP_LENGTH = 35; // ASP Tree かどうかのフラグ private boolean asp; // 個人用Treeかどうかのフラグ private boolean userTree; // StampBox private StampBoxPlugin stampBox; // timerTask 関連 private SimpleWorker worker; private javax.swing.Timer taskTimer; private ProgressMonitor monitor; private int delayCount; private final int maxEstimation = 60*1000; // 60 秒 private final int delay = 300; // 300 mmsec /** * StampTreeオブジェクトを生成する。 * * @param model TreeModel */ public StampTree(TreeModel model) { super(model); this.putClientProperty("JTree.lineStyle", "Angled"); // 水平及び垂直線を使用する this.setEditable(false); // ノード名を編集不可にする this.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); // Single Selection// にする this.setRootVisible(false); // root visible this.setDragEnabled(true); // Drag 可能 // デフォルトのセルレンダラーを置き換える TreeCellRenderer oldRenderer = this.getCellRenderer(); this.setCellRenderer(new StampTreeRenderer(oldRenderer)); // Listens TreeModelEvent model.addTreeModelListener(StampTree.this); // Enable ToolTips enableToolTips(true); } /** * このStampTreeのTreeInfoを返す。 * @return Tree情報 */ public TreeInfo getTreeInfo() { StampTreeNode node = (StampTreeNode)this.getModel().getRoot(); TreeInfo info = (TreeInfo)node.getUserObject(); return info; } /** * このStampTreeのエンティティを返す。 * @return エンティティ */ public String getEntity() { return getTreeInfo().getEntity(); } /** * このStampTreeの名前を返す。 * @return 名前 */ public String getTreeName() { return getTreeInfo().getName(); } /** * UserTreeかどうかを返す。 * @return UserTreeの時true */ public boolean isUserTree() { return userTree; } /** * UserTreeかどうかを設定する。 * @param userTree UserTreeの時true */ public void setUserTree(boolean userTree) { this.userTree = userTree; } /** * ASP提供Treeかどうかを返す。 * @return ASP提供の時 true */ public boolean isAsp() { return asp; } /** * ASP提供Treeかどうかを設定する。 * @param asp ASP提供の時 true */ public void setAsp(boolean asp) { this.asp = asp; } /** * Enable or disable tooltip * @param state */ public final void enableToolTips(boolean state) { ToolTipManager mgr = ToolTipManager.sharedInstance(); if (state) { // Enable tooltips mgr.registerComponent(this); } else { mgr.unregisterComponent(this); } } /** * Set StampBox reference * @param stampBox */ public void setStampBox(StampBoxPlugin stampBox) { this.stampBox = stampBox; } /** * 選択されているノードを返す。 * @return */ public StampTreeNode getSelectedNode() { return (StampTreeNode)this.getLastSelectedPathComponent(); } /** * 引数のポイント位置のノードを返す。 * @param p * @return */ public StampTreeNode getNode(Point p) { TreePath path = this.getPathForLocation(p.x, p.y); return (path!=null) ? (StampTreeNode)path.getLastPathComponent() : null; } /** * このStampTreeにenter()する。 */ public void enter() { } /** * Stamp を treeに追加する * @param parent 親ノード * @param droppedStamp 追加するStamp * @param childIndex 追加するインデックス * @return 成功した場合に true */ public boolean addStamp(final StampTreeNode parent, ModuleModel droppedStamp, final int childIndex) { boolean ret = false; if (parent==null || droppedStamp==null) { return ret; } //--------------------------------------- // Drop された Stamp の ModuleInfoを得る //--------------------------------------- ModuleInfoBean droppedInfo = droppedStamp.getModuleInfoBean(); //---------------------------------------------- // データベースへ droppedStamp のデータモデルを保存する //---------------------------------------------- // Entityを生成する final StampModel stampModel = new StampModel(); final String stampId = GUIDGenerator.generate(stampModel); // stampId stampModel.setId(stampId); stampModel.setUserId(Project.getUserModel().getId()); // userId stampModel.setEntity(droppedInfo.getEntity()); // entity stampModel.setStampBytes(getXMLBytes(droppedStamp.getModel())); // XML //---------------------------------------------- // Tree に加える新しい StampInfo を生成する //---------------------------------------------- final ModuleInfoBean info = new ModuleInfoBean(); info.setStampName(droppedInfo.getStampName()); // オリジナル名 info.setEntity(droppedInfo.getEntity()); // Entity info.setStampRole(droppedInfo.getStampRole()); // Role info.setStampMemo(constractToolTip(droppedStamp)); // Tooltip info.setStampId(stampId); // StampID worker = new SimpleWorker<String, Void>() { @Override protected String doInBackground() throws Exception { StampDelegater sdl = new StampDelegater(); String ret = sdl.putStamp(stampModel); return ret; } @Override protected void succeeded(String result) { StampTreeNode node = new StampTreeNode(info); DefaultTreeModel model = (DefaultTreeModel)StampTree.this.getModel(); int index = childIndex!=-1 ? childIndex : parent.getChildCount(); model.insertNodeInto(node, parent, index); } @Override protected void cancelled() { java.util.logging.Logger.getLogger(this.getClass().getName()).fine("addStamp cancelled"); } @Override protected void failed(java.lang.Throwable cause) { java.util.logging.Logger.getLogger(this.getClass().getName()).warning("addStamp failed"); java.util.logging.Logger.getLogger(this.getClass().getName()).warning(cause.getCause().getMessage()); java.util.logging.Logger.getLogger(this.getClass().getName()).warning(cause.getMessage()); } @Override protected void startProgress() { delayCount = 0; taskTimer.start(); } @Override protected void stopProgress() { taskTimer.stop(); monitor.close(); taskTimer = null; monitor = null; } }; java.util.ResourceBundle bundle = ClientContext.getMyBundle(StampTree.class); String message = bundle.getString("message.progress"); String fmt = bundle.getString("messageFormat.note.saving"); String note = new MessageFormat(fmt).format(new Object[]{info.getStampName()}); Component c = SwingUtilities.getWindowAncestor(this); monitor = new ProgressMonitor(c, message, note, 0, maxEstimation / delay); taskTimer = new Timer(delay, (ActionEvent e) -> { delayCount++; if (monitor.isCanceled() && (!worker.isCancelled())) { worker.cancel(true); } else { monitor.setProgress(delayCount); } }); worker.execute(); return true; } /** * 1. KartePaneから drop されたスタンプをツリーに加える。 * 2. スタンプ道具箱エディタで編集されたスタンプを加える。 * @param droppedStamp * @param selected * @return */ public boolean addStamp(ModuleModel droppedStamp, final StampTreeNode selected) { boolean ret = false; if (droppedStamp == null) { return ret; } //--------------------------------------- // Drop された Stamp の ModuleInfoを得る //--------------------------------------- ModuleInfoBean droppedInfo = droppedStamp.getModuleInfoBean(); //---------------------------------------------- // データベースへ droppedStamp のデータモデルを保存する //---------------------------------------------- // Entityを生成する final StampModel stampModel = new StampModel(); final String stampId = GUIDGenerator.generate(stampModel); // stampId stampModel.setId(stampId); stampModel.setUserId(Project.getUserModel().getId()); // userId stampModel.setEntity(droppedInfo.getEntity()); // entity stampModel.setStampBytes(getXMLBytes(droppedStamp.getModel())); // XML //---------------------------------------------- // Tree に加える新しい StampInfo を生成する //---------------------------------------------- final ModuleInfoBean info = new ModuleInfoBean(); info.setStampName(droppedInfo.getStampName()); // オリジナル名 info.setEntity(droppedInfo.getEntity()); // Entity info.setStampRole(droppedInfo.getStampRole()); // Role info.setStampMemo(constractToolTip(droppedStamp)); // Tooltip info.setStampId(stampId); // StampID worker = new SimpleWorker<String, Void>() { @Override protected String doInBackground() throws Exception { StampDelegater sdl = new StampDelegater(); String ret = sdl.putStamp(stampModel); return ret; } @Override protected void succeeded(String result) { addInfoToTree(info, selected); } @Override protected void cancelled() { java.util.logging.Logger.getLogger(this.getClass().getName()).fine("addStamp cancelled"); } @Override protected void failed(java.lang.Throwable cause) { java.util.logging.Logger.getLogger(this.getClass().getName()).warning("addStamp failed"); java.util.logging.Logger.getLogger(this.getClass().getName()).warning(cause.getCause().getMessage()); java.util.logging.Logger.getLogger(this.getClass().getName()).warning(cause.getMessage()); } @Override protected void startProgress() { delayCount = 0; taskTimer.start(); } @Override protected void stopProgress() { taskTimer.stop(); monitor.close(); taskTimer = null; monitor = null; } }; java.util.ResourceBundle bundle = ClientContext.getMyBundle(StampTree.class); String message = bundle.getString("message.progress"); String fmt = bundle.getString("messageFormat.note.saving"); String note = new MessageFormat(fmt).format(new Object[]{info.getStampName()}); Component c = SwingUtilities.getWindowAncestor(this); monitor = new ProgressMonitor(c, message, note, 0, maxEstimation / delay); taskTimer = new Timer(delay, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { delayCount++; if (monitor.isCanceled() && (!worker.isCancelled())) { worker.cancel(true); } else { monitor.setProgress(delayCount); } } }); worker.execute(); worker.execute(); return true; } /** * StampTree に新しいノードを加える。 * @param info 追加するノードの情報 * @param selected カーソルの下にあるノード(Drop 位置のノード) */ public void addInfoToTree(ModuleInfoBean info, StampTreeNode selected) { //---------------------------------------------- // StampInfo から新しい StampTreeNode を生成する //---------------------------------------------- StampTreeNode node = new StampTreeNode(info); //---------------------------------------------- // Drop 位置のノードによって追加する位置を決める //---------------------------------------------- if (selected != null && selected.isLeaf()) { //---------------------------------------------- // Drop位置のノードが葉の場合、その前に挿入する //---------------------------------------------- StampTreeNode newParent = (StampTreeNode) selected.getParent(); int index = newParent.getIndex(selected); DefaultTreeModel model = (DefaultTreeModel) this.getModel(); model.insertNodeInto(node, newParent, index); //---------------------------------------------- // 追加したノードを選択する //---------------------------------------------- TreeNode[] path = model.getPathToRoot(node); ((JTree)this).setSelectionPath(new TreePath(path)); } else if (selected != null && (!selected.isLeaf())) { //---------------------------------------------- // Drop位置のノードが子を持つ時、最後の子として挿入する //---------------------------------------------- DefaultTreeModel model = (DefaultTreeModel) this.getModel(); model.insertNodeInto(node, selected, selected.getChildCount()); //---------------------------------------------- // 追加したノードを選択する //---------------------------------------------- TreeNode[] path = model.getPathToRoot(node); ((JTree)this).setSelectionPath(new TreePath(path)); } else { //--------------------------------------------------------- // Drop 位置のノードが null でコールされるケースがある // 1. このtreeのスタンプではない場合、該当するTreeのルートに加える // 2. パス Tree など、まだノードを持たない初期状態の時 //--------------------------------------------------------- // Stamp ボックスから entity に対応する tree を得る StampTree another = stampBox.getStampTree(info.getEntity()); boolean myTree = (another == this); final String treeName = another.getTreeName(); DefaultTreeModel model = (DefaultTreeModel) another.getModel(); StampTreeNode root = (StampTreeNode) model.getRoot(); root.add(node); model.reload(root); //--------------------------------------------------------- // 追加したノードを選択する //--------------------------------------------------------- TreeNode[] path = model.getPathToRoot(node); ((JTree)this).setSelectionPath(new TreePath(path)); // メッセージを表示する if (!myTree) { SwingUtilities.invokeLater(() -> { java.util.ResourceBundle bundle = ClientContext.getMyBundle(StampTree.class); String fmt = bundle.getString("meesageFormat.savedInPersonalBox"); String msg = new MessageFormat(fmt).format(new Object[]{treeName}); String title = bundle.getString("message.progress"); JOptionPane.showMessageDialog( StampTree.this, msg, ClientContext.getFrameTitle(title), JOptionPane.INFORMATION_MESSAGE); }); } } } /** * Stampを置き換える。 * @param stampToReplcae 置き換えるスタンプ */ public void replaceStamp(ModuleModel stampToReplcae) { if (stampToReplcae == null) { return; } // 置き換える Stamp の ModuleInfoを得る ModuleInfoBean stampInfo = stampToReplcae.getModuleInfoBean(); //------------------------------------------------- // データベースへ stampToReplcae のデータモデルを保存する // Entityを生成する //------------------------------------------------- final StampModel stampModel = new StampModel(); final String stampId = stampInfo.getStampId(); // stampId stampModel.setId(stampId); stampModel.setUserId(Project.getUserModel().getId()); // userId stampModel.setEntity(stampInfo.getEntity()); // entity stampModel.setStampBytes(getXMLBytes(stampToReplcae.getModel())); // XML //s.oh^ 2013/11/08 スタンプ置換不具合 stampInfo.setStampMemo(constractToolTip(stampToReplcae)); // Tooltip //s.oh$ worker = new SimpleWorker<String, Void>() { @Override protected String doInBackground() throws Exception { StampDelegater sdl = new StampDelegater(); String ret = sdl.replaceStamp(stampModel); return ret; } @Override protected void succeeded(String result) { } @Override protected void cancelled() { java.util.logging.Logger.getLogger(this.getClass().getName()).fine("addStamp cancelled"); } @Override protected void failed(java.lang.Throwable cause) { java.util.logging.Logger.getLogger(this.getClass().getName()).warning("addStamp failed"); java.util.logging.Logger.getLogger(this.getClass().getName()).warning(cause.getCause().toString()); java.util.logging.Logger.getLogger(this.getClass().getName()).warning(cause.getMessage()); } @Override protected void startProgress() { delayCount = 0; taskTimer.start(); } @Override protected void stopProgress() { taskTimer.stop(); monitor.close(); taskTimer = null; monitor = null; } }; java.util.ResourceBundle bundle = ClientContext.getMyBundle(StampTree.class); String message = bundle.getString("message.progress"); String fmt = bundle.getString("messageFormat.note.saving"); String note = new MessageFormat(fmt).format(new Object[]{stampInfo.getStampName()}); Component c = SwingUtilities.getWindowAncestor(this); monitor = new ProgressMonitor(c, message, note, 0, maxEstimation / delay); taskTimer = new Timer(delay, (ActionEvent e) -> { delayCount++; if (monitor.isCanceled() && (!worker.isCancelled())) { worker.cancel(true); } else { monitor.setProgress(delayCount); } }); worker.execute(); } /** * Diagnosis Table から Drag & Drop されたRegisteredDiagnosisをスタンプ化する。 * @param parent * @param rd * @param childIndex * @return */ public boolean addDiagnosis(final StampTreeNode parent, RegisteredDiagnosisModel rd, final int childIndex) { if ((parent==null) || (rd==null)) { return false; } // クリア rd.setId(0L); rd.setKarteBean(null); rd.setUserModel(null); rd.setDiagnosisCategoryModel(null); rd.setDiagnosisOutcomeModel(null); rd.setFirstEncounterDate(null); rd.setStartDate(null); rd.setEndDate(null); rd.setRelatedHealthInsurance(null); rd.setFirstConfirmDate(null); rd.setConfirmDate(null); rd.setStatus(null); rd.setPatientLiteModel(null); rd.setUserLiteModel(null); RegisteredDiagnosisModel add = new RegisteredDiagnosisModel(); add.setDiagnosis(rd.getDiagnosis()); add.setDiagnosisCode(rd.getDiagnosisCode()); add.setDiagnosisCodeSystem(rd.getDiagnosisCodeSystem()); //ModuleModel stamp = new ModuleModel(); //stamp.setModel(add); // データベースへ Stamp のデータモデルを永続化する final StampModel addStamp = new StampModel(); final String stampId = GUIDGenerator.generate(addStamp); // stampId addStamp.setId(stampId); addStamp.setUserId(Project.getUserModel().getId()); // user pk addStamp.setEntity(IInfoModel.ENTITY_DIAGNOSIS); // entity //addStamp.setStampBytes(getXMLBytes(stamp.getModel())); // RD data のバイト addStamp.setStampBytes(getXMLBytes(add)); // RD data のバイト // Tree に加える 新しい StampInfo を生成する final ModuleInfoBean info = new ModuleInfoBean(); info.setStampId(stampId); // Stamp ID info.setStampName(add.getDiagnosis()); // 傷病名 info.setEntity(IInfoModel.ENTITY_DIAGNOSIS); // カテゴリ info.setStampRole(IInfoModel.ENTITY_DIAGNOSIS); // Role StringBuilder buf = new StringBuilder(); buf.append(add.getDiagnosis()); String cd = add.getDiagnosisCode(); if (cd != null) { buf.append("("); buf.append(cd); buf.append(")"); // Tooltip } info.setStampMemo(buf.toString()); worker = new SimpleWorker<String, Void>() { @Override protected String doInBackground() throws Exception { StampDelegater sdl = new StampDelegater(); String ret = sdl.putStamp(addStamp); return ret; } @Override protected void succeeded(String result) { StampTreeNode node = new StampTreeNode(info); DefaultTreeModel model = (DefaultTreeModel)StampTree.this.getModel(); int index = childIndex!=-1 ? childIndex : parent.getChildCount(); model.insertNodeInto(node, parent, index); } @Override protected void cancelled() { java.util.logging.Logger.getLogger(this.getClass().getName()).fine("addDiagnosis cancelled"); } @Override protected void failed(java.lang.Throwable cause) { java.util.logging.Logger.getLogger(this.getClass().getName()).warning("addDiagnosis failed"); java.util.logging.Logger.getLogger(this.getClass().getName()).warning(cause.getCause().toString()); java.util.logging.Logger.getLogger(this.getClass().getName()).warning(cause.getMessage()); } @Override protected void startProgress() { delayCount = 0; taskTimer.start(); } @Override protected void stopProgress() { taskTimer.stop(); monitor.close(); taskTimer = null; monitor = null; } }; java.util.ResourceBundle bundle = ClientContext.getMyBundle(StampTree.class); String message = bundle.getString("message.progress"); String fmt = bundle.getString("messageFormat.note.saving"); String note = new MessageFormat(fmt).format(new Object[]{info.getStampName()}); Component c = SwingUtilities.getWindowAncestor(this); monitor = new ProgressMonitor(c, message, note, 0, maxEstimation / delay); taskTimer = new Timer(delay, (ActionEvent e) -> { delayCount++; if (monitor.isCanceled() && (!worker.isCancelled())) { worker.cancel(true); } else { monitor.setProgress(delayCount); } }); worker.execute(); return true; } /** * エディタで生成した病名リストを登録する。 * @param list */ public void addDiagnosis(ArrayList<RegisteredDiagnosisModel> list) { //System.err.println("StampTree: addDiagnosis"); if (list == null || list.isEmpty()) { return; } final ArrayList<StampModel> stampList = new ArrayList<>(); final ArrayList<ModuleInfoBean> infoList = new ArrayList<>(); for (RegisteredDiagnosisModel rd : list) { // クリア rd.setId(0L); rd.setKarteBean(null); rd.setUserModel(null); rd.setDiagnosisCategoryModel(null); rd.setDiagnosisOutcomeModel(null); rd.setFirstEncounterDate(null); rd.setStartDate(null); rd.setEndDate(null); rd.setRelatedHealthInsurance(null); rd.setFirstConfirmDate(null); rd.setConfirmDate(null); rd.setStatus(null); rd.setPatientLiteModel(null); rd.setUserLiteModel(null); RegisteredDiagnosisModel add = new RegisteredDiagnosisModel(); add.setDiagnosis(rd.getDiagnosis()); add.setDiagnosisCode(rd.getDiagnosisCode()); add.setDiagnosisCodeSystem(rd.getDiagnosisCodeSystem()); //ModuleModel stamp = new ModuleModel(); //stamp.setModel(add); // データベースへ Stamp のデータモデルを永続化する StampModel addStamp = new StampModel(); String stampId = GUIDGenerator.generate(addStamp); // stampId addStamp.setId(stampId); addStamp.setUserId(Project.getUserModel().getId()); // user pk addStamp.setEntity(IInfoModel.ENTITY_DIAGNOSIS); // entity //addStamp.setStampBytes(getXMLBytes(stamp.getModel())); // RD data bytes addStamp.setStampBytes(getXMLBytes(add)); // RD data bytes stampList.add(addStamp); // Tree に加える 新しい StampInfo を生成する ModuleInfoBean info = new ModuleInfoBean(); info.setStampId(stampId); // stmap ID info.setStampName(add.getDiagnosis()); // name (傷病名) info.setEntity(IInfoModel.ENTITY_DIAGNOSIS); // entity info.setStampRole(IInfoModel.ENTITY_DIAGNOSIS); // Role StringBuilder buf = new StringBuilder(); buf.append(add.getDiagnosis()); String cd = add.getDiagnosisCode(); if (cd != null) { buf.append("("); buf.append(cd); buf.append(")"); // Tooltip } info.setStampMemo(buf.toString()); infoList.add(info); } worker = new SimpleWorker<List<String>, Void>() { @Override protected List<String> doInBackground() throws Exception { // StampModel: InfoModelのホルダーを永続する StampDelegater sdl = new StampDelegater(); sdl.putStamp(stampList); return null; } @Override protected void succeeded(List<String> result) { infoList.stream().forEach((info) -> { addInfoToTree(info, null); }); } @Override protected void cancelled() { java.util.logging.Logger.getLogger(this.getClass().getName()).fine("addDiagnosis cancelled"); } @Override protected void failed(java.lang.Throwable cause) { java.util.logging.Logger.getLogger(this.getClass().getName()).warning("addDiagnosis failed"); java.util.logging.Logger.getLogger(this.getClass().getName()).warning(cause.getCause().toString()); java.util.logging.Logger.getLogger(this.getClass().getName()).warning(cause.getMessage()); } @Override protected void startProgress() { delayCount = 0; taskTimer.start(); } @Override protected void stopProgress() { taskTimer.stop(); monitor.close(); taskTimer = null; monitor = null; } }; java.util.ResourceBundle bundle = ClientContext.getMyBundle(StampTree.class); String message = bundle.getString("message.progress"); String note = bundle.getString("note.savingDiceaseStamp"); Component c = SwingUtilities.getWindowAncestor(this); monitor = new ProgressMonitor(c, message, note, 0, maxEstimation / delay); taskTimer = new Timer(delay, (ActionEvent e) -> { delayCount++; if (monitor.isCanceled() && (!worker.isCancelled())) { worker.cancel(true); } else { monitor.setProgress(delayCount); } }); worker.execute(); } /** * テキストスタンプを追加する。 * @param parent * @param text * @param childIndex * @return */ public boolean addTextStamp(final StampTreeNode parent, String text, final int childIndex) { if ((parent==null) || (text==null) || (text.length()==0) || text.equals("")) { return false; } // TextStampModelを生成する TextStampModel stamp = new TextStampModel(); stamp.setText(text); // データベースへ Stamp のデータモデルを永続化する final StampModel addStamp = new StampModel(); final String stampId = GUIDGenerator.generate(addStamp); addStamp.setId(stampId); // stampId addStamp.setUserId(Project.getUserModel().getId()); // user pk addStamp.setEntity(IInfoModel.ENTITY_TEXT); // entity addStamp.setStampBytes(getXMLBytes((IInfoModel)stamp)); // TextStampModel->IInfoModelのバイトdata // Tree へ加える 新しい StampInfo を生成する final ModuleInfoBean info = new ModuleInfoBean(); int len = text.length() > 16 ? 16 : text.length(); String name = text.substring(0, len); len = name.indexOf("\n"); if (len > 0) { name = name.substring(0, len); } info.setStampName(name); // Stamp名 info.setEntity(IInfoModel.ENTITY_TEXT); // Entity info.setStampRole(IInfoModel.ENTITY_TEXT); // Role info.setStampMemo(text); // Tooltip info.setStampId(stampId); // Stamp ID worker = new SimpleWorker<String, Void>() { @Override protected String doInBackground() throws Exception { // StampModel: InfoModelのホルダーを永続する StampDelegater sdl = new StampDelegater(); String ret = sdl.putStamp(addStamp); return ret; } @Override protected void succeeded(String result) { // Treeには ModuleInfoBean=StampInfoをUserObjectにしたノードを加える StampTreeNode node = new StampTreeNode(info); DefaultTreeModel model = (DefaultTreeModel)StampTree.this.getModel(); int index = childIndex!=-1 ? childIndex : parent.getChildCount(); model.insertNodeInto(node, parent, index); } @Override protected void cancelled() { java.util.logging.Logger.getLogger(this.getClass().getName()).fine("addTextStamp cancelled"); } @Override protected void failed(java.lang.Throwable cause) { java.util.logging.Logger.getLogger(this.getClass().getName()).warning("addTextStamp failed"); java.util.logging.Logger.getLogger(this.getClass().getName()).warning(cause.getCause().toString()); java.util.logging.Logger.getLogger(this.getClass().getName()).warning(cause.getMessage()); } @Override protected void startProgress() { delayCount = 0; taskTimer.start(); } @Override protected void stopProgress() { taskTimer.stop(); monitor.close(); taskTimer = null; monitor = null; } }; java.util.ResourceBundle bundle = ClientContext.getMyBundle(StampTree.class); String message = bundle.getString("message.progress"); String fmt = bundle.getString("messageFormat.note.saving"); String note = new MessageFormat(fmt).format(new Object[]{info.getStampName()}); Component c = SwingUtilities.getWindowAncestor(this); monitor = new ProgressMonitor(c, message, note, 0, maxEstimation / delay); taskTimer = new Timer(delay, (ActionEvent e) -> { delayCount++; if (monitor.isCanceled() && (!worker.isCancelled())) { worker.cancel(true); } else { monitor.setProgress(delayCount); } }); worker.execute(); return true; } /** * テキストスタンプを追加する。 * @param text * @param selected * @return */ public boolean addTextStamp(String text, final StampTreeNode selected) { if ( (text == null) || (text.length() == 0) || text.equals("") ) { return false; } TextStampModel stamp = new TextStampModel(); stamp.setText(text); // // データベースへ Stamp のデータモデルを永続化する // final StampModel addStamp = new StampModel(); final String stampId = GUIDGenerator.generate(addStamp); addStamp.setId(stampId); addStamp.setUserId(Project.getUserModel().getId()); addStamp.setEntity(IInfoModel.ENTITY_TEXT); addStamp.setStampBytes(getXMLBytes((IInfoModel) stamp)); // // Tree へ加える 新しい StampInfo を生成する // final ModuleInfoBean info = new ModuleInfoBean(); int len = text.length() > 16 ? 16 : text.length(); String name = text.substring(0, len); len = name.indexOf("¥n"); if (len > 0) { name = name.substring(0, len); } info.setStampName(name); // info.setEntity(IInfoModel.ENTITY_TEXT); // カテゴリ info.setStampRole(IInfoModel.ENTITY_TEXT); // Role info.setStampMemo(text); // Tooltip info.setStampId(stampId); // Stamp ID worker = new SimpleWorker<String, Void>() { @Override protected String doInBackground() throws Exception { StampDelegater sdl = new StampDelegater(); String ret = sdl.putStamp(addStamp); return ret; } @Override protected void succeeded(String result) { addInfoToTree(info, selected); } @Override protected void cancelled() { java.util.logging.Logger.getLogger(this.getClass().getName()).fine("addTextStamp cancelled"); } @Override protected void failed(java.lang.Throwable cause) { java.util.logging.Logger.getLogger(this.getClass().getName()).warning("addTextStamp failed"); java.util.logging.Logger.getLogger(this.getClass().getName()).warning(cause.getCause().toString()); java.util.logging.Logger.getLogger(this.getClass().getName()).warning(cause.getMessage()); } @Override protected void startProgress() { delayCount = 0; taskTimer.start(); } @Override protected void stopProgress() { taskTimer.stop(); monitor.close(); taskTimer = null; monitor = null; } }; java.util.ResourceBundle bundle = ClientContext.getMyBundle(StampTree.class); String message = bundle.getString("message.progress"); String fmt = bundle.getString("messageFormat.note.saving"); String note = new MessageFormat(fmt).format(new Object[]{info.getStampName()}); Component c = SwingUtilities.getWindowAncestor(this); monitor = new ProgressMonitor(c, message, note, 0, maxEstimation / delay); taskTimer = new Timer(delay, (ActionEvent e) -> { delayCount++; if (monitor.isCanceled() && (!worker.isCancelled())) { worker.cancel(true); } else { monitor.setProgress(delayCount); } }); worker.execute(); return true; } /** * スタンプの情報を表示するための文字列を生成する。 * @param stamp 情報を生成するスタンプ * @return スタンプの情報文字列 */ protected String constractToolTip(ModuleModel stamp) { String ret = null; try { StringBuilder buf = new StringBuilder(); try (BufferedReader reader = new BufferedReader(new StringReader(stamp.getModel().toString()))) { String line; while ( (line = reader.readLine()) != null ) { buf.append(line); if (buf.length() < TOOLTIP_LENGTH) { buf.append(","); } else { break; } } } if (buf.length() > TOOLTIP_LENGTH) { buf.setLength(TOOLTIP_LENGTH); } buf.append("..."); ret = buf.toString(); } catch (IOException e) { e.toString(); } return ret; } /** * ノードの名前を変更する。 */ public void renameNode() { if (!isUserTree()) { return; } // Root へのパスを取得する StampTreeNode node = getSelectedNode(); if (node == null) { return; } TreeNode[] nodes = node.getPath(); TreePath path = new TreePath(nodes); // 編集を開始する this.setEditable(true); this.startEditingAtPath(path); // this.setEditable (false); は TreeModelListener で行う } /** * ノードを削除する。 */ public void deleteNode() { java.util.logging.Logger.getLogger(this.getClass().getName()).fine("stampTree deleteNode"); if (!isUserTree()) { return; } // // 削除するノードを取得する // 右クリックで選択されている // final StampTreeNode theNode = getSelectedNode(); if (theNode == null) { return; } // // このノードをルートにするサブツリーを前順走査する列挙を生成して返します。 // 列挙の nextElement() メソッドによって返される最初のノードは、この削除するノードです。 // Enumeration e = theNode.preorderEnumeration(); // // このリストのなかに削除するノードとその子を含める // final ArrayList<String> deleteList = new ArrayList<>(); // エディタから発行があるかどうかのフラグ boolean hasEditor = false; // 列挙する while (e.hasMoreElements()) { java.util.logging.Logger.getLogger(this.getClass().getName()).fine("stampTree deleteNode e.hasMoreElements()"); StampTreeNode node = (StampTreeNode) e.nextElement(); if (node.isLeaf()) { ModuleInfoBean info = (ModuleInfoBean) node.getUserObject(); String stampId = info.getStampId(); // // エディタから発行がある場合は中止する // String treeName = ClientContext.getMyBundle(StampTree.class).getString("treeName.fromEditor"); if (info.getStampName().equals(treeName) && (! info.isSerialized()) ) { hasEditor = true; break; } // // IDが付いているもののみを加える // if (stampId != null) { deleteList.add(stampId); java.util.logging.Logger.getLogger(this.getClass().getName()).log(Level.FINE, "added {0}", info.getStampName()); } } } // // エディタから発行が有った場合はダイアログを表示し // リターンする // if (hasEditor) { java.util.ResourceBundle bundle = ClientContext.getMyBundle(StampTree.class); String msg0 = bundle.getString("message.cannotDeleteFromEditor_1"); String msg1 = bundle.getString("message.cannotDeleteFromEditor_2"); String taskTitle = bundle.getString("title.optionPane"); //String taskTitle = ClientContext.getString("stamptree.title"); JOptionPane.showMessageDialog( (Component) null, new Object[]{msg0, msg1}, ClientContext.getFrameTitle(taskTitle), JOptionPane.INFORMATION_MESSAGE ); return; } // // 削除するフォルダが空の場合は削除してリターンする // リストのサイズがゼロかつ theNode が葉でない時 // if (deleteList.isEmpty() && (!theNode.isLeaf()) ) { DefaultTreeModel model = (DefaultTreeModel)(StampTree.this).getModel(); model.removeNodeFromParent(theNode); return; } // データベースのスタンプを削除するデリゲータを生成する final StampDelegater sdl = new StampDelegater(); worker = new SimpleWorker<Void, Void>() { @Override protected Void doInBackground() throws Exception { sdl.removeStamp(deleteList); return null; } @Override protected void succeeded(Void result) { //--------------------------------------- // 成功している場合は Tree からノードを削除する //--------------------------------------- DefaultTreeModel model = (DefaultTreeModel) (StampTree.this).getModel(); model.removeNodeFromParent(theNode); } @Override protected void cancelled() { java.util.logging.Logger.getLogger(this.getClass().getName()).fine("deleteNode cancelled"); } @Override protected void failed(java.lang.Throwable cause) { //--------------------------------------- // 失敗した場合も削除する 2011-02-9 //--------------------------------------- DefaultTreeModel model = (DefaultTreeModel) (StampTree.this).getModel(); model.removeNodeFromParent(theNode); java.util.logging.Logger.getLogger(this.getClass().getName()).warning("deleteNode failed"); java.util.logging.Logger.getLogger(this.getClass().getName()).warning(cause.getCause().toString()); java.util.logging.Logger.getLogger(this.getClass().getName()).warning(cause.getMessage()); } @Override protected void startProgress() { delayCount = 0; taskTimer.start(); } @Override protected void stopProgress() { taskTimer.stop(); monitor.close(); taskTimer = null; monitor = null; } }; java.util.ResourceBundle bundle = ClientContext.getMyBundle(StampTree.class); String message = bundle.getString("message.progress.deleteStamp"); String note = bundle.getString("note.progress.deletingStamp"); Component c = SwingUtilities.getWindowAncestor(this); monitor = new ProgressMonitor(c, message, note, 0, maxEstimation / delay); taskTimer = new Timer(delay, (ActionEvent e1) -> { delayCount++; if (monitor.isCanceled() && (!worker.isCancelled())) { worker.cancel(true); } else { monitor.setProgress(delayCount); } }); worker.execute(); } /** * 新規のフォルダを追加する */ public void createNewFolder() { if (!isUserTree()) { return; } // フォルダノードを生成する String name = ClientContext.getMyBundle(StampTree.class).getString("name.newFolder"); StampTreeNode folder = new StampTreeNode(name); // // 生成位置となる選択されたノードを得る // StampTreeNode selected = getSelectedNode(); if (selected != null && selected.isLeaf()) { // // 選択位置のノードが葉の場合、その前に挿入する // StampTreeNode newParent = (StampTreeNode) selected.getParent(); int index = newParent.getIndex(selected); DefaultTreeModel model = (DefaultTreeModel) this.getModel(); model.insertNodeInto(folder, newParent, index); } else if (selected != null && (!selected.isLeaf())) { // // 選択位置のノードが子を持つ時、最後の子として挿入する // DefaultTreeModel model = (DefaultTreeModel) this.getModel(); model.insertNodeInto(folder, selected, selected.getChildCount()); } //TreePath parentPath = new TreePath(parent.getPath()); //this.expandPath(parentPath); } @Override public void treeNodesChanged(TreeModelEvent e) { this.setEditable(false); } @Override public void treeNodesInserted(TreeModelEvent e) { } @Override public void treeNodesRemoved(TreeModelEvent e) { } @Override public void treeStructureChanged(TreeModelEvent e) { } private byte[] getXMLBytes(Object bean) { ByteArrayOutputStream bo = new ByteArrayOutputStream(); try (XMLEncoder e = new XMLEncoder(new BufferedOutputStream(bo))) { e.writeObject(bean); } return bo.toByteArray(); } class StampTreeRenderer extends DefaultTreeCellRenderer { private final Color TEXT_COLOR = new Color(0,0,153); private final Color DICEASE_COLOR = new Color(203,0,102); private final TreeCellRenderer renderer; public StampTreeRenderer(TreeCellRenderer renderer) { this.renderer = renderer; } @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row, boolean hasFocus) { JLabel c = (JLabel)renderer.getTreeCellRendererComponent( tree, value, isSelected, expanded, leaf, row, hasFocus); if (leaf) { // 共通 Object o = ((StampTreeNode)value).getUserObject(); ModuleInfoBean mi = (ModuleInfoBean)o; String entity = mi.getEntity(); String treeEntity = getTreeInfo().getEntity(); //minagawa^ Icon Server //c.setIcon(ClientContext.getImageIcon("move2_16.gif")); // icon c.setIcon(ClientContext.getImageIconArias("icon_stamp_drag_leaf")); // icon //minagawa$ c.setToolTipText(mi.getStampMemo()); // toolTips if (isSelected) { c.setForeground(getTextSelectionColor()); } else { if (treeEntity.equals(IInfoModel.ENTITY_PATH) && entity.equals(IInfoModel.ENTITY_DIAGNOSIS)) { c.setForeground(DICEASE_COLOR); } else if (treeEntity.equals(IInfoModel.ENTITY_PATH) && entity.equals(IInfoModel.ENTITY_TEXT)) { c.setForeground(TEXT_COLOR); } else { c.setForeground(getTextNonSelectionColor()); } } } else { if (isSelected) { c.setForeground(getTextSelectionColor()); } else { c.setForeground(getTextNonSelectionColor()); } } return c; } } }