/*******************************************************************************
* 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.base.viewer2d;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.FocusEvent;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import javax.swing.ButtonGroup;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JSeparator;
import javax.swing.KeyStroke;
import javax.swing.TransferHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.weasis.core.api.explorer.model.DataExplorerModel;
import org.weasis.core.api.explorer.model.TreeModel;
import org.weasis.core.api.gui.util.ActionState;
import org.weasis.core.api.gui.util.ActionW;
import org.weasis.core.api.gui.util.JMVUtils;
import org.weasis.core.api.gui.util.MouseActionAdapter;
import org.weasis.core.api.image.FilterOp;
import org.weasis.core.api.image.FlipOp;
import org.weasis.core.api.image.PseudoColorOp;
import org.weasis.core.api.image.RotationOp;
import org.weasis.core.api.image.SimpleOpManager;
import org.weasis.core.api.image.WindowOp;
import org.weasis.core.api.image.ZoomOp;
import org.weasis.core.api.image.util.ImageLayer;
import org.weasis.core.api.media.data.ImageElement;
import org.weasis.core.api.media.data.MediaSeriesGroup;
import org.weasis.core.api.media.data.Series;
import org.weasis.core.api.media.data.TagW;
import org.weasis.core.api.service.BundleTools;
import org.weasis.core.api.util.StringUtil;
import org.weasis.core.ui.dialog.MeasureDialog;
import org.weasis.core.ui.docking.UIManager;
import org.weasis.core.ui.editor.ViewerPluginBuilder;
import org.weasis.core.ui.editor.image.CalibrationView;
import org.weasis.core.ui.editor.image.DefaultView2d;
import org.weasis.core.ui.editor.image.ImageViewerEventManager;
import org.weasis.core.ui.editor.image.ImageViewerPlugin;
import org.weasis.core.ui.editor.image.MouseActions;
import org.weasis.core.ui.editor.image.PannerListener;
import org.weasis.core.ui.editor.image.SynchData;
import org.weasis.core.ui.editor.image.ViewCanvas;
import org.weasis.core.ui.editor.image.ViewerPlugin;
import org.weasis.core.ui.editor.image.ViewerToolBar;
import org.weasis.core.ui.model.graphic.DragGraphic;
import org.weasis.core.ui.model.graphic.Graphic;
import org.weasis.core.ui.model.graphic.imp.line.LineGraphic;
import org.weasis.core.ui.util.ColorLayerUI;
import org.weasis.core.ui.util.MouseEventDouble;
import org.weasis.core.ui.util.TitleMenuItem;
import org.weasis.core.ui.util.UriListFlavor;
public class View2d extends DefaultView2d<ImageElement> {
private static final Logger LOGGER = LoggerFactory.getLogger(View2d.class);
private final Dimension oldSize;
private final ContextMenuHandler contextMenuHandler = new ContextMenuHandler();
public View2d(ImageViewerEventManager<ImageElement> eventManager) {
super(eventManager);
SimpleOpManager manager = imageLayer.getDisplayOpManager();
manager.addImageOperationAction(new WindowOp());
manager.addImageOperationAction(new FilterOp());
manager.addImageOperationAction(new PseudoColorOp());
// Zoom and Rotation must be the last operations for the lens
manager.addImageOperationAction(new ZoomOp());
manager.addImageOperationAction(new RotationOp());
manager.addImageOperationAction(new FlipOp());
infoLayer = new InfoLayer(this);
oldSize = new Dimension(0, 0);
}
@Override
public void registerDefaultListeners() {
buildPanner();
super.registerDefaultListeners();
setTransferHandler(new SequenceHandler());
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
View2d.this.componentResized();
}
});
}
private void componentResized() {
Double currentZoom = (Double) actionsInView.get(ActionW.ZOOM.cmd());
/*
* Negative value means a default value according to the zoom type (pixel size, best fit...). Set again to
* default value to compute again the position. For instance, the image cannot be center aligned until the view
* has been repaint once (because the size is null).
*/
if (currentZoom <= 0.0) {
zoom(0.0);
}
if (panner != null) {
panner.updateImageSize();
}
if (lens != null) {
int w = getWidth();
int h = getHeight();
if (w != 0 && h != 0) {
Rectangle bound = lens.getBounds();
if (oldSize.width != 0 && oldSize.height != 0) {
int centerx = bound.width / 2;
int centery = bound.height / 2;
bound.x = (bound.x + centerx) * w / oldSize.width - centerx;
bound.y = (bound.y + centery) * h / oldSize.height - centery;
lens.setLocation(bound.x, bound.y);
}
oldSize.width = w;
oldSize.height = h;
}
lens.updateZoom();
}
}
@Override
protected void initActionWState() {
super.initActionWState();
actionsInView.put(ActionW.ZOOM.cmd(), -1.0);
actionsInView.put(ViewCanvas.ZOOM_TYPE_CMD, ZoomType.PIXEL_SIZE);
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
super.propertyChange(evt);
if (series == null) {
return;
}
}
@Override
public synchronized void enableMouseAndKeyListener(MouseActions actions) {
disableMouseAndKeyListener();
iniDefaultMouseListener();
iniDefaultKeyListener();
// Set the butonMask to 0 of all the actions
resetMouseAdapter();
this.setCursor(DefaultView2d.DEFAULT_CURSOR);
addMouseAdapter(actions.getLeft(), InputEvent.BUTTON1_DOWN_MASK); // left mouse button
if (actions.getMiddle().equals(actions.getLeft())) {
// If mouse action is already registered, only add the modifier mask
MouseActionAdapter adapter = getMouseAdapter(actions.getMiddle());
adapter.setButtonMaskEx(adapter.getButtonMaskEx() | InputEvent.BUTTON2_DOWN_MASK);
} else {
addMouseAdapter(actions.getMiddle(), InputEvent.BUTTON2_DOWN_MASK);// middle mouse button
}
if (actions.getRight().equals(actions.getLeft()) || actions.getRight().equals(actions.getMiddle())) {
// If mouse action is already registered, only add the modifier mask
MouseActionAdapter adapter = getMouseAdapter(actions.getRight());
adapter.setButtonMaskEx(adapter.getButtonMaskEx() | InputEvent.BUTTON3_DOWN_MASK);
} else {
addMouseAdapter(actions.getRight(), InputEvent.BUTTON3_DOWN_MASK); // right mouse button
}
this.addMouseWheelListener(getMouseAdapter(actions.getWheel()));
}
private void addMouseAdapter(String actionName, int buttonMask) {
MouseActionAdapter adapter = getMouseAdapter(actionName);
if (adapter == null) {
return;
}
adapter.setButtonMaskEx(adapter.getButtonMaskEx() | buttonMask);
if (adapter == graphicMouseHandler) {
this.addKeyListener(drawingsKeyListeners);
} else if (adapter instanceof PannerListener) {
((PannerListener) adapter).reset();
this.addKeyListener((PannerListener) adapter);
}
if (actionName.equals(ActionW.WINLEVEL.cmd())) {
// For window/level action set window action on x axis
MouseActionAdapter win = getAction(ActionW.WINDOW);
if (win != null) {
win.setButtonMaskEx(win.getButtonMaskEx() | buttonMask);
win.setMoveOnX(true);
this.addMouseListener(win);
this.addMouseMotionListener(win);
}
// set level action with inverse progression (move the cursor down will decrease the values)
adapter.setInverse(true);
} else if (actionName.equals(ActionW.WINDOW.cmd())) {
adapter.setMoveOnX(false);
} else if (actionName.equals(ActionW.LEVEL.cmd())) {
adapter.setInverse(true);
}
this.addMouseListener(adapter);
this.addMouseMotionListener(adapter);
}
protected MouseActionAdapter getMouseAdapter(String command) {
if (command.equals(ActionW.CONTEXTMENU.cmd())) {
return contextMenuHandler;
} else if (command.equals(ActionW.WINLEVEL.cmd())) {
return getAction(ActionW.LEVEL);
}
Optional<ActionW> actionKey = eventManager.getActionKey(command);
if (!actionKey.isPresent()) {
return null;
}
if (actionKey.get().isDrawingAction()) {
return graphicMouseHandler;
}
return eventManager.getAction(actionKey.get(), MouseActionAdapter.class).orElse(null);
}
private void resetMouseAdapter() {
for (ActionState adapter : eventManager.getAllActionValues()) {
if (adapter instanceof MouseActionAdapter) {
((MouseActionAdapter) adapter).setButtonMaskEx(0);
}
}
// reset context menu that is a field of this instance
contextMenuHandler.setButtonMaskEx(0);
graphicMouseHandler.setButtonMaskEx(0);
}
private MouseActionAdapter getAction(ActionW action) {
ActionState a = eventManager.getAction(action);
if (a instanceof MouseActionAdapter) {
return (MouseActionAdapter) a;
}
return null;
}
@Override
public void handleLayerChanged(ImageLayer layer) {
repaint();
}
@Override
public void focusGained(FocusEvent e) {
if (!e.isTemporary()) {
ImageViewerPlugin<ImageElement> pane = eventManager.getSelectedView2dContainer();
if (pane != null && pane.isContainingView(this)) {
pane.setSelectedImagePaneFromFocus(this);
}
}
}
protected JPopupMenu buildGraphicContextMenu(final MouseEvent evt, final List<Graphic> selected) {
if (selected != null) {
JPopupMenu popupMenu = new JPopupMenu();
TitleMenuItem itemTitle = new TitleMenuItem(Messages.getString("View2d.selection"), popupMenu.getInsets()); //$NON-NLS-1$
popupMenu.add(itemTitle);
popupMenu.addSeparator();
boolean graphicComplete = true;
if (selected.size() == 1) {
final Graphic graph = selected.get(0);
if (graph instanceof DragGraphic) {
final DragGraphic absgraph = (DragGraphic) graph;
if (!absgraph.isGraphicComplete()) {
graphicComplete = false;
}
if (absgraph.getVariablePointsNumber()) {
if (graphicComplete) {
/*
* Convert mouse event point to real image coordinate point (without geometric
* transformation)
*/
final MouseEventDouble mouseEvt = new MouseEventDouble(View2d.this,
MouseEvent.MOUSE_RELEASED, evt.getWhen(), 16, 0, 0, 0, 0, 1, true, 1);
mouseEvt.setSource(View2d.this);
mouseEvt.setImageCoordinates(getImageCoordinatesFromMouse(evt.getX(), evt.getY()));
final int ptIndex = absgraph.getHandlePointIndex(mouseEvt);
if (ptIndex >= 0) {
JMenuItem menuItem = new JMenuItem(Messages.getString("View2d.rem_point")); //$NON-NLS-1$
menuItem.addActionListener(e -> absgraph.removeHandlePoint(ptIndex, mouseEvt));
popupMenu.add(menuItem);
menuItem = new JMenuItem(Messages.getString("View2d.add_point")); //$NON-NLS-1$
menuItem.addActionListener(e -> {
absgraph.forceToAddPoints(ptIndex);
MouseEventDouble evt2 =
new MouseEventDouble(View2d.this, MouseEvent.MOUSE_PRESSED, evt.getWhen(), 16,
evt.getX(), evt.getY(), evt.getXOnScreen(), evt.getYOnScreen(), 1, true, 1);
graphicMouseHandler.mousePressed(evt2);
});
popupMenu.add(menuItem);
popupMenu.add(new JSeparator());
}
} else if (graphicMouseHandler.getDragSequence() != null
&& Objects.equals(absgraph.getPtsNumber(), Graphic.UNDEFINED)) {
final JMenuItem item2 = new JMenuItem(Messages.getString("View2d.stop_draw")); //$NON-NLS-1$
item2.addActionListener(e -> {
MouseEventDouble event =
new MouseEventDouble(View2d.this, 0, 0, 16, 0, 0, 0, 0, 2, true, 1);
graphicMouseHandler.getDragSequence().completeDrag(event);
graphicMouseHandler.mouseReleased(event);
});
popupMenu.add(item2);
popupMenu.add(new JSeparator());
}
}
}
}
if (graphicComplete) {
JMenuItem menuItem = new JMenuItem(Messages.getString("View2d.delete_selec")); //$NON-NLS-1$
menuItem
.addActionListener(e -> View2d.this.getGraphicManager().deleteSelectedGraphics(View2d.this, true));
popupMenu.add(menuItem);
menuItem = new JMenuItem(Messages.getString("View2d.cut")); //$NON-NLS-1$
menuItem.addActionListener(e -> {
DefaultView2d.GRAPHIC_CLIPBOARD.setGraphics(selected);
View2d.this.getGraphicManager().deleteSelectedGraphics(View2d.this, false);
});
popupMenu.add(menuItem);
menuItem = new JMenuItem(Messages.getString("View2d.copy")); //$NON-NLS-1$
menuItem.addActionListener(e -> DefaultView2d.GRAPHIC_CLIPBOARD.setGraphics(selected));
popupMenu.add(menuItem);
popupMenu.add(new JSeparator());
}
final ArrayList<DragGraphic> list = new ArrayList<>();
for (Graphic graphic : selected) {
if (graphic instanceof DragGraphic) {
list.add((DragGraphic) graphic);
}
}
if (selected.size() == 1) {
final Graphic graph = selected.get(0);
JMenuItem item = new JMenuItem(Messages.getString("View2d.front")); //$NON-NLS-1$
item.addActionListener(e -> graph.toFront());
popupMenu.add(item);
item = new JMenuItem(Messages.getString("View2d.back")); //$NON-NLS-1$
item.addActionListener(e -> graph.toBack());
popupMenu.add(item);
popupMenu.add(new JSeparator());
if (graphicComplete && graph instanceof LineGraphic) {
final JMenuItem calibMenu = new JMenuItem(Messages.getString("View2d.calib")); //$NON-NLS-1$
calibMenu.addActionListener(e -> {
ColorLayerUI layer = ColorLayerUI.createTransparentLayerUI(View2d.this);
String title = Messages.getString("View2d.man_calib"); //$NON-NLS-1$
CalibrationView calibrationDialog = new CalibrationView((LineGraphic) graph, View2d.this, false);
int res = JOptionPane.showConfirmDialog(ColorLayerUI.getContentPane(layer), calibrationDialog,
title, JOptionPane.OK_CANCEL_OPTION);
if (layer != null) {
layer.hideUI();
}
if (res == JOptionPane.OK_OPTION) {
calibrationDialog.applyNewCalibration();
}
});
popupMenu.add(calibMenu);
popupMenu.add(new JSeparator());
}
}
if (!list.isEmpty()) {
JMenuItem properties = new JMenuItem(Messages.getString("View2d.prop")); //$NON-NLS-1$
properties.addActionListener(e -> {
ColorLayerUI layer = ColorLayerUI.createTransparentLayerUI(View2d.this);
JDialog dialog = new MeasureDialog(View2d.this, list);
ColorLayerUI.showCenterScreen(dialog, layer);
});
popupMenu.add(properties);
}
return popupMenu;
}
return null;
}
protected JPopupMenu buildContexMenu(final MouseEvent evt) {
JPopupMenu popupMenu = new JPopupMenu();
TitleMenuItem itemTitle =
new TitleMenuItem(Messages.getString("View2d.left_mouse") + StringUtil.COLON, popupMenu.getInsets()); //$NON-NLS-1$
popupMenu.add(itemTitle);
popupMenu.setLabel(MouseActions.LEFT);
String action = eventManager.getMouseActions().getLeft();
int count = popupMenu.getComponentCount();
ButtonGroup groupButtons = new ButtonGroup();
ImageViewerPlugin<ImageElement> view = eventManager.getSelectedView2dContainer();
if (view != null) {
final ViewerToolBar toolBar = view.getViewerToolBar();
if (toolBar != null) {
ActionListener leftButtonAction = e -> {
if (e.getSource() instanceof JRadioButtonMenuItem) {
JRadioButtonMenuItem item = (JRadioButtonMenuItem) e.getSource();
toolBar.changeButtonState(MouseActions.LEFT, item.getActionCommand());
}
};
List<ActionW> actionsButtons = ViewerToolBar.actionsButtons;
synchronized (actionsButtons) {
for (int i = 0; i < actionsButtons.size(); i++) {
ActionW b = actionsButtons.get(i);
if (eventManager.isActionRegistered(b)) {
JRadioButtonMenuItem radio =
new JRadioButtonMenuItem(b.getTitle(), b.getIcon(), b.cmd().equals(action));
radio.setActionCommand(b.cmd());
radio.setAccelerator(KeyStroke.getKeyStroke(b.getKeyCode(), b.getModifier()));
// Trigger the selected mouse action
radio.addActionListener(toolBar);
// Update the state of the button in the toolbar
radio.addActionListener(leftButtonAction);
popupMenu.add(radio);
groupButtons.add(radio);
}
}
}
}
}
if (count < popupMenu.getComponentCount()) {
popupMenu.add(new JSeparator());
count = popupMenu.getComponentCount();
}
if (DefaultView2d.GRAPHIC_CLIPBOARD.hasGraphics()) {
JMenuItem menuItem = new JMenuItem(Messages.getString("View2d.paste_draw")); //$NON-NLS-1$
menuItem.addActionListener(e -> copyGraphicsFromClipboard());
popupMenu.add(menuItem);
}
if (count < popupMenu.getComponentCount()) {
popupMenu.add(new JSeparator());
count = popupMenu.getComponentCount();
}
if (eventManager instanceof EventManager) {
EventManager manager = (EventManager) eventManager;
JMVUtils.addItemToMenu(popupMenu, manager.getLutMenu("weasis.contextmenu.lut")); //$NON-NLS-1$
JMVUtils.addItemToMenu(popupMenu, manager.getLutInverseMenu("weasis.contextmenu.invertLut")); //$NON-NLS-1$
JMVUtils.addItemToMenu(popupMenu, manager.getFilterMenu("weasis.contextmenu.filter")); //$NON-NLS-1$
if (count < popupMenu.getComponentCount()) {
popupMenu.add(new JSeparator());
count = popupMenu.getComponentCount();
}
JMVUtils.addItemToMenu(popupMenu, manager.getZoomMenu("weasis.contextmenu.zoom")); //$NON-NLS-1$
JMVUtils.addItemToMenu(popupMenu, manager.getOrientationMenu("weasis.contextmenu.orientation")); //$NON-NLS-1$
if (count < popupMenu.getComponentCount()) {
popupMenu.add(new JSeparator());
}
JMVUtils.addItemToMenu(popupMenu, manager.getResetMenu("weasis.contextmenu.reset")); //$NON-NLS-1$
}
if (BundleTools.SYSTEM_PREFERENCES.getBooleanProperty("weasis.contextmenu.close", true)) { //$NON-NLS-1$
JMenuItem close = new JMenuItem(Messages.getString("View2d.close")); //$NON-NLS-1$
close.addActionListener(e -> View2d.this.setSeries(null, null));
popupMenu.add(close);
}
return popupMenu;
}
class ContextMenuHandler extends MouseActionAdapter {
@Override
public void mousePressed(final MouseEvent evt) {
showPopup(evt);
}
@Override
public void mouseReleased(final MouseEvent evt) {
showPopup(evt);
}
private void showPopup(final MouseEvent evt) {
// Context menu
if ((evt.getModifiersEx() & getButtonMaskEx()) != 0) {
JPopupMenu popupMenu = null;
final List<Graphic> selected = View2d.this.getGraphicManager().getSelectedGraphics();
if (!selected.isEmpty() && isDrawActionActive()) {
popupMenu = View2d.this.buildGraphicContextMenu(evt, selected);
} else if (View2d.this.getSourceImage() != null) {
popupMenu = View2d.this.buildContexMenu(evt);
}
if (popupMenu != null) {
popupMenu.show(evt.getComponent(), evt.getX(), evt.getY());
}
}
}
}
private class SequenceHandler extends TransferHandler {
public SequenceHandler() {
super("series"); //$NON-NLS-1$
}
@Override
public Transferable createTransferable(JComponent comp) {
return null;
}
@Override
public boolean canImport(TransferSupport support) {
if (!support.isDrop()) {
return false;
}
if (support.isDataFlavorSupported(Series.sequenceDataFlavor)
|| support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)
|| support.isDataFlavorSupported(UriListFlavor.flavor)) {
return true;
}
return false;
}
@Override
public boolean importData(TransferSupport support) {
if (!canImport(support)) {
return false;
}
Transferable transferable = support.getTransferable();
List<File> files = null;
// Not supported by some OS
if (support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
try {
files = (List<File>) transferable.getTransferData(DataFlavor.javaFileListFlavor);
} catch (Exception e) {
LOGGER.error("Get dragable files", e); //$NON-NLS-1$
}
return dropDicomFiles(files);
}
// When dragging a file or group of files
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4899516
else if (support.isDataFlavorSupported(UriListFlavor.flavor)) {
try {
// Files with spaces in the filename trigger an error
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6936006
String val = (String) transferable.getTransferData(UriListFlavor.flavor);
files = UriListFlavor.textURIListToFileList(val);
} catch (Exception e) {
LOGGER.error("Get dragable URIs", e); //$NON-NLS-1$
}
return dropDicomFiles(files);
}
ImageViewerPlugin<ImageElement> selPlugin = eventManager.getSelectedView2dContainer();
Series seq;
try {
seq = (Series) transferable.getTransferData(Series.sequenceDataFlavor);
// Do not add series without medias. BUG WEA-100
if (seq == null || seq.size(null) == 0) {
return false;
}
DataExplorerModel model = (DataExplorerModel) seq.getTagValue(TagW.ExplorerModel);
if (seq.getMedia(0, null, null) instanceof ImageElement && model instanceof TreeModel) {
TreeModel treeModel = (TreeModel) model;
MediaSeriesGroup p1 = treeModel.getParent(seq, model.getTreeModelNodeForNewPlugin());
ViewerPlugin openPlugin = null;
if (p1 != null) {
if (selPlugin instanceof View2dContainer
&& ((View2dContainer) selPlugin).isContainingView(View2d.this)
&& p1.equals(selPlugin.getGroupID())) {
} else {
synchronized (UIManager.VIEWER_PLUGINS) {
plugin: for (final ViewerPlugin<?> p : UIManager.VIEWER_PLUGINS) {
if (p1.equals(p.getGroupID())) {
if (!((View2dContainer) p).isContainingView(View2d.this)) {
openPlugin = p;
}
break plugin;
}
}
}
if (openPlugin == null) {
if (View2d.this.getSeries() != null) {
ViewerPluginBuilder.openSequenceInDefaultPlugin(seq, model, true, true);
return true;
}
} else {
openPlugin.setSelectedAndGetFocus();
openPlugin.addSeries(seq);
// openPlugin.setSelected(true);
return false;
}
}
}
} else {
ViewerPluginBuilder.openSequenceInDefaultPlugin(seq,
model == null ? ViewerPluginBuilder.DefaultDataModel : model, true, true);
return true;
}
} catch (Exception e) {
LOGGER.error("Opening series", e); //$NON-NLS-1$
return false;
}
if (selPlugin != null && SynchData.Mode.TILE.equals(selPlugin.getSynchView().getSynchData().getMode())) {
selPlugin.addSeries(seq);
return true;
}
setSeries(seq);
// Getting the focus has a delay and so it will trigger the view selection later
// requestFocusInWindow();
if (selPlugin != null && selPlugin.isContainingView(View2d.this)) {
selPlugin.setSelectedImagePaneFromFocus(View2d.this);
}
return true;
}
private boolean dropDicomFiles(List<File> files) {
if (files != null) {
for (File file : files) {
ViewerPluginBuilder.openSequenceInDefaultPlugin(file, true, true);
}
return true;
}
return false;
}
}
}