package open.dolphin.impl.img; import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; import java.net.MalformedURLException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.*; import javax.swing.table.TableColumn; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import open.dolphin.client.ClientContext; import open.dolphin.client.GUIConst; import open.dolphin.client.ImageEntry; import open.dolphin.infomodel.DocInfoModel; import open.dolphin.infomodel.ModelUtils; import open.dolphin.project.Project; import open.dolphin.utilities.utility.FCRLink; /** * FCR連携 * @author Life Sciences Computing Corporation. */ public class FCRBrowser extends AbstractBrowser { private static final String TITLE = "PDF・画像"; private static final String SETTING_FILE_NAME = "fcr.properties"; private static final String DATE_FORMAT = "yyyyMMdd"; private ImageTableRenderer imageRenderer; private final int cellWidth = MAX_IMAGE_SIZE + CELL_WIDTH_MARGIN; private final int cellHeight = MAX_IMAGE_SIZE + CELL_HEIGHT_MARGIN; private FCRBrowserView view; private String savePath; private final boolean zeroSup; public FCRBrowser() { //s.oh^ 2013/04/18 zeroSup = Project.getBoolean("fcr.patientid.zerosuppress", false); //s.oh$ String title = Project.getString("fcr.title.name"); if(valueIsNullOrEmpty(title)) { setTitle(TITLE); }else{ setTitle(title); } // フォルダが設定されていない場合はTempフォルダを使う savePath = Project.getString("fcr.folder.path"); if(valueIsNullOrEmpty(savePath)) savePath = ClientContext.getTempDirectory(); if (valueIsNotNullNorEmpty(savePath)) { File folder = new File(savePath); if(!folder.exists()) { if(!folder.mkdirs()) { savePath = ""; } } } properties = getProperties(); // Convert the old properties Properties old = Project.loadPropertiesAsObject("imageBrowserProp2.xml"); if (old!=null) { Enumeration e = old.propertyNames(); while (e.hasMoreElements()) { String key = (String)e.nextElement(); String val = old.getProperty(key); properties.setProperty(key, val); } Project.storeProperties(properties, SETTING_FILE_NAME); Project.deleteSettingFile("imageBrowserProp2.xml"); } else { Project.loadProperties(properties, SETTING_FILE_NAME); } // Base directory String value = properties.getProperty(PROP_BASE_DIR); imageBase = valueIsNotNullNorEmpty(value) ? value : null; } @Override protected String getImgLocation() { if (getContext()==null) { view.getDirLbl().setText(""); return null; } if (valueIsNullOrEmpty(getImageBase())) { view.getDirLbl().setText("画像ディレクトリが指定されていません。"); return null; } String pid = getContext().getPatient().getPatientId(); StringBuilder sb = new StringBuilder(); sb.append(getImageBase()); if (!getImageBase().endsWith(File.separator)) { sb.append(File.separator); } sb.append(pid); String loc = sb.toString(); //if (loc.length() > 33) { // sb = new StringBuilder(); // sb.append(loc.substring(0, 15)); // sb.append("..."); // int pos = loc.length() - 15; // sb.append(loc.substring(pos)); // view.getDirLbl().setText(sb.toString()); // //} else { // view.getDirLbl().setText(loc); //} nowLocation = loc; view.getDirLbl().setText(createLocationText(nowLocation)); return loc; } private String createLocationText(String loc) { StringBuilder sb = new StringBuilder(); if (loc.length() > 33) { sb.append(loc.substring(0, 15)); sb.append("..."); int pos = loc.length() - 15; sb.append(loc.substring(pos)); } else { return loc; } return sb.toString(); } public void linkList() { if (valueIsNullOrEmpty(savePath)) { return; } FCRLink fcr = new FCRLink(savePath); try { String pid = null; //s.oh^ 2013/04/18 //fcr.linkList(getContext().getPatient().getPatientId()); if(zeroSup) { pid = zeroSuppress(getContext().getPatient().getPatientId()); }else{ pid = getContext().getPatient().getPatientId(); } fcr.linkList(pid); //s.oh$ } catch (ParserConfigurationException ex) { Logger.getLogger(FCRBrowser.class.getName()).log(Level.SEVERE, null, ex); } catch (TransformerConfigurationException ex) { Logger.getLogger(FCRBrowser.class.getName()).log(Level.SEVERE, null, ex); } catch (TransformerException ex) { Logger.getLogger(FCRBrowser.class.getName()).log(Level.SEVERE, null, ex); } } public void linkImage() { DocInfoModel[] selectModel = getContext().getDocumentHistory().getSelectedHistories(); String date = ""; if(selectModel == null || selectModel.length <= 0) { return; }else if(selectModel != null && selectModel.length == 1) { //date = ModelUtils.getDateAsFormatString(selectModel[0].getConfirmDate(), DATE_FORMAT); date = ModelUtils.getDateAsFormatString(selectModel[0].getFirstConfirmDate(), DATE_FORMAT); } linkImage(date); } public void linkToday() { Date today = new Date(); SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT); String date = sdf.format(today); linkImage(date); } public void linkThumbnail(ImageEntry entry) { String date; if(entry.getFileName().length() >= DATE_FORMAT.length()) { date = entry.getFileName().substring(0, DATE_FORMAT.length()); SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT); try { sdf.parse(date); } catch (ParseException ex) { // ファイル名の先頭8ケタが日付以外の場合は全画像検索 Logger.getLogger(FCRBrowser.class.getName()).log(Level.SEVERE, null, ex); date = ""; } }else{ // ファイル名が8ケタ未満の場合は全画像検索 date = ""; } linkImage(date); } private void linkImage(String date) { if (valueIsNullOrEmpty(savePath)) { return; } FCRLink fcr = new FCRLink(savePath); try { String pid = null; //s.oh^ 2013/04/18 //fcr.linkImage(getContext().getPatient().getPatientId(), date); if(zeroSup) { pid = zeroSuppress(getContext().getPatient().getPatientId()); }else{ pid = getContext().getPatient().getPatientId(); } fcr.linkImage(pid, date); //s.oh$ } catch (ParserConfigurationException ex) { Logger.getLogger(FCRBrowser.class.getName()).log(Level.SEVERE, null, ex); } catch (TransformerConfigurationException ex) { Logger.getLogger(FCRBrowser.class.getName()).log(Level.SEVERE, null, ex); } catch (TransformerException ex) { Logger.getLogger(FCRBrowser.class.getName()).log(Level.SEVERE, null, ex); } } private ActionMap getActionMap(ResourceBundle resource) { ActionMap ret = new ActionMap(); //String text = resource.getString("refresh.Action.text"); //minagawa^ Icon Server //ImageIcon icon = ClientContext.getImageIcon("ref_16.gif"); ImageIcon icon = ClientContext.getImageIconArias("icon_refresh_small"); //minagawa$ AbstractAction refresh = new AbstractAction("更新",icon) { @Override public void actionPerformed(ActionEvent ae) { //s.oh^ 2014/05/07 PDF・画像タブの改善 if(isScanning(getContext().getFrame(), "更新できません。")) return; //s.oh$ scan(getImgLocation()); nowLocation = getImgLocation(); view.getDirLbl().setText(createLocationText(nowLocation)); } }; ret.put("refresh", refresh); //text = resource.getString("doSetting.Action.text"); //minagawa^ Icon Server //icon = ClientContext.getImageIcon("confg_16.gif"); icon = ClientContext.getImageIconArias("icon_setting_small"); //minagawa$ AbstractAction doSetting = new AbstractAction("設定",icon) { @Override public void actionPerformed(ActionEvent ae) { //s.oh^ 2014/05/07 PDF・画像タブの改善 if(isScanning(getContext().getFrame(), "設定を変更できません。")) return; //s.oh$ // 現在のパラメータを保存し、Setting dialog を開始する int oldCount = columnCount(); boolean oldShow = showFilename(); boolean oldDisplayIsFilename = displayIsFilename(); boolean oldSortIsLastModified = sortIsLastModified(); boolean oldSortIsDescending = sortIsDescending(); String oldBase = properties.getProperty(PROP_BASE_DIR); oldBase = valueIsNotNullNorEmpty(oldBase) ? oldBase : ""; // 設定ダイアログを起動する FCRSetting setting = new FCRSetting(FCRBrowser.this, getUI()); setting.start(); // 結果は properties にセットされて返ってくるので save する Project.storeProperties(properties, SETTING_FILE_NAME); // 新たに設定された値を読む int newCount = columnCount(); boolean newShow = showFilename(); boolean newDisplayIsFilename = displayIsFilename(); boolean newSortIsLastModified = sortIsLastModified(); boolean newSortIsDescending = sortIsDescending(); String newBase = properties.getProperty(PROP_BASE_DIR); newBase = valueIsNotNullNorEmpty(newBase) ? newBase : ""; // 更新ボタンの enabled boolean canRefresh = true; canRefresh = canRefresh && (!newBase.equals("")); view.getRefreshBtn().setEnabled(canRefresh); boolean needsRefresh = false; // カラム数変更 if (newCount != oldCount) { needsRefresh = true; tableModel = new ImageTableModel(null, newCount); table.setModel(tableModel); TableColumn column; for (int i = 0; i < newCount; i++) { column = table.getColumnModel().getColumn(i); column.setPreferredWidth(cellWidth); } table.setRowHeight(cellHeight); } needsRefresh = (needsRefresh || (newShow!=oldShow) || (newDisplayIsFilename!=oldDisplayIsFilename) || (newSortIsLastModified!=oldSortIsLastModified) || (newSortIsDescending!=oldSortIsDescending)); // ベースディレクトリ if (!newBase.equals(oldBase)) { setImageBase(newBase); } else if (needsRefresh) { scan(getImgLocation()); nowLocation = getImgLocation(); view.getDirLbl().setText(createLocationText(nowLocation)); } } }; ret.put("doSetting", doSetting); // FCR List //icon = ClientContext.getImageIcon("web_16.gif"); String text = resource.getString("linkList.Action.text"); AbstractAction linkList = new AbstractAction(text) { @Override public void actionPerformed(ActionEvent ae) { linkList(); } }; ret.put("linkList", linkList); // FCR Image //icon = ClientContext.getImageIcon("web_16.gif"); text = resource.getString("linkImage.Action.text"); AbstractAction linkImage = new AbstractAction(text) { @Override public void actionPerformed(ActionEvent ae) { linkImage(); } }; ret.put("linkImage", linkImage); // FCR Today //icon = ClientContext.getImageIcon("web_16.gif"); text = resource.getString("linkToday.Action.text"); AbstractAction linkToday = new AbstractAction(text) { @Override public void actionPerformed(ActionEvent ae) { linkToday(); } }; ret.put("linkToday", linkToday); //s.oh^ 2014/05/07 PDF・画像タブの改善 icon = ClientContext.getImageIconArias("icon_delete"); AbstractAction delete = new AbstractAction("削除", icon) { @Override public void actionPerformed(ActionEvent ae) { if(isScanning(getContext().getFrame(), "ファイル/フォルダを削除できません。")) return; int row = table.getSelectedRow(); int col = table.getSelectedColumn(); if(row < 0 || col < 0) return; ImageEntry entry = getEntryAt(row, col); if(entry == null) return; //String yes = "はい"; //String no = "いいえ"; //Object[] options = new Object[]{yes, no}; //if (ClientContext.isMac()) { // options = new Object[]{no, yes}; //}else{ // options = new Object[]{yes, no}; //} String msg = "「" + entry.getPath() + "」を削除しますか?"; //int select = JOptionPane.showOptionDialog(getContext().getFrame(), msg, "削除", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, no); int option = JOptionPane.showConfirmDialog(getContext().getFrame(), msg, "削除", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); if(option == JOptionPane.OK_OPTION) { delete(new File(entry.getPath())); if(tableModel != null && tableModel.getImageList() != null) { tableModel.getImageList().remove(entry); } ArrayList<ImageEntry> imageList = new ArrayList<ImageEntry>(); for(Object obj : tableModel.getImageList()) { imageList.add(((ImageEntry)obj).copy()); } tableModel.setImageList(imageList); //scan(nowLocation); } } }; ret.put("delete", delete); AbstractAction rename = new AbstractAction("名前の変更") { @Override public void actionPerformed(ActionEvent ae) { if(isScanning(getContext().getFrame(), "名前の変更はできません。")) return; int row = table.getSelectedRow(); int col = table.getSelectedColumn(); if(row < 0 || col < 0) return; ImageEntry entry = getEntryAt(row, col); if(entry == null) return; String newName = JOptionPane.showInputDialog(getContext().getFrame(), "名前を入力してください。", entry.getFileName()); ImageEntry newEntry = rename(newName, entry); if(newEntry != null) { ArrayList<ImageEntry> imageList = new ArrayList<ImageEntry>(); for(Object obj : tableModel.getImageList()) { if(((ImageEntry)obj).getFileName().equals(entry.getFileName())) { imageList.add(newEntry); }else{ imageList.add(((ImageEntry)obj).copy()); } } tableModel.setImageList(imageList); } } }; ret.put("rename", rename); AbstractAction newdir = new AbstractAction("新規") { @Override public void actionPerformed(ActionEvent ae) { if(isScanning(getContext().getFrame(), "フォルダを作成できません。")) return; //s.oh^ 2014/07/29 PDF・画像タブの改善 String name = JOptionPane.showInputDialog(getContext().getFrame(), "フォルダ名を入力してください。", checkDirName(nowLocation, "新規フォルダ")); //s.oh$ newdir(name); } }; ret.put("newdir", newdir); //s.oh$ //s.oh^ 2014/05/30 PDF・画像タブの改善 AbstractAction backdir = new AbstractAction("戻る") { @Override public void actionPerformed(ActionEvent ae) { backdir(); } }; ret.put("backdir", backdir); //s.oh$ return ret; } //s.oh^ 2014/05/07 PDF・画像タブの改善 private void delete(File file) { if(!file.exists()) { return; } if(file.isFile()) { file.delete(); }else if(file.isDirectory()) { File[] files = file.listFiles(); for(int i = 0; i < files.length; i++) { delete(files[i]); } file.delete(); } } private ImageEntry rename(String name, ImageEntry entry) { if(name != null && name.length() >= 0 && entry != null) { File newFile = new File(nowLocation, name); if(newFile.exists()) { String name2 = JOptionPane.showInputDialog(getContext().getFrame(), "同じ名前が既に存在します。別の名前を入力してください。", name); return rename(name2, entry); }else if(name.startsWith("__")) { String name2 = JOptionPane.showInputDialog(getContext().getFrame(), "__から始まる名前を使用できません。別の名前を入力してください。", name); return rename(name2, entry); }else{ ImageEntry newEntry = entry.copy(); try { entry.setUrl(newFile.toURI().toURL().toString()); } catch (MalformedURLException ex) { } newEntry.setFileName(name); newEntry.setPath(newFile.getPath()); File oldFile = new File(nowLocation, entry.getFileName()); oldFile.renameTo(newFile); return newEntry; } } return null; } private void newdir(String name) { if(name != null && name.length() >= 0) { File dir = new File(nowLocation); if(!dir.exists()) { dir.mkdirs(); }else if((dir.exists()) && (!dir.isDirectory())) { return; } File[] files = dir.listFiles(); if(files == null) return; for(File file : files) { if(file.getName().equals(name)) { String name2 = JOptionPane.showInputDialog(getContext().getFrame(), "同じ名前が既に存在します。別の名前を入力してください。", name); newdir(name2); return; } } name = nowLocation + File.separator + name; File folder = new File(name); folder.mkdir(); ImageEntry entry = new ImageEntry(); try { entry.setUrl(folder.toURI().toURL().toString()); } catch (MalformedURLException ex) { } entry.setPath(folder.getPath()); entry.setFileName(folder.getName()); entry.setLastModified(folder.lastModified()); entry.setImageIcon(ClientContext.getImageIconArias("icon_foldr")); entry.setDirectrory(true); ArrayList<ImageEntry> imageList = new ArrayList<ImageEntry>(); imageList.add(entry); if(tableModel.getImageList() != null) { for(Object obj : tableModel.getImageList()) { imageList.add(((ImageEntry)obj).copy()); } } tableModel.setImageList(imageList); //scan(nowLocation); } } //s.oh$ private void backdir() { String path = getImageBase() + File.separator + getContext().getPatient().getPatientId(); if(path.equals(nowLocation)) return; File dir = new File(nowLocation); nowLocation = dir.getParent(); scan(nowLocation); view.getDirLbl().setText(createLocationText(nowLocation)); } @Override protected void initComponents() { ResourceBundle resource = ClientContext.getMyBundle(FCRBrowser.class); final ActionMap map = getActionMap(resource); // TableModel int columnCount = columnCount(); tableModel = new ImageTableModel(null, columnCount); view = new FCRBrowserView(); table = view.getTable(); table.setModel(tableModel); table.putClientProperty("karteCompositor", this); table.setFillsViewportHeight(true); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); table.setCellSelectionEnabled(true); table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); table.setDragEnabled(true); table.setTransferHandler(new ImageTableTransferHandler(this)); TableColumn column; for (int i = 0; i < columnCount; i++) { column = view.getTable().getColumnModel().getColumn(i); column.setPreferredWidth(cellWidth); } table.setRowHeight(cellHeight); // Renderer imageRenderer = new ImageTableRenderer(this); imageRenderer.setImageSize(MAX_IMAGE_SIZE); table.setDefaultRenderer(java.lang.Object.class, imageRenderer); table.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (e.getClickCount()==1) { int row = table.getSelectedRow(); int col = table.getSelectedColumn(); ImageEntry entry = getEntryAt(row, col); Action copy = getContext().getChartMediator().getAction(GUIConst.ACTION_COPY); copy.setEnabled(entry!=null && (!entry.isDirectrory())); } else if(e.getClickCount()==2) { int row = table.getSelectedRow(); int col = table.getSelectedColumn(); ImageEntry entry = getEntryAt(row, col); if (entry!=null && (!entry.isDirectrory())) { //s.oh^ FCR連携 //openImage(entry); if(entry.getFileName().toUpperCase().endsWith(".JPG")) { linkThumbnail(entry); }else{ openImage(entry); } //s.oh$ } else if (entry!=null && entry.isDirectrory()) { scan(entry.getPath()); nowLocation = entry.getPath(); view.getDirLbl().setText(createLocationText(nowLocation)); } } } @Override public void mousePressed(MouseEvent me) { mabeShowPopup(me); } @Override public void mouseReleased(MouseEvent me) { mabeShowPopup(me); } private void mabeShowPopup(MouseEvent e) { if (!e.isPopupTrigger()) { return; } int row = table.rowAtPoint(e.getPoint()); int col = table.columnAtPoint(e.getPoint()); Object entry = tableModel.getValueAt(row, col); if (entry==null) { return; } JPopupMenu contextMenu = new JPopupMenu(); JMenuItem micp = new JMenuItem("コピー"); Action copy = getContext().getChartMediator().getAction(GUIConst.ACTION_COPY); micp.setAction(copy); contextMenu.add(micp); //s.oh^ 2014/05/07 PDF・画像タブの改善 JMenuItem midel = new JMenuItem("削除"); midel.setAction(map.get("delete")); contextMenu.add(midel); JMenuItem mirename = new JMenuItem("名前の変更"); mirename.setAction(map.get("rename")); contextMenu.add(mirename); //s.oh$ contextMenu.show(e.getComponent(), e.getX(), e.getY()); } }); view.getSettingBtn().setAction(map.get("doSetting")); view.getSettingBtn().setToolTipText("画像ディレクトリ等の設定を行います。"); view.getRefreshBtn().setAction(map.get("refresh")); view.getRefreshBtn().setToolTipText("表示を更新します。"); boolean canRefresh = true; canRefresh = canRefresh && (valueIsNotNullNorEmpty(properties.getProperty(PROP_BASE_DIR))); view.getRefreshBtn().setEnabled(canRefresh); // FCR Listボタン view.getFcrListBtn().setAction(map.get("linkList")); // FCR Imageボタン view.getFcrImageBtn().setAction(map.get("linkImage")); // FCR Todayボタン view.getFcrTodayBtn().setAction(map.get("linkToday")); // enabled boolean canLaunch = valueIsNotNullNorEmpty(savePath); view.getFcrListBtn().setEnabled(canLaunch); view.getFcrImageBtn().setEnabled(canLaunch); //s.oh^ 2014/05/07 PDF・画像タブの改善 view.getNewDirBtn().setAction(map.get("newdir")); //s.oh$ //s.oh^ 2014/05/30 PDF・画像タブの改善 view.getBackDirBtn().setAction(map.get("backdir")); //s.oh$ //minagawa^ Icon Server view.getDirLbl().setIcon(ClientContext.getImageIconArias("icon_info_small")); //minagawa$ view.getDirLbl().setToolTipText("画像・PDFディレクトリの場所を表示してます。"); setUI(view); } /** * ゼロサプレス * @param data * @return */ private String zeroSuppress(String data) { String ret = null; Pattern ptn = java.util.regex.Pattern.compile("^0+([0-9]+.*)"); Matcher m = ptn.matcher(data); if(m.matches()) { ret = m.group(1); }else{ ret = data; } return ret; } }