/******************************************************************************* * Copyright (c) 2016 Weasis Team and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Nicolas Roduit - initial API and implementation *******************************************************************************/ package org.weasis.dicom.viewer2d; import java.awt.Component; import java.awt.event.KeyEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.swing.Action; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JSeparator; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import org.dcm4che3.data.Attributes; import org.dcm4che3.data.Tag; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; import org.osgi.service.prefs.Preferences; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.weasis.core.api.explorer.DataExplorerView; import org.weasis.core.api.explorer.ObservableEvent; import org.weasis.core.api.gui.Insertable.Type; import org.weasis.core.api.gui.InsertableUtil; import org.weasis.core.api.gui.util.ActionState; import org.weasis.core.api.gui.util.ActionW; import org.weasis.core.api.gui.util.AppProperties; import org.weasis.core.api.gui.util.ComboItemListener; import org.weasis.core.api.gui.util.Filter; import org.weasis.core.api.gui.util.JMVUtils; import org.weasis.core.api.gui.util.SliderChangeListener; import org.weasis.core.api.gui.util.SliderCineListener; import org.weasis.core.api.gui.util.ToggleButtonListener; import org.weasis.core.api.image.GridBagLayoutModel; import org.weasis.core.api.media.data.MediaSeries; import org.weasis.core.api.media.data.MediaSeriesGroup; import org.weasis.core.api.media.data.Series; import org.weasis.core.api.media.data.SeriesEvent; import org.weasis.core.api.service.BundlePreferences; import org.weasis.core.api.service.BundleTools; import org.weasis.core.ui.docking.DockableTool; import org.weasis.core.ui.docking.PluginTool; import org.weasis.core.ui.docking.UIManager; import org.weasis.core.ui.editor.SeriesViewerListener; import org.weasis.core.ui.editor.image.DefaultView2d; import org.weasis.core.ui.editor.image.ImageViewerPlugin; import org.weasis.core.ui.editor.image.MeasureToolBar; import org.weasis.core.ui.editor.image.RotationToolBar; import org.weasis.core.ui.editor.image.SynchData; import org.weasis.core.ui.editor.image.SynchView; import org.weasis.core.ui.editor.image.ViewCanvas; import org.weasis.core.ui.editor.image.ViewerToolBar; import org.weasis.core.ui.editor.image.ZoomToolBar; import org.weasis.core.ui.editor.image.dockable.MeasureTool; import org.weasis.core.ui.editor.image.dockable.MiniTool; import org.weasis.core.ui.util.ColorLayerUI; import org.weasis.core.ui.util.DefaultAction; import org.weasis.core.ui.util.PrintDialog; import org.weasis.core.ui.util.Toolbar; import org.weasis.dicom.codec.DicomImageElement; import org.weasis.dicom.codec.DicomSeries; import org.weasis.dicom.codec.DicomSpecialElement; import org.weasis.dicom.codec.KOSpecialElement; import org.weasis.dicom.codec.PRSpecialElement; import org.weasis.dicom.codec.PresentationStateReader; import org.weasis.dicom.codec.TagD; import org.weasis.dicom.codec.TagD.Level; import org.weasis.dicom.explorer.DicomExplorer; import org.weasis.dicom.explorer.DicomModel; import org.weasis.dicom.explorer.print.DicomPrintDialog; import org.weasis.dicom.viewer2d.dockable.DisplayTool; import org.weasis.dicom.viewer2d.dockable.ImageTool; @SuppressWarnings("serial") public class View2dContainer extends ImageViewerPlugin<DicomImageElement> implements PropertyChangeListener { private static final Logger LOGGER = LoggerFactory.getLogger(View2dContainer.class); public static final List<SynchView> SYNCH_LIST = Collections.synchronizedList(new ArrayList<SynchView>()); static { SYNCH_LIST.add(SynchView.NONE); SYNCH_LIST.add(SynchView.DEFAULT_STACK); SYNCH_LIST.add(SynchView.DEFAULT_TILE); } public static final GridBagLayoutModel VIEWS_2x1_r1xc2_dump = new GridBagLayoutModel(View2dContainer.class.getResourceAsStream("/config/layoutModel.xml"), "layout_dump", //$NON-NLS-1$ //$NON-NLS-2$ Messages.getString("View2dContainer.layout_dump"), new ImageIcon( //$NON-NLS-1$ View2dContainer.class.getResource("/icon/22x22/layout1x2_c2.png"))); //$NON-NLS-1$ public static final List<GridBagLayoutModel> LAYOUT_LIST = Collections.synchronizedList(new ArrayList<GridBagLayoutModel>()); static { LAYOUT_LIST.add(VIEWS_1x1); LAYOUT_LIST.add(VIEWS_1x2); LAYOUT_LIST.add(VIEWS_2x1); LAYOUT_LIST.add(VIEWS_2x2_f2); LAYOUT_LIST.add(VIEWS_2_f1x2); LAYOUT_LIST.add(VIEWS_2x1_r1xc2_dump); LAYOUT_LIST.add(VIEWS_2x2); LAYOUT_LIST.add(VIEWS_3x2); LAYOUT_LIST.add(VIEWS_3x3); LAYOUT_LIST.add(VIEWS_4x3); LAYOUT_LIST.add(VIEWS_4x4); } // Static tools shared by all the View2dContainer instances, tools are registered when a container is selected // Do not initialize tools in a static block (order initialization issue with eventManager), use instead a lazy // initialization with a method. public static final List<Toolbar> TOOLBARS = Collections.synchronizedList(new ArrayList<Toolbar>()); public static final List<DockableTool> TOOLS = Collections.synchronizedList(new ArrayList<DockableTool>()); private static volatile boolean initComponents = false; public View2dContainer() { this(VIEWS_1x1, null, View2dFactory.NAME, View2dFactory.ICON, null); } public View2dContainer(GridBagLayoutModel layoutModel, String uid, String pluginName, Icon icon, String tooltips) { super(EventManager.getInstance(), layoutModel, uid, pluginName, icon, tooltips); setSynchView(SynchView.DEFAULT_STACK); if (!initComponents) { initComponents = true; // Add standard toolbars final BundleContext context = FrameworkUtil.getBundle(this.getClass()).getBundleContext(); EventManager evtMg = EventManager.getInstance(); String bundleName = context.getBundle().getSymbolicName(); String componentName = InsertableUtil.getCName(this.getClass()); String key = "enable"; //$NON-NLS-1$ if (InsertableUtil.getBooleanProperty(BundleTools.SYSTEM_PREFERENCES, bundleName, componentName, InsertableUtil.getCName(ViewerToolBar.class), key, true)) { TOOLBARS.add(new ViewerToolBar<>(evtMg, evtMg.getMouseActions().getActiveButtons(), BundleTools.SYSTEM_PREFERENCES, 10)); } if (InsertableUtil.getBooleanProperty(BundleTools.SYSTEM_PREFERENCES, bundleName, componentName, InsertableUtil.getCName(MeasureToolBar.class), key, true)) { TOOLBARS.add(new MeasureToolBar(evtMg, 11)); } if (InsertableUtil.getBooleanProperty(BundleTools.SYSTEM_PREFERENCES, bundleName, componentName, InsertableUtil.getCName(ZoomToolBar.class), key, true)) { TOOLBARS.add(new ZoomToolBar(evtMg, 20, true)); } if (InsertableUtil.getBooleanProperty(BundleTools.SYSTEM_PREFERENCES, bundleName, componentName, InsertableUtil.getCName(RotationToolBar.class), key, true)) { TOOLBARS.add(new RotationToolBar(evtMg, 30)); } if (InsertableUtil.getBooleanProperty(BundleTools.SYSTEM_PREFERENCES, bundleName, componentName, InsertableUtil.getCName(DcmHeaderToolBar.class), key, true)) { TOOLBARS.add(new DcmHeaderToolBar(evtMg, 35)); } if (InsertableUtil.getBooleanProperty(BundleTools.SYSTEM_PREFERENCES, bundleName, componentName, InsertableUtil.getCName(LutToolBar.class), key, true)) { TOOLBARS.add(new LutToolBar(evtMg, 40)); } if (InsertableUtil.getBooleanProperty(BundleTools.SYSTEM_PREFERENCES, bundleName, componentName, InsertableUtil.getCName(Basic3DToolBar.class), key, true)) { TOOLBARS.add(new Basic3DToolBar<DicomImageElement>(50)); } if (InsertableUtil.getBooleanProperty(BundleTools.SYSTEM_PREFERENCES, bundleName, componentName, InsertableUtil.getCName(CineToolBar.class), key, true)) { TOOLBARS.add(new CineToolBar<DicomImageElement>(80)); } if (InsertableUtil.getBooleanProperty(BundleTools.SYSTEM_PREFERENCES, bundleName, componentName, InsertableUtil.getCName(KeyObjectToolBar.class), key, true)) { TOOLBARS.add(new KeyObjectToolBar(90)); } PluginTool tool = null; if (InsertableUtil.getBooleanProperty(BundleTools.SYSTEM_PREFERENCES, bundleName, componentName, InsertableUtil.getCName(MiniTool.class), key, true)) { tool = new MiniTool(MiniTool.BUTTON_NAME) { @Override public SliderChangeListener[] getActions() { ArrayList<SliderChangeListener> listeners = new ArrayList<>(3); ActionState seqAction = eventManager.getAction(ActionW.SCROLL_SERIES); if (seqAction instanceof SliderChangeListener) { listeners.add((SliderChangeListener) seqAction); } ActionState zoomAction = eventManager.getAction(ActionW.ZOOM); if (zoomAction instanceof SliderChangeListener) { listeners.add((SliderChangeListener) zoomAction); } ActionState rotateAction = eventManager.getAction(ActionW.ROTATION); if (rotateAction instanceof SliderChangeListener) { listeners.add((SliderChangeListener) rotateAction); } return listeners.toArray(new SliderChangeListener[listeners.size()]); } }; TOOLS.add(tool); } if (InsertableUtil.getBooleanProperty(BundleTools.SYSTEM_PREFERENCES, bundleName, componentName, InsertableUtil.getCName(ImageTool.class), key, true)) { tool = new ImageTool(ImageTool.BUTTON_NAME); TOOLS.add(tool); } if (InsertableUtil.getBooleanProperty(BundleTools.SYSTEM_PREFERENCES, bundleName, componentName, InsertableUtil.getCName(DisplayTool.class), key, true)) { tool = new DisplayTool(DisplayTool.BUTTON_NAME); TOOLS.add(tool); eventManager.addSeriesViewerListener((SeriesViewerListener) tool); } if (InsertableUtil.getBooleanProperty(BundleTools.SYSTEM_PREFERENCES, bundleName, componentName, InsertableUtil.getCName(MeasureTool.class), key, true)) { tool = new MeasureTool(eventManager); TOOLS.add(tool); } InsertableUtil.sortInsertable(TOOLS); // Send event to synchronize the series selection. DataExplorerView dicomView = UIManager.getExplorerplugin(DicomExplorer.NAME); if (dicomView != null) { eventManager.addSeriesViewerListener((SeriesViewerListener) dicomView); } Preferences prefs = BundlePreferences.getDefaultPreferences(context); if (prefs != null) { InsertableUtil.applyPreferences(TOOLBARS, prefs, bundleName, componentName, Type.TOOLBAR); InsertableUtil.applyPreferences(TOOLS, prefs, bundleName, componentName, Type.TOOL); } } } @Override public void setSelectedImagePaneFromFocus(ViewCanvas<DicomImageElement> viewCanvas) { setSelectedImagePane(viewCanvas); if (viewCanvas != null && viewCanvas.getSeries() instanceof DicomSeries) { DicomSeries series = (DicomSeries) viewCanvas.getSeries(); DicomSeries.startPreloading(series, series.copyOfMedias( (Filter<DicomImageElement>) viewCanvas.getActionValue(ActionW.FILTERED_SERIES.cmd()), viewCanvas.getCurrentSortComparator()), viewCanvas.getFrameIndex()); } } @Override public JMenu fillSelectedPluginMenu(JMenu menuRoot) { if (menuRoot != null) { menuRoot.removeAll(); if (eventManager instanceof EventManager) { EventManager manager = (EventManager) eventManager; JMenu menu = new JMenu(Messages.getString("View2dContainer.3d")); //$NON-NLS-1$ ActionState scrollAction = EventManager.getInstance().getAction(ActionW.SCROLL_SERIES); menu.setEnabled( manager.getSelectedSeries() != null && (scrollAction != null && scrollAction.isActionEnabled())); if (menu.isEnabled()) { JMenuItem mpr = new JMenuItem(Messages.getString("View2dContainer.mpr")); //$NON-NLS-1$ mpr.addActionListener(Basic3DToolBar.getMprAction()); menu.add(mpr); JMenuItem mip = new JMenuItem(Messages.getString("View2dContainer.mip")); //$NON-NLS-1$ mip.addActionListener(Basic3DToolBar.getMipAction()); menu.add(mip); } menuRoot.add(menu); menuRoot.add(new JSeparator()); JMVUtils.addItemToMenu(menuRoot, manager.getPresetMenu(null)); JMVUtils.addItemToMenu(menuRoot, manager.getLutShapeMenu(null)); JMVUtils.addItemToMenu(menuRoot, manager.getLutMenu(null)); JMVUtils.addItemToMenu(menuRoot, manager.getLutInverseMenu(null)); JMVUtils.addItemToMenu(menuRoot, manager.getFilterMenu(null)); menuRoot.add(new JSeparator()); JMVUtils.addItemToMenu(menuRoot, manager.getZoomMenu(null)); JMVUtils.addItemToMenu(menuRoot, manager.getOrientationMenu(null)); JMVUtils.addItemToMenu(menuRoot, manager.getSortStackMenu(null)); menuRoot.add(new JSeparator()); menuRoot.add(manager.getResetMenu(null)); } } return menuRoot; } @Override public List<DockableTool> getToolPanel() { return TOOLS; } @Override public void setSelected(boolean selected) { if (selected) { eventManager.setSelectedView2dContainer(this); // Send event to select the related patient in Dicom Explorer. DataExplorerView dicomView = UIManager.getExplorerplugin(DicomExplorer.NAME); if (dicomView != null && dicomView.getDataExplorerModel() instanceof DicomModel) { dicomView.getDataExplorerModel().firePropertyChange( new ObservableEvent(ObservableEvent.BasicAction.SELECT, this, null, getGroupID())); } } else { eventManager.setSelectedView2dContainer(null); } } @Override public void close() { View2dFactory.closeSeriesViewer(this); super.close(); } private boolean closeIfNoContent() { if (getOpenSeries().isEmpty()) { close(); handleFocusAfterClosing(); return true; } return false; } @Override public void propertyChange(PropertyChangeEvent evt) { if (evt instanceof ObservableEvent) { ObservableEvent event = (ObservableEvent) evt; ObservableEvent.BasicAction action = event.getActionCommand(); Object newVal = event.getNewValue(); if (newVal instanceof SeriesEvent) { SeriesEvent event2 = (SeriesEvent) newVal; SeriesEvent.Action action2 = event2.getActionCommand(); Object source = event2.getSource(); Object param = event2.getParam(); if (ObservableEvent.BasicAction.ADD.equals(action)) { if (SeriesEvent.Action.ADD_IMAGE.equals(action2)) { if (source instanceof DicomSeries) { DicomSeries series = (DicomSeries) source; ViewCanvas<DicomImageElement> view2DPane = eventManager.getSelectedViewPane(); if (view2DPane != null) { DicomImageElement img = view2DPane.getImage(); if (img != null && view2DPane.getSeries() == series) { ActionState seqAction = eventManager.getAction(ActionW.SCROLL_SERIES); if (seqAction instanceof SliderCineListener) { SliderCineListener sliceAction = (SliderCineListener) seqAction; if (param instanceof DicomImageElement) { Filter<DicomImageElement> filter = (Filter<DicomImageElement>) view2DPane .getActionValue(ActionW.FILTERED_SERIES.cmd()); int imgIndex = series.getImageIndex(img, filter, view2DPane.getCurrentSortComparator()); if (imgIndex < 0) { imgIndex = 0; // add again the series for registering listeners // (require at least one image) view2DPane.setSeries(series, null); } if (imgIndex >= 0) { sliceAction.setSliderMinMaxValue(1, series.size(filter), imgIndex + 1); } } } } } } } else if (SeriesEvent.Action.UPDATE_IMAGE.equals(action2)) { if (source instanceof DicomImageElement) { DicomImageElement dcm = (DicomImageElement) source; for (ViewCanvas<DicomImageElement> v : view2ds) { if (dcm == v.getImage()) { // Force to repaint the same image if (v.getImageLayer().getDisplayImage() == null) { v.setActionsInView(ActionW.PROGRESSION.cmd(), param); // Set image to null for getting correct W/L values v.getImageLayer().setImage(null, null); v.setSeries(v.getSeries()); } else { v.propertyChange( new PropertyChangeEvent(dcm, ActionW.PROGRESSION.cmd(), null, param)); } } } } } else if (SeriesEvent.Action.PRELOADING.equals(action2)) { if (source instanceof DicomSeries) { DicomSeries dcm = (DicomSeries) source; for (ViewCanvas<DicomImageElement> v : view2ds) { if (dcm == v.getSeries()) { v.getJComponent().repaint(v.getInfoLayer().getPreloadingProgressBound()); } } } } } else if (ObservableEvent.BasicAction.UPDATE.equals(action)) { if (SeriesEvent.Action.UPDATE.equals(action2)) { if (source instanceof KOSpecialElement) { setKOSpecialElement((KOSpecialElement) source, null, false, param.equals("updateAll")); //$NON-NLS-1$ } } } } else if (ObservableEvent.BasicAction.REMOVE.equals(action)) { if (newVal instanceof MediaSeriesGroup) { MediaSeriesGroup group = (MediaSeriesGroup) newVal; // Patient Group if (TagD.getUID(Level.PATIENT).equals(group.getTagID())) { if (group.equals(getGroupID())) { // Close the content of the plug-in close(); handleFocusAfterClosing(); } } // Study Group else if (TagD.getUID(Level.STUDY).equals(group.getTagID())) { if (event.getSource() instanceof DicomModel) { DicomModel model = (DicomModel) event.getSource(); for (ViewCanvas<DicomImageElement> v : view2ds) { if (group.equals(model.getParent(v.getSeries(), DicomModel.study))) { v.setSeries(null); if (closeIfNoContent()) { return; } } } } } // Series Group else if (TagD.getUID(Level.SERIES).equals(group.getTagID())) { for (ViewCanvas<DicomImageElement> v : view2ds) { if (newVal.equals(v.getSeries())) { v.setSeries(null); if (closeIfNoContent()) { return; } } } } } } else if (ObservableEvent.BasicAction.REPLACE.equals(action)) { if (newVal instanceof Series) { Series series = (Series) newVal; for (ViewCanvas<DicomImageElement> v : view2ds) { MediaSeries<DicomImageElement> s = v.getSeries(); if (series.equals(s)) { /* * Set to null to be sure that all parameters from the view are apply again to the Series * (for instance it is the same series with more images) */ v.setSeries(null); v.setSeries(series, null); } } } } else if (ObservableEvent.BasicAction.UPDATE.equals(action)) { DicomSpecialElement specialElement = null; // When a dicom KO element is loaded an ObservableEvent.BasicAction.Update is sent // Either it's a new DicomObject or it's content is updated // TODO - a choice should be done about sending either a DicomSpecialElement or a Series object as the // new value for this event. A DicomSpecialElement seems to be a better choice since a Series of // DicomSpecialElement do not necessarily concerned the series in the Viewer2dContainer if (newVal instanceof Series) { specialElement = DicomModel.getFirstSpecialElement((Series) newVal, DicomSpecialElement.class); } else if (newVal instanceof DicomSpecialElement) { specialElement = (DicomSpecialElement) newVal; } if (specialElement instanceof PRSpecialElement) { for (ViewCanvas<DicomImageElement> view : view2ds) { if (view instanceof View2d) { DicomImageElement img = view.getImage(); if (img != null) { if (PresentationStateReader.isModuleAppicable( TagD.getTagValue(specialElement, Tag.ReferencedSeriesSequence, Attributes[].class), img)) { ((View2d) view).updatePR(); } } } } } /* * Update if necessary all the views with the KOSpecialElement */ else if (specialElement instanceof KOSpecialElement) { setKOSpecialElement((KOSpecialElement) specialElement, null, false, false); } } else if (ObservableEvent.BasicAction.SELECT.equals(action)) { if (newVal instanceof KOSpecialElement) { // Match using UID of the plugin window and the source event if (this.getDockableUID().equals(evt.getSource())) { setKOSpecialElement((KOSpecialElement) newVal, true, true, false); } } } } } private void setKOSpecialElement(KOSpecialElement updatedKOSelection, Boolean enableFilter, boolean forceUpdate, boolean updateAll) { ViewCanvas<DicomImageElement> selectedView = getSelectedImagePane(); if (updatedKOSelection != null && selectedView instanceof View2d) { if (SynchData.Mode.TILE.equals(this.getSynchView().getSynchData().getMode())) { ActionState koSelection = selectedView.getEventManager().getAction(ActionW.KO_SELECTION); if (koSelection instanceof ComboItemListener) { ((ComboItemListener) koSelection).setSelectedItem(updatedKOSelection); } if (forceUpdate || enableFilter != null) { ActionState koFilterAction = selectedView.getEventManager().getAction(ActionW.KO_FILTER); if (koFilterAction instanceof ToggleButtonListener) { if (enableFilter == null) { enableFilter = JMVUtils.getNULLtoFalse(selectedView.getActionValue(ActionW.KO_FILTER.cmd())); } ((ToggleButtonListener) koFilterAction).setSelected(enableFilter); } } if (updateAll) { List<ViewCanvas<DicomImageElement>> viewList = getImagePanels(true); for (ViewCanvas<DicomImageElement> view : viewList) { ((View2d) view).updateKOButtonVisibleState(); } } else { ((View2d) selectedView).updateKOButtonVisibleState(); } } else { /* * Set the selected view at the end of the list to trigger the synchronization of the SCROLL_SERIES * action at the end of the process */ List<ViewCanvas<DicomImageElement>> viewList = getImagePanels(true); for (ViewCanvas<DicomImageElement> view : viewList) { if ((view.getSeries() instanceof DicomSeries) == false || (view instanceof View2d) == false) { continue; } if (forceUpdate || updatedKOSelection == view.getActionValue(ActionW.KO_SELECTION.cmd())) { KOManager.updateKOFilter(view, forceUpdate ? updatedKOSelection : null, enableFilter, -1); } DicomSeries dicomSeries = (DicomSeries) view.getSeries(); String seriesInstanceUID = TagD.getTagValue(dicomSeries, Tag.SeriesInstanceUID, String.class); if (updatedKOSelection.containsSeriesInstanceUIDReference(seriesInstanceUID) == false) { continue; } ((View2d) view).updateKOButtonVisibleState(); } } EventManager.getInstance().updateKeyObjectComponentsListener(selectedView); } } @Override public int getViewTypeNumber(GridBagLayoutModel layout, Class<?> defaultClass) { return View2dFactory.getViewTypeNumber(layout, defaultClass); } @Override public boolean isViewType(Class<?> defaultClass, String type) { if (defaultClass != null) { try { Class<?> clazz = Class.forName(type); return defaultClass.isAssignableFrom(clazz); } catch (Exception e) { LOGGER.error("Checking view", e); //$NON-NLS-1$ } } return false; } @Override public DefaultView2d<DicomImageElement> createDefaultView(String classType) { return new View2d(eventManager); } @Override public JComponent createUIcomponent(String clazz) { if (isViewType(DefaultView2d.class, clazz)) { return createDefaultView(clazz); } try { // FIXME use classloader.loadClass or injection Class<?> cl = Class.forName(clazz); JComponent component = (JComponent) cl.newInstance(); if (component instanceof SeriesViewerListener) { eventManager.addSeriesViewerListener((SeriesViewerListener) component); } return component; } catch (Exception e) { LOGGER.error("Cannot create {}", clazz, e); //$NON-NLS-1$ } return null; } @Override public synchronized List<Toolbar> getToolBar() { return TOOLBARS; } @Override public List<Action> getExportActions() { List<Action> actions = selectedImagePane == null ? null : selectedImagePane.getExportToClipboardAction(); if (AppProperties.OPERATING_SYSTEM.startsWith("mac")) { //$NON-NLS-1$ if (actions == null) { actions = new ArrayList<>(); } boolean expOsirix = BundleTools.SYSTEM_PREFERENCES.getBooleanProperty("export.menu.osirix", true); //$NON-NLS-1$ if (expOsirix) { DefaultAction action = new DefaultAction(String.format(Messages.getString("View2dContainer.expOsirixMes"), "Osirix"), //$NON-NLS-1$ //$NON-NLS-2$ new ImageIcon(View2dContainer.class.getResource("/icon/16x16/osirix.png")), //$NON-NLS-1$ event -> exportTosirix(this, "Osirix", "/usr/bin/open -b com.rossetantoine.osirix")); //$NON-NLS-1$ //$NON-NLS-2$ actions.add(action); } boolean expHoros = BundleTools.SYSTEM_PREFERENCES.getBooleanProperty("export.menu.horos", true); //$NON-NLS-1$ if (expHoros) { DefaultAction action = new DefaultAction(String.format(Messages.getString("View2dContainer.expOsirixMes"), "Horos"), //$NON-NLS-1$ //$NON-NLS-2$ new ImageIcon(View2dContainer.class.getResource("/icon/16x16/horos.png")), //$NON-NLS-1$ event -> exportTosirix(this, "Horos", "/usr/bin/open -b com.horosproject.horos")); // $NON-NLS-1$ //$NON-NLS-1$ //$NON-NLS-2$ actions.add(action); } } return actions; } private static void exportTosirix(Component parent, String AppName, String cmd) { String baseDir = System.getProperty("weasis.portable.dir"); //$NON-NLS-1$ if (baseDir != null) { String prop = System.getProperty("weasis.portable.dicom.directory"); //$NON-NLS-1$ if (prop != null) { String[] dirs = prop.split(","); //$NON-NLS-1$ File[] files = new File[dirs.length]; for (int i = 0; i < files.length; i++) { File file = new File(baseDir, dirs[i].trim()); if (file.canRead()) { cmd += " " + file.getAbsolutePath(); //$NON-NLS-1$ } } } } else { File file = new File(AppProperties.APP_TEMP_DIR, "dicom"); //$NON-NLS-1$ if (file.canRead()) { cmd += " " + file.getAbsolutePath(); //$NON-NLS-1$ } } LOGGER.info("Execute cmd:" + cmd); //$NON-NLS-1$ try { Process p = Runtime.getRuntime().exec(cmd); BufferedReader buffer = new BufferedReader(new InputStreamReader(p.getInputStream())); String data; while ((data = buffer.readLine()) != null) { System.out.println(data); } int val = 0; if (p.waitFor() != 0) { val = p.exitValue(); } if (val != 0) { JOptionPane.showMessageDialog(parent, String.format(Messages.getString("View2dContainer.expOsirixTitle"), //$NON-NLS-1$ AppName), Messages.getString("View2dContainer.expOsirixMes"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$ } } catch (IOException e1) { LOGGER.error("Running cmd", e1); //$NON-NLS-1$ } catch (InterruptedException e2) { LOGGER.error("Cannot get the exit status of the open Osirix command", e2); //$NON-NLS-1$ } } @Override public List<Action> getPrintActions() { ArrayList<Action> actions = new ArrayList<>(2); final String title = Messages.getString("View2dContainer.print_layout"); //$NON-NLS-1$ DefaultAction printStd = new DefaultAction(title, new ImageIcon(ImageViewerPlugin.class.getResource("/icon/16x16/printer.png")), event -> { //$NON-NLS-1$ ColorLayerUI layer = ColorLayerUI.createTransparentLayerUI(View2dContainer.this); PrintDialog<DicomImageElement> dialog = new PrintDialog<>(SwingUtilities.getWindowAncestor(View2dContainer.this), title, eventManager); ColorLayerUI.showCenterScreen(dialog, layer); }); printStd.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_P, 0)); actions.add(printStd); final String title2 = Messages.getString("View2dContainer.dcm_print"); //$NON-NLS-1$ DefaultAction printStd2 = new DefaultAction(title2, null, event -> { ColorLayerUI layer = ColorLayerUI.createTransparentLayerUI(View2dContainer.this); DicomPrintDialog<DicomImageElement> dialog = new DicomPrintDialog<>(SwingUtilities.getWindowAncestor(View2dContainer.this), title2, eventManager); ColorLayerUI.showCenterScreen(dialog, layer); }); actions.add(printStd2); return actions; } @Override public List<SynchView> getSynchList() { return SYNCH_LIST; } @Override public List<GridBagLayoutModel> getLayoutList() { return LAYOUT_LIST; } }