package org.weasis.dicom.explorer;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
import javax.swing.SwingUtilities;
import org.dcm4che3.data.Tag;
import org.weasis.core.api.explorer.DataExplorerView;
import org.weasis.core.api.media.data.ImageElement;
import org.weasis.core.api.media.data.MediaElement;
import org.weasis.core.api.media.data.MediaSeries;
import org.weasis.core.api.media.data.MediaSeries.MEDIA_POSITION;
import org.weasis.core.api.media.data.MediaSeriesGroup;
import org.weasis.core.api.media.data.Series;
import org.weasis.core.api.media.data.SeriesThumbnail;
import org.weasis.core.api.media.data.TagW;
import org.weasis.core.ui.docking.UIManager;
import org.weasis.core.ui.editor.DefaultMimeAppFactory;
import org.weasis.core.ui.editor.SeriesViewerEvent;
import org.weasis.core.ui.editor.SeriesViewerEvent.EVENT;
import org.weasis.core.ui.editor.SeriesViewerFactory;
import org.weasis.core.ui.editor.ViewerPluginBuilder;
import org.weasis.dicom.codec.DicomSeries;
import org.weasis.dicom.codec.TagD;
import org.weasis.dicom.codec.geometry.ImageOrientation;
import org.weasis.dicom.explorer.wado.LoadSeries;
public class ThumbnailMouseAndKeyAdapter extends MouseAdapter implements KeyListener {
private final Series series;
private final DicomModel dicomModel;
private final LoadSeries loadSeries;
public ThumbnailMouseAndKeyAdapter(Series series, DicomModel dicomModel, LoadSeries loadSeries) {
this.series = Objects.requireNonNull(series);
this.dicomModel = Objects.requireNonNull(dicomModel);
this.loadSeries = loadSeries;
}
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
final SeriesSelectionModel selList = getSeriesSelectionModel();
selList.setOpenningSeries(true);
Map<String, Object> props = Collections.synchronizedMap(new HashMap<String, Object>());
props.put(ViewerPluginBuilder.CMP_ENTRY_BUILD_NEW_VIEWER, true);
props.put(ViewerPluginBuilder.BEST_DEF_LAYOUT, false);
props.put(ViewerPluginBuilder.OPEN_IN_SELECTION, true);
String mime = series.getMimeType();
SeriesViewerFactory plugin = UIManager.getViewerFactory(mime);
if (plugin == null) {
plugin = DefaultMimeAppFactory.getInstance();
}
ArrayList<MediaSeries<MediaElement>> list = new ArrayList<>(1);
list.add(series);
ViewerPluginBuilder builder = new ViewerPluginBuilder(plugin, list, dicomModel, props);
ViewerPluginBuilder.openSequenceInPlugin(builder);
selList.setOpenningSeries(false);
}
}
@Override
public void mousePressed(MouseEvent mouseevent) {
final Component c = mouseevent.getComponent();
if (!c.isFocusOwner()) {
c.requestFocusInWindow();
}
final SeriesSelectionModel selList = getSeriesSelectionModel();
if (SwingUtilities.isRightMouseButton(mouseevent)) {
JPopupMenu popupMenu = new JPopupMenu();
List<SeriesViewerFactory> plugins = UIManager.getViewerFactoryList(new String[] { series.getMimeType() });
if (!selList.contains(series)) {
selList.setSelectionInterval(series, series);
}
// Is the selection has multiple mime types
boolean multipleMimes = false;
String mime = series.getMimeType();
for (Series s : selList) {
if (!mime.equals(s.getMimeType())) {
multipleMimes = true;
break;
}
}
final List<MediaSeries<? extends MediaElement>> seriesList;
if (multipleMimes) {
// Filter the list to have only one mime type
seriesList = new ArrayList<>();
for (Series s : selList) {
if (mime.equals(s.getMimeType())) {
seriesList.add(s);
}
}
} else {
seriesList = new ArrayList<>(selList);
}
for (final SeriesViewerFactory viewerFactory : plugins) {
JMenu menuFactory = new JMenu(viewerFactory.getUIName());
menuFactory.setIcon(viewerFactory.getIcon());
JMenuItem item4 = new JMenuItem(Messages.getString("DicomExplorer.open")); //$NON-NLS-1$
item4.addActionListener(e -> {
selList.setOpenningSeries(true);
ViewerPluginBuilder.openSequenceInPlugin(viewerFactory, seriesList, dicomModel, true, true);
selList.setOpenningSeries(false);
});
menuFactory.add(item4);
// Exclude system factory
if (viewerFactory.canExternalizeSeries()) {
item4 = new JMenuItem(Messages.getString("DicomExplorer.open_win")); //$NON-NLS-1$
item4.addActionListener(e -> {
selList.setOpenningSeries(true);
ViewerPluginBuilder.openSequenceInPlugin(viewerFactory, seriesList, dicomModel, false, true);
selList.setOpenningSeries(false);
});
menuFactory.add(item4);
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
final GraphicsDevice[] gd = ge.getScreenDevices();
if (gd.length > 0) {
JMenu subMenu = new JMenu(Messages.getString("DicomExplorer.open_screen")); //$NON-NLS-1$
for (int i = 0; i < gd.length; i++) {
GraphicsConfiguration config = gd[i].getDefaultConfiguration();
final Rectangle b = config.getBounds();
item4 = new JMenuItem(config.getDevice().toString());
item4.addActionListener(e -> {
selList.setOpenningSeries(true);
ViewerPluginBuilder.openSequenceInPlugin(viewerFactory, seriesList, dicomModel, false,
true, b);
selList.setOpenningSeries(false);
});
subMenu.add(item4);
}
menuFactory.add(subMenu);
}
}
if (viewerFactory.canAddSeries()) {
item4 = new JMenuItem(Messages.getString("DicomExplorer.add")); //$NON-NLS-1$
item4.addActionListener(e -> {
selList.setOpenningSeries(true);
ViewerPluginBuilder.openSequenceInPlugin(viewerFactory, seriesList, dicomModel, true, false);
selList.setOpenningSeries(false);
});
menuFactory.add(item4);
}
popupMenu.add(menuFactory);
if (viewerFactory instanceof MimeSystemAppFactory) {
final JMenuItem item5 = new JMenuItem(Messages.getString("DicomExplorer.open_info"), null); //$NON-NLS-1$
item5.addActionListener(e -> {
JFrame frame = new JFrame(Messages.getString("DicomExplorer.dcmInfo")); //$NON-NLS-1$
frame.setSize(500, 630);
DicomFieldsView view = new DicomFieldsView();
view.changingViewContentEvent(new SeriesViewerEvent(viewerFactory.createSeriesViewer(null),
series, series.getMedia(MEDIA_POSITION.FIRST, null, null), EVENT.SELECT));
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(view);
frame.getContentPane().add(panel);
frame.setVisible(true);
});
popupMenu.add(item5);
}
}
if (series instanceof DicomSeries) {
if (selList.size() == 1) {
popupMenu.add(new JSeparator());
JMenuItem item2 = new JMenuItem(Messages.getString("DicomExplorer.sel_rel_series")); //$NON-NLS-1$
item2.addActionListener(e -> {
String fruid = TagD.getTagValue(series, Tag.FrameOfReferenceUID, String.class);
if (fruid != null) {
selList.clear();
MediaSeriesGroup studyGroup = dicomModel.getParent(series, DicomModel.study);
synchronized (dicomModel) {
for (MediaSeriesGroup seq : dicomModel.getChildren(studyGroup)) {
if (seq instanceof Series) {
Series s = (Series) seq;
if (fruid.equals(TagD.getTagValue(s, Tag.FrameOfReferenceUID))) {
selList.add(s);
}
}
}
}
selList.addSelectionInterval(series, series);
}
});
popupMenu.add(item2);
item2 = new JMenuItem(Messages.getString("DicomExplorer.sel_rel_series_axis")); //$NON-NLS-1$
item2.addActionListener(e -> {
String fruid = TagD.getTagValue(series, Tag.FrameOfReferenceUID, String.class);
if (fruid != null) {
selList.clear();
MediaSeriesGroup studyGroup = dicomModel.getParent(series, DicomModel.study);
synchronized (dicomModel) {
for (MediaSeriesGroup seq : dicomModel.getChildren(studyGroup)) {
if (seq instanceof Series) {
Series s = (Series) seq;
if (fruid.equals(TagD.getTagValue(s, Tag.FrameOfReferenceUID))) {
if (ImageOrientation.hasSameOrientation(series, s)) {
selList.add(s);
}
}
}
}
}
selList.addSelectionInterval(series, series);
}
});
popupMenu.add(item2);
}
if (selList.size() == 1 && loadSeries != null) {
if (loadSeries.isStopped()) {
popupMenu.add(new JSeparator());
JMenuItem item3 = new JMenuItem(Messages.getString("LoadSeries.resume")); //$NON-NLS-1$
item3.addActionListener(e -> loadSeries.resume());
popupMenu.add(item3);
} else if (!loadSeries.isDone()) {
popupMenu.add(new JSeparator());
JMenuItem item3 = new JMenuItem(Messages.getString("LoadSeries.stop")); //$NON-NLS-1$
item3.addActionListener(e -> loadSeries.stop());
popupMenu.add(item3);
}
}
Object splitNb = series.getTagValue(TagW.SplitSeriesNumber);
if (splitNb != null && seriesList.size() > 1) {
String uid = TagD.getTagValue(series, Tag.SeriesInstanceUID, String.class);
boolean sameOrigin = true;
if (uid != null) {
for (MediaSeries s : seriesList) {
if (!uid.equals(TagD.getTagValue(s, Tag.SeriesInstanceUID))) {
sameOrigin = false;
break;
}
}
}
if (sameOrigin) {
popupMenu.add(new JSeparator());
JMenuItem item2 = new JMenuItem(Messages.getString("DicomExplorer.merge")); //$NON-NLS-1$
item2.addActionListener(e -> {
selList.clear();
dicomModel.mergeSeries(seriesList);
});
popupMenu.add(item2);
}
}
}
popupMenu.add(new JSeparator());
JMenuItem item2 = new JMenuItem(Messages.getString("DicomExplorer.rem_series")); //$NON-NLS-1$
item2.addActionListener(e -> {
for (int i = selList.size() - 1; i >= 0; i--) {
dicomModel.removeSeries(selList.get(i));
}
selList.clear();
});
popupMenu.add(item2);
if (selList.size() == 1) {
item2 = new JMenuItem(Messages.getString("DicomExplorer.rem_study")); //$NON-NLS-1$
item2.addActionListener(e -> {
MediaSeriesGroup studyGroup = dicomModel.getParent(series, DicomModel.study);
dicomModel.removeStudy(studyGroup);
selList.clear();
});
popupMenu.add(item2);
item2 = new JMenuItem(Messages.getString("DicomExplorer.rem_pat")); //$NON-NLS-1$
item2.addActionListener(e -> {
MediaSeriesGroup patientGroup =
dicomModel.getParent(dicomModel.getParent(series, DicomModel.study), DicomModel.patient);
dicomModel.removePatient(patientGroup);
selList.clear();
});
popupMenu.add(item2);
if (series.size(null) > 1) {
if (series.getMedia(0, null, null) instanceof ImageElement) {
popupMenu.add(new JSeparator());
JMenu menu = new JMenu(Messages.getString("DicomExplorer.build_thumb")); //$NON-NLS-1$
item2 = new JMenuItem(Messages.getString("DicomExplorer.from_1")); //$NON-NLS-1$
item2.addActionListener(e -> {
SeriesThumbnail t = (SeriesThumbnail) series.getTagValue(TagW.Thumbnail);
if (t != null) {
t.reBuildThumbnail(MEDIA_POSITION.FIRST);
}
});
menu.add(item2);
item2 = new JMenuItem(Messages.getString("DicomExplorer.from_mid")); //$NON-NLS-1$
item2.addActionListener(e -> {
SeriesThumbnail t = (SeriesThumbnail) series.getTagValue(TagW.Thumbnail);
if (t != null) {
t.reBuildThumbnail(MEDIA_POSITION.MIDDLE);
}
});
menu.add(item2);
item2 = new JMenuItem(Messages.getString("DicomExplorer.from_last")); //$NON-NLS-1$
item2.addActionListener(e -> {
SeriesThumbnail t = (SeriesThumbnail) series.getTagValue(TagW.Thumbnail);
if (t != null) {
t.reBuildThumbnail(MEDIA_POSITION.LAST);
}
});
menu.add(item2);
popupMenu.add(menu);
}
}
}
popupMenu.show(mouseevent.getComponent(), mouseevent.getX() - 5, mouseevent.getY() - 5);
} else {
selList.adjustSelection(mouseevent, series);
}
}
@Override
public void keyTyped(KeyEvent e) {
// Do nothing
}
@Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
SeriesSelectionModel selList = getSeriesSelectionModel();
if (code == KeyEvent.VK_ENTER) {
if (selList.isEmpty()) {
selList.add(series);
}
selList.setOpenningSeries(true);
ViewerPluginBuilder.openSequenceInDefaultPlugin(new ArrayList<MediaSeries<? extends MediaElement>>(selList),
dicomModel, true, true);
selList.setOpenningSeries(false);
if (e.getSource() instanceof JComponent) {
((JComponent) e.getSource()).requestFocusInWindow();
}
e.consume();
} else if (code == KeyEvent.VK_DOWN) {
selList.adjustSelection(e, selList.getNextElement(series));
} else if (code == KeyEvent.VK_UP) {
selList.adjustSelection(e, selList.getPreviousElement(series));
} else if (e.isControlDown() && code == KeyEvent.VK_A) {
selList.setSelectionInterval(selList.getFirstElement(), selList.getLastElement());
} else if (code == KeyEvent.VK_PAGE_DOWN || code == KeyEvent.VK_END) {
Series val = selList.getLastElement();
selList.setSelectionInterval(val, val);
} else if (code == KeyEvent.VK_PAGE_UP || code == KeyEvent.VK_HOME) {
Series val = selList.getFirstElement();
selList.setSelectionInterval(val, val);
}
}
@Override
public void keyReleased(KeyEvent e) {
// Do nothing
}
public static SeriesSelectionModel getSeriesSelectionModel() {
DataExplorerView explorer = UIManager.getExplorerplugin(DicomExplorer.NAME);
return explorer instanceof DicomExplorer ? ((DicomExplorer) explorer).getSelectionList()
: new SeriesSelectionModel(null);
}
}