package open.dolphin.stampbox; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.List; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import open.dolphin.client.*; import open.dolphin.helper.ComponentMemory; import open.dolphin.helper.WindowSupport; import open.dolphin.infomodel.*; import open.dolphin.order.EditorSetPanel; import open.dolphin.project.Project; /** * StampBox クラス。 * * @author Kazushi Minagawa, Digital Globe, Inc. */ public class StampBoxPlugin extends AbstractMainTool { // private static final String NAME = "スタンプ箱"; // frameのデフォルトの大きさ及びタイトル private final int DEFAULT_WIDTH = 320; private final int DEFAULT_HEIGHT = 690; private final int IMPORT_TREE_OFFSET = 1; // StampBox の JFrame private JFrame frame; // StampBox private JTabbedPane parentBox; //ユーザ個人用の StampBox private AbstractStampBox userBox; // 現在選択されている StampBox private AbstractStampBox curBox; // インポートしている StampTree のリスト private List<Long> importedTreeList; // 現在選択されている StampBox の情報を表示するラベル private JLabel curBoxInfo; // StampBox JFrame のcontentPane private JPanel content; // Stampmaker ボタン private JToggleButton toolBtn; // 公開ボタン private JButton publishBtn; // インポートボタン private JButton importBtn; // StampMaker のエディタセット private EditorSetPanel editors; // Editorの編集値リスナ private EditorValueListener editorValueListener; // StampMaker モードのフラグ private boolean editing; // StampBox 位置 private Point stampBoxLoc; // StampBox 幅 private int stampBoxWidth; // StampBox 高さ private int stampBoxHeight; // Block Glass Pane private BlockGlass glass; // Container Panel private JPanel stampBoxPanel; // このスタンプボックスの StmpTreeModel private List<IStampTreeModel> stampTreeModels; // Logger private static final boolean DEBUG=false; private static final java.util.logging.Logger logger; static { logger = java.util.logging.Logger.getLogger(StampBoxPlugin.class.getName()); logger.setLevel(DEBUG ? java.util.logging.Level.FINE : java.util.logging.Level.INFO); } /** * Creates new StampBoxPlugin */ public StampBoxPlugin() { String NAME = ClientContext.getMyBundle(StampBoxPlugin.class).getString("title.window"); setName(NAME); } /** * StampTreeModel を返す。 * @return StampTreeModelのリスト */ public List<IStampTreeModel> getStampTreeModels() { return stampTreeModels; } /** * StampTreeModel を設定する。 * @param stampTreeModels StampTreeModelのリスト */ public void setStampTreeModels(List<IStampTreeModel> stampTreeModels) { this.stampTreeModels = stampTreeModels; } /** * 現在のStampBoxを返す。 * @return 現在選択されているStampBox */ public AbstractStampBox getCurrentBox() { return curBox; } /** * 現在のStampBoxを設定する。 * @param curBox 選択されたStampBox */ public void setCurrentBox(AbstractStampBox curBox) { this.curBox = curBox; } /** * User(個人用)のStampBoxを返す。 * @return User(個人用)のStampBox */ public AbstractStampBox getUserStampBox() { return userBox; } /** * User(個人用)のStampBoxを設定する。 * @param userBox User(個人用)のStampBox */ public void setUserStampBox(AbstractStampBox userBox) { this.userBox = userBox; } /** * StampBox の JFrame を返す。 * @return StampBox の JFrame */ public JFrame getFrame() { return frame; } /** * インポートしているStampTreeのリストを返す。 * @return インポートしているStampTreeのリスト */ public List<Long> getImportedTreeList() { return importedTreeList; } /** * Block用GlassPaneを返す。 * @return Block用GlassPane */ public BlockGlass getBlockGlass() { return glass; } /** * プログラムを開始する。 */ @Override public void start() { if (stampTreeModels == null) { logger.severe("StampTreeModel is null"); throw new RuntimeException("Fatal error: StampTreeModel is null at start."); } // StampBoxのJFrameを生成する String title = ClientContext.getFrameTitle(getName()); Rectangle placeBounds = new Rectangle(0, 0, 1024, 768); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); int x = (screenSize.width - placeBounds.width) / 2; // left edge x = x + placeBounds.width - DEFAULT_WIDTH; int y = (screenSize.height - DEFAULT_HEIGHT) / 2; int width = DEFAULT_WIDTH; int height = DEFAULT_HEIGHT; //s.oh^ 2014/08/26 スタンプ箱の表示 //frame = new JFrame(title); WindowSupport ws = WindowSupport.create(title); frame = ws.getFrame(); //s.oh$ glass = new BlockGlass(); frame.setGlassPane(glass); frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { if (editing) { toolBtn.doClick(); } else { Toolkit.getDefaultToolkit().beep(); } } }); ComponentMemory cm = new ComponentMemory(frame, new Point(x, y), new Dimension(width, height), this); cm.setToPreferenceBounds(); // 全体のボックスを生成する parentBox = new JTabbedPane(); parentBox.setTabPlacement(JTabbedPane.BOTTOM); java.util.ResourceBundle bundle = ClientContext.getMyBundle(StampBoxPlugin.class); // 読み込んだStampTreeをTabbedPaneに格納し、さらにそれをparentBoxに追加する for (IStampTreeModel model : stampTreeModels) { if (model != null) { if (DEBUG) { logger.log(java.util.logging.Level.FINE, "id = {0}", model.getId()); logger.log(java.util.logging.Level.FINE, "name = {0}", model.getName()); logger.log(java.util.logging.Level.FINE, "publishType = {0}", model.getPublishType()); logger.log(java.util.logging.Level.FINE, "category = {0}", model.getCategory()); logger.log(java.util.logging.Level.FINE, "partyName = {0}", model.getPartyName()); logger.log(java.util.logging.Level.FINE, "url = {0}", model.getUrl()); logger.log(java.util.logging.Level.FINE, "description = {0}", model.getDescription()); logger.log(java.util.logging.Level.FINE, "publishedDate = {0}", model.getPublishedDate()); logger.log(java.util.logging.Level.FINE, "lastUpdated = {0}", model.getLastUpdated()); logger.log(java.util.logging.Level.FINE, "userId = {0}", model.getUserModel()); } // ユーザ個人用StampTreeの場合 if (model.getUserModel().getId() == Project.getUserModel().getId() && model instanceof open.dolphin.infomodel.StampTreeModel) { //------------------------------------------ // 個人用のスタンプボックス(JTabbedPane)を生成する //------------------------------------------ userBox = new UserStampBox(); userBox.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT); userBox.setContext(this); userBox.setStampTreeModel(model); userBox.buildStampBox(); // ParentBox に追加する parentBox.addTab(bundle.getString("stampTree.personal.box.name"), userBox); } else if (model instanceof PublishedTreeModel) { // インポートしているTreeの場合 importPublishedTree(model); } model.setTreeXml(null); } } // StampTreeModel を clear する stampTreeModels.clear(); // ParentBox のTab に tooltips を設定する for (int i = 0; i < parentBox.getTabCount(); i++) { AbstractStampBox box = (AbstractStampBox) parentBox.getComponentAt(i); parentBox.setToolTipTextAt(i, box.getInfo()); } // ParentBoxにChangeListenerを登録しスタンプメーカの制御を行う parentBox.addChangeListener(new BoxChangeListener()); setCurrentBox(userBox); // ユーザBox用にChangeListenerを設定する userBox.addChangeListener(new TabChangeListener()); // スタンプメーカを起動するためのボタンを生成する toolBtn = new JToggleButton(ClientContext.getImageIconArias("icon_stamp_maker")); String toolTipText = bundle.getString("toolTipText.launchStampMaker"); toolBtn.setToolTipText(toolTipText); toolBtn.addActionListener((ActionEvent e) -> { if (!editing) { startStampMake(); editing = true; } else { stopStampMake(); editing = false; } }); // スタンプ公開ボタンを生成する publishBtn = new JButton(ClientContext.getImageIconArias("icon_stamp_publish")); toolTipText = bundle.getString("toolTipText.managePublishStamp"); publishBtn.setToolTipText(toolTipText); publishBtn.addActionListener((ActionEvent e) -> { int modifiers = e.getModifiers(); if ((modifiers & MouseEvent.SHIFT_MASK) != 0) { // Shift Click で export UserStampBoxExportImporter ei = new UserStampBoxExportImporter(StampBoxPlugin.this); ei.exportUserStampBox(); } else { publishStamp(); } }); // インポートボタンを生成する importBtn = new JButton(ClientContext.getImageIconArias("icon_stamp_import")); toolTipText = bundle.getString("toolTipText.manageImportStamp"); importBtn.setToolTipText(toolTipText); importBtn.addActionListener((ActionEvent e) -> { int modifiers = e.getModifiers(); if ((modifiers & MouseEvent.SHIFT_MASK) != 0) { // Shift Click で import UserStampBoxExportImporter ei = new UserStampBoxExportImporter(StampBoxPlugin.this); ei.importUserStampBox(); } else { importStamp(); } }); // curBoxInfoラベルを生成する curBoxInfo = new JLabel(""); curBoxInfo.setFont(GUIFactory.createSmallFont()); // レイアウトする stampBoxPanel = new JPanel(new BorderLayout()); stampBoxPanel.add(parentBox, BorderLayout.CENTER); JPanel cmdPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); cmdPanel.add(toolBtn); cmdPanel.add(publishBtn); cmdPanel.add(importBtn); JPanel p = new JPanel(new FlowLayout(FlowLayout.LEFT,10,5)); p.add(curBoxInfo); JPanel p2 = new JPanel(new BorderLayout()); p2.add(cmdPanel, BorderLayout.CENTER); p2.add(p, BorderLayout.SOUTH); stampBoxPanel.add(p2, BorderLayout.NORTH); // コンテントパネルを生成する content = new JPanel(new BorderLayout()); content.add(stampBoxPanel, BorderLayout.CENTER); content.setOpaque(true); // Frame に加える frame.setContentPane(content); // 前回終了時のタブを選択する String name = this.getClass().getName(); int index = Project.getInt(name + "_parentBox", 0); index = ( index >= 0 && index <= (parentBox.getTabCount() -1) ) ? index : 0; parentBox.setSelectedIndex(index); index = Project.getInt(name + "_stampBox", 0); index = ( index >= 0 && index <= (userBox.getTabCount() -1) ) ? index : 0; // ORCA タブが選択されていて ORCA に接続がない場合を避ける int test = (int)java.util.ResourceBundle.getBundle("open.dolphin.stampbox.StampBoxResource").getObject("TAB_INDEX_ORCA"); index = index == test ? 0 : index; userBox.setSelectedIndex(index); // ボタンをコントロールする boxChanged(); } /** * 選択されているIndexでボタンを制御する。 */ private void boxChanged() { int index = parentBox.getSelectedIndex(); setCurrentBox((AbstractStampBox) parentBox.getComponentAt(index)); String info = getCurrentBox().getInfo(); curBoxInfo.setText(info); if (getCurrentBox() == userBox) { publishBtn.setEnabled(true); int index2 = userBox.getSelectedIndex(); boolean enabled = userBox.isHasEditor(index2); toolBtn.setEnabled(enabled); } else { toolBtn.setEnabled(false); publishBtn.setEnabled(false); } } /** * ImportしたStampBoxの選択可能を制御する。 * @param enabled 選択可能な時 true */ private void enabledImportBox(boolean enabled) { int cnt = parentBox.getTabCount(); for (int i = 0 ; i < cnt; i++) { if ((JTabbedPane) parentBox.getComponentAt(i) != userBox) { parentBox.setEnabledAt(i, enabled); } } } /** * TabChangeListener * User用StampBoxのTab切り替えリスナクラス。 */ class TabChangeListener implements ChangeListener { @Override public void stateChanged(ChangeEvent e) { if (!editing) { // スタンプメーカ起動中でない時 // テキストスタンプタブが選択されたらスタンプメーカボタンを disabledにする // ORCA セットタブの場合を処理する int index = userBox.getSelectedIndex(); StampTree tree = userBox.getStampTree(index); tree.enter(); boolean enabled = userBox.isHasEditor(index); toolBtn.setEnabled(enabled); } else { // スタンプメーカ起動中の時 // 選択されたタブに対応するエディタを表示する int index = userBox.getSelectedIndex(); StampTree tree = userBox.getStampTree(index); if (editors != null && (!tree.getEntity().equals(IInfoModel.ENTITY_TEXT)) ) { editors.show(tree.getEntity()); } } } } /** * ParentBox の TabChangeListenerクラス。 */ class BoxChangeListener implements ChangeListener { @Override public void stateChanged(ChangeEvent e) { boxChanged(); } } /** * スタンプメーカを起動する。 */ public void startStampMake() { if (editing) { return; } Runnable awt = () -> { createAndShowEditorSet(); }; SwingUtilities.invokeLater(awt); } /** * スタンプメーカを起動する。 */ private void createAndShowEditorSet() { // インポートボックスを選択不可にする enabledImportBox(false); // 現在の位置と大きさを保存する stampBoxLoc = frame.getLocation(); stampBoxWidth = frame.getWidth(); stampBoxHeight = frame.getHeight(); // 現在のタブからtreeのEntityを得る int index = userBox.getSelectedIndex(); StampTree tree = userBox.getStampTree(index); String entity = tree.getEntity(); // エディタセットを生成する editors = new EditorSetPanel(); // text タブを選択不可にする userBox.setHasNoEditorEnabled(false); //---------------------------------------------------------- // 全 Tree に edirorSet を treeSelectionListener として登録する //---------------------------------------------------------- List<StampTree> allTrees = userBox.getAllTrees(); allTrees.stream().forEach((st) -> { st.addTreeSelectionListener(editors); }); // Editorへ編集値を受けとるためのリスナを登録する editorValueListener = new EditorValueListener(); editors.addPropertyChangeListener(EditorSetPanel.EDITOR_VALUE_PROP, editorValueListener); // EditorSet へ現在のentity(Tree)に対応するエディタを表示させる editors.show(entity); // StampBox の Frame を再構築する frame.setVisible(false); content.removeAll(); content.add(editors, BorderLayout.CENTER); content.add(stampBoxPanel, BorderLayout.EAST); stampBoxPanel.setPreferredSize(new Dimension(300, 650)); content.revalidate(); frame.pack(); // 前回終了時の位置とサイズを取得する String name = this.getClass().getName(); int locX = Project.getInt(name + ".stampmMaker.x", 0); int locY = Project.getInt(name + ".stampmMaker.y", 0); //int width = Project.getInt(name + ".stampmMaker.width", 0); //int height = Project.getInt(name + ".stampmMaker.height", 0); int width=0; int height=0; if (width == 0 || height == 0) { // センタリングする Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); int x = (screen.width - frame.getSize().width)/2; int y = (screen.height - frame.getSize().height)/2; frame.setLocation(x, y); } else { frame.setLocation(locX, locY); frame.setSize(width, height); } frame.setVisible(true); if (editors.getCurrentEditor()!=null && editors.getCurrentEditor().getSearchTextField()!=null) { editors.getCurrentEditor().getSearchTextField().requestFocusInWindow(); } editing = true; String toolTipText = ClientContext.getMyBundle(StampBoxPlugin.class).getString("toolTipText.quitStampMaker"); toolBtn.setToolTipText(toolTipText); publishBtn.setEnabled(false); importBtn.setEnabled(false); } public void stopStampMake() { if (!editing) { return; } Runnable awt = () -> { disposeEditorSet(); }; SwingUtilities.invokeLater(awt); } /** * スタンプメーカを終了する。 */ private void disposeEditorSet() { // 現在の大きさと位置をPreferenceに保存ずる String name = this.getClass().getName(); Project.setInt(name + ".stampmMaker.x", frame.getLocation().x); Project.setInt(name + ".stampmMaker.y", frame.getLocation().y); Project.setInt(name + ".stampmMaker.width", frame.getWidth()); Project.setInt(name + ".stampmMaker.height", frame.getHeight()); editors.close(); editors.removePropertyChangeListener(EditorSetPanel.EDITOR_VALUE_PROP, editorValueListener); List<StampTree> allTrees = userBox.getAllTrees(); allTrees.stream().forEach((st) -> { st.removeTreeSelectionListener(editors); }); content.removeAll(); content.add(stampBoxPanel, BorderLayout.CENTER); editors = null; editorValueListener = null; userBox.setHasNoEditorEnabled(true); content.revalidate(); frame.setLocation(stampBoxLoc); frame.setSize(new Dimension(stampBoxWidth, stampBoxHeight)); editing = false; String toolTipText = ClientContext.getMyBundle(StampBoxPlugin.class).getString("toolTipText.launchStampMaker"); toolBtn.setToolTipText(toolTipText); publishBtn.setEnabled(true); importBtn.setEnabled(true); // // ASP ボックスを選択可にする // enabledImportBox(true); } /** * EditorValueListener * エディタで作成したスタンプをStampTreeに加える。 */ class EditorValueListener implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent e) { Object obj = e.getNewValue(); if (obj != null && obj instanceof ModuleModel) { //-------------------- // 編集したスタンプ //-------------------- ModuleModel stamp = (ModuleModel) obj; String entity = stamp.getModuleInfoBean().getEntity(); StampTree tree = userBox.getStampTree(entity); if (stamp.getModuleInfoBean().getStampId()!=null) { // stampId!=nullなら上書き tree.replaceStamp(stamp); } else { // でなければ新規 tree.addStamp(stamp, null); } } else if (obj != null && obj instanceof ArrayList) { //------------------- // 傷病名 //------------------- //System.err.println("EditorValueListener: 傷病名"); StampTree tree = getStampTree(IInfoModel.ENTITY_DIAGNOSIS); tree.addDiagnosis((ArrayList<RegisteredDiagnosisModel>) obj); } } } /** * スタンプパブリッシャーを起動する。 */ public void publishStamp() { StampPublisher publisher = new StampPublisher(this); publisher.start(); } /** * スタンプインポーターを起動する。 */ public void importStamp() { StampImporter importer = new StampImporter(this); importer.start(); } /** * 公開されているスタンプTreeをインポートする。 * @param importTree インポートする公開Tree */ public void importPublishedTree(IStampTreeModel importTree) { // Asp StampBox を生成し parentBox に加える AbstractStampBox aspBox = new AspStampBox(); aspBox.setContext(this); aspBox.setStampTreeModel(importTree); aspBox.buildStampBox(); parentBox.addTab(importTree.getName(), aspBox); // インポートリストに追加する if (importedTreeList == null) { importedTreeList = new ArrayList<>(5); } importedTreeList.add(importTree.getId()); } /** * インポートしている公開Treeを削除する。 * @param removeId 削除する公開TreeのId */ public void removeImportedTree(long removeId) { if (importedTreeList != null) { for (int i = 0; i < importedTreeList.size(); i++) { Long id = importedTreeList.get(i); if (id == removeId) { parentBox.removeTabAt(i+IMPORT_TREE_OFFSET); importedTreeList.remove(i); break; } } } } /** * プログラムを終了する。 */ @Override public void stop() { frame.setVisible(false); frame.dispose(); } /** * フレームを前面に出す。 */ @Override public void enter() { if (frame != null) { frame.toFront(); } } /** * アプリケーションの終了時にスタンプツリーを返し保存する。 * @return StamPtreeMode; */ public IStampTreeModel getUsersTreeTosave() { preSave(); // User Tree のみを保存する ArrayList<StampTree> list = (ArrayList<StampTree>) userBox.getAllTrees(); if (list == null || list.isEmpty()) { // never return null; } // ORCA セットは除く for (StampTree tree : list) { if (tree.getTreeInfo().getEntity().equals(IInfoModel.ENTITY_ORCA)) { list.remove(tree); if (DEBUG) { logger.fine("Remove the ORCA set"); } break; } } // StampTree を表す XML データを生成する DefaultStampTreeXmlBuilder builder = new DefaultStampTreeXmlBuilder(); StampTreeXmlDirector director = new StampTreeXmlDirector(builder); String treeXml = director.build(list); // 個人用のStampTreeModelにXMLをセットする IStampTreeModel treeTosave = userBox.getStampTreeModel(); treeTosave.setTreeXml(treeXml); return treeTosave; } /** * 位置大きさを保存する。 * @throws Exception */ private void preSave() { String name = (StampBoxPlugin.this).getClass().getName(); // StampMeker modeで終了した場合、 // 次回起動時に通常モードの位置と大きさで表示するため if (editing) { Project.setInt(name + "_x", stampBoxLoc.x); Project.setInt(name + "_y", stampBoxLoc.y); Project.setInt(name + "_width", stampBoxWidth); Project.setInt(name + "_height", stampBoxHeight); } // 終了時のタブ選択インデックスを保存する Project.setInt(name + "_parentBox", parentBox.getSelectedIndex()); Project.setInt(name + "_stampBox", userBox.getSelectedIndex()); } /** * 引数のカテゴリに対応するTreeを返す。 * @param entity * @return * @par * @return カテゴリにマッチするStampTree */ public StampTree getStampTree(String entity) { return getCurrentBox().getStampTree(entity); } public StampTree getStampTreeFromUserBox(String entity) { return getUserStampBox().getStampTree(entity); } /** * スタンプボックスに含まれる全treeのTreeInfoリストを返す。 * @return TreeInfoのリスト */ public List<TreeInfo> getAllTress() { return getCurrentBox().getAllTreeInfos(); } /** * スタンプボックスに含まれる全treeを返す。 * @return StampTreeのリスト */ public List<StampTree> getAllTrees() { return getCurrentBox().getAllTrees(); } /** * スタンプボックスに含まれる全treeを返す。 * @return StampTreeのリスト */ public List<StampTree> getAllAllPTrees() { int cnt = parentBox.getTabCount(); ArrayList<StampTree> ret = new ArrayList<>(); for (int i = 0; i < cnt; i++) { AbstractStampBox stb = (AbstractStampBox) parentBox.getComponentAt(i); ret.addAll(stb.getAllPTrees()); } return ret; } /** * Currentボックスの P 関連Staptreeを返す。 * @return StampTreeのリスト */ public List<StampTree> getAllPTrees() { AbstractStampBox stb = (AbstractStampBox) getCurrentBox(); return stb.getAllPTrees(); } /** * 引数のエンティティ配下にある全てのスタンプを返す。 * これはメニュー等で使用する。 * @param entity Treeのエンティティ * @return 全てのスタンプのリスト */ public List<ModuleInfoBean> getAllStamps(String entity) { return getCurrentBox().getAllStamps(entity); } }