/*******************************************************************************
* 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.acquire.explorer.gui.dialog;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.media.jai.PlanarImage;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import javax.swing.SwingWorker.StateValue;
import javax.swing.border.EmptyBorder;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import org.osgi.framework.FrameworkUtil;
import org.osgi.service.prefs.Preferences;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.weasis.acquire.explorer.AcquireImageInfo;
import org.weasis.acquire.explorer.AcquireManager;
import org.weasis.acquire.explorer.DicomizeTask;
import org.weasis.acquire.explorer.Messages;
import org.weasis.acquire.explorer.gui.central.meta.model.imp.AcquireGlobalMeta;
import org.weasis.acquire.explorer.gui.central.meta.model.imp.AcquireImageMeta;
import org.weasis.acquire.explorer.gui.central.meta.model.imp.AcquireSerieMeta;
import org.weasis.acquire.explorer.gui.control.AcquirePublishPanel;
import org.weasis.acquire.explorer.gui.model.publish.PublishTree;
import org.weasis.acquire.explorer.util.ImageInfoHelper;
import org.weasis.core.api.gui.util.WinUtil;
import org.weasis.core.api.image.ZoomOp;
import org.weasis.core.api.service.BundlePreferences;
import org.weasis.core.api.service.BundleTools;
import org.weasis.core.api.util.FontTools;
import org.weasis.core.api.util.StringUtil;
import org.weasis.core.api.util.ThreadUtil;
import org.weasis.dicom.explorer.pref.node.AbstractDicomNode;
import org.weasis.dicom.explorer.pref.node.AbstractDicomNode.UsageType;
import org.weasis.dicom.explorer.pref.node.DefaultDicomNode;
@SuppressWarnings("serial")
public class AcquirePublishDialog extends JDialog {
private static final Logger LOGGER = LoggerFactory.getLogger(AcquirePublishDialog.class);
public static final String P_LAST_RES = "last.dir"; //$NON-NLS-1$
public static final String PREFERENCE_NODE = "publish"; //$NON-NLS-1$
public enum Resolution {
ORIGINAL(Messages.getString("AcquirePublishDialog.original"), Integer.MAX_VALUE), //$NON-NLS-1$
ULTRA_HD(Messages.getString("AcquirePublishDialog.high_res"), 3840), //$NON-NLS-1$
FULL_HD(Messages.getString("AcquirePublishDialog.med_res"), 1920), //$NON-NLS-1$
HD_DVD(Messages.getString("AcquirePublishDialog.low_res"), 1280); //$NON-NLS-1$
private String title;
private int maxSize;
Resolution(String title, int size) {
this.title = title;
this.maxSize = size;
}
@Override
public String toString() {
return title;
}
public String getTitle() {
return title;
}
public int getMaxSize() {
return maxSize;
}
public static Resolution getInstance(String val) {
if (StringUtil.hasText(val)) {
try {
return Resolution.valueOf(val);
} catch (Exception e) {
LOGGER.error("Cannot find Resolution: {}", val, e); //$NON-NLS-1$
}
}
return Resolution.ORIGINAL;
}
}
private final AcquirePublishPanel publishPanel;
private PublishTree publishTree;
private JPanel resolutionPane;
private JComboBox<Resolution> resolutionCombo;
private JButton publishButton;
private JButton cancelButton;
private JProgressBar progressBar;
private transient ActionListener clearAndHideActionListener;
private final JComboBox<AbstractDicomNode> comboNode = new JComboBox<>();
public AcquirePublishDialog(AcquirePublishPanel publishPanel) {
super(WinUtil.getParentWindow(publishPanel), Messages.getString("AcquirePublishDialog.publication"), ModalityType.APPLICATION_MODAL); //$NON-NLS-1$
this.publishPanel = publishPanel;
setContentPane(initContent());
publishTree.getTree().addCheckingPath(new TreePath(publishTree.getModel().getRootNode().getPath()));
setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent we) {
cancelButton.doClick();
}
});
setPreferredSize(new Dimension(700, 400));
pack();
}
private JPanel initContent() {
JPanel contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(10, 10, 10, 10));
contentPane.setLayout(new BorderLayout());
JLabel questionLabel = new JLabel(Messages.getString("AcquirePublishDialog.select_pub")); //$NON-NLS-1$
questionLabel.setFont(FontTools.getFont12Bold());
contentPane.add(questionLabel, BorderLayout.NORTH);
JPanel imageTreePane = new JPanel(new BorderLayout());
imageTreePane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
publishTree = new PublishTree();
publishTree.addTreeCheckingListener(evt -> {
resolutionPane.setVisible(!getOversizedSelected(publishTree).isEmpty());
resolutionPane.repaint();
});
publishTree.setMinimumSize(publishTree.getPreferredSize());
imageTreePane.add(publishTree);
contentPane.add(imageTreePane, BorderLayout.CENTER);
JPanel actionPane = new JPanel(new BorderLayout());
actionPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
resolutionPane = new JPanel();
resolutionPane.setBorder(BorderFactory.createLineBorder(Color.BLACK));
JLabel resolutionLabel =
new JLabel(Messages.getString("AcquirePublishDialog.resolution") + StringUtil.COLON_AND_SPACE); //$NON-NLS-1$
resolutionPane.add(resolutionLabel);
resolutionCombo = new JComboBox<>(Resolution.values());
Preferences prefs =
BundlePreferences.getDefaultPreferences(FrameworkUtil.getBundle(this.getClass()).getBundleContext());
if (prefs != null) {
Preferences p = prefs.node(PREFERENCE_NODE);
resolutionCombo.setSelectedItem(Resolution.getInstance(p.get(P_LAST_RES, Resolution.ORIGINAL.name())));
}
resolutionPane.add(resolutionCombo);
resolutionPane.setVisible(Boolean.FALSE);
actionPane.add(resolutionPane, BorderLayout.NORTH);
progressBar = new JProgressBar();
progressBar.setStringPainted(true);
progressBar.setVisible(false);
actionPane.add(progressBar, BorderLayout.CENTER);
JPanel bottomPane = new JPanel(new BorderLayout());
JPanel buttonPane = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10));
publishButton = new JButton(Messages.getString("AcquirePublishDialog.publish")); //$NON-NLS-1$
publishButton.addActionListener(e -> publishAction());
cancelButton = new JButton(Messages.getString("AcquirePublishDialog.cancel")); //$NON-NLS-1$
clearAndHideActionListener = e -> clearAndHide();
cancelButton.addActionListener(clearAndHideActionListener);
JPanel destPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 10));
JLabel lblDestination =
new JLabel(Messages.getString("AcquirePublishDialog.lblDestination.text") + StringUtil.COLON); //$NON-NLS-1$
destPane.add(lblDestination);
AbstractDicomNode.addTooltipToComboList(comboNode);
if (!StringUtil.hasText(BundleTools.SYSTEM_PREFERENCES.getProperty("weasis.acquire.dest.host"))) { //$NON-NLS-1$
DefaultDicomNode.loadDicomNodes(comboNode, AbstractDicomNode.Type.DICOM, UsageType.STORAGE);
if (comboNode.getItemCount() == 0) {
comboNode.addItem(getDestinationConfiguration());
}
} else {
comboNode.addItem(getDestinationConfiguration());
}
destPane.add(comboNode);
bottomPane.add(destPane, BorderLayout.WEST);
buttonPane.add(publishButton);
buttonPane.add(cancelButton);
bottomPane.add(buttonPane, BorderLayout.EAST);
actionPane.add(bottomPane, BorderLayout.SOUTH);
contentPane.add(actionPane, BorderLayout.SOUTH);
return contentPane;
}
private static AbstractDicomNode getDestinationConfiguration() {
String host = BundleTools.SYSTEM_PREFERENCES.getProperty("weasis.acquire.dest.host", "localhost"); //$NON-NLS-1$ //$NON-NLS-2$
String aet = BundleTools.SYSTEM_PREFERENCES.getProperty("weasis.acquire.dest.aet", "DCM4CHEE"); //$NON-NLS-1$ //$NON-NLS-2$
String port = BundleTools.SYSTEM_PREFERENCES.getProperty("weasis.acquire.dest.port", "11112"); //$NON-NLS-1$ //$NON-NLS-2$
return new DefaultDicomNode(Messages.getString("AcquirePublishDialog.def_archive"), aet, host, //$NON-NLS-1$
Integer.parseInt(port), UsageType.BOTH);
}
private void publishAction() {
List<AcquireImageInfo> toPublish = getSelectedImages(publishTree);
if (toPublish.isEmpty()) {
JOptionPane.showMessageDialog(this, Messages.getString("AcquirePublishDialog.select_one_msg"), //$NON-NLS-1$
this.getTitle(), JOptionPane.ERROR_MESSAGE);
return;
}
boolean publishable = AcquireGlobalMeta.isPublishable(AcquireManager.GLOBAL);
if (publishable) {
for (AcquireImageInfo info : toPublish) {
publishable = AcquireSerieMeta.isPublishable(info.getSeries());
if (!publishable) {
break;
}
publishable = AcquireImageMeta.isPublishable(info.getImage());
if (!publishable) {
break;
}
}
}
if (!publishable) {
JOptionPane.showMessageDialog(this, Messages.getString("AcquirePublishDialog.pub_warn_msg"), //$NON-NLS-1$
this.getTitle(), JOptionPane.ERROR_MESSAGE);
return;
}
List<AcquireImageInfo> overSizedSelected = getOversizedSelected(publishTree);
if (!overSizedSelected.isEmpty()) {
Resolution resolution = (Resolution) resolutionCombo.getSelectedItem();
for (AcquireImageInfo imgInfo : overSizedSelected) {
// calculate zoom ration
Double ratio = ImageInfoHelper.calculateRatio(imgInfo, resolution);
imgInfo.getCurrentValues().setRatio(ratio);
imgInfo.getPostProcessOpManager().setParamValue(ZoomOp.OP_NAME, ZoomOp.P_RATIO_X, ratio);
imgInfo.getPostProcessOpManager().setParamValue(ZoomOp.OP_NAME, ZoomOp.P_RATIO_Y, ratio);
}
}
SwingWorker<File, AcquireImageInfo> dicomizeTask = new DicomizeTask(toPublish);
ActionListener taskCancelActionListener = e -> dicomizeTask.cancel(true);
dicomizeTask.addPropertyChangeListener(evt -> {
if ("progress" == evt.getPropertyName()) { //$NON-NLS-1$
int progress = (Integer) evt.getNewValue();
progressBar.setValue(progress);
} else if ("state" == evt.getPropertyName()) { //$NON-NLS-1$
if (StateValue.STARTED == evt.getNewValue()) {
resolutionPane.setVisible(false);
progressBar.setVisible(true);
publishButton.setEnabled(false);
cancelButton.removeActionListener(clearAndHideActionListener);
cancelButton.addActionListener(taskCancelActionListener);
} else if (StateValue.DONE == evt.getNewValue()) {
File exportDirDicom = null;
if (!dicomizeTask.isCancelled()) {
try {
exportDirDicom = dicomizeTask.get();
} catch (InterruptedException doNothing) {
LOGGER.warn("Dicomizing task Interruption"); //$NON-NLS-1$
} catch (ExecutionException e) {
LOGGER.error("Dicomizing task", e); //$NON-NLS-1$
}
if (exportDirDicom != null) {
AbstractDicomNode node = (AbstractDicomNode) comboNode.getSelectedItem();
if (node instanceof DefaultDicomNode) {
publishPanel.publishDirDicom(exportDirDicom, ((DefaultDicomNode) node).getDicomNode());
clearAndHide();
}
} else {
JOptionPane.showMessageDialog(this,
Messages.getString("AcquirePublishDialog.dicomize_error_msg"), //$NON-NLS-1$
Messages.getString("AcquirePublishDialog.dicomize_error_title"), //$NON-NLS-1$
JOptionPane.ERROR_MESSAGE);
}
}
if (exportDirDicom == null) {
resolutionPane.setVisible(!getOversizedSelected(publishTree).isEmpty());
progressBar.setValue(0);
progressBar.setVisible(false);
publishButton.setEnabled(true);
cancelButton.removeActionListener(taskCancelActionListener);
cancelButton.addActionListener(clearAndHideActionListener);
}
}
}
});
ThreadUtil.buildNewSingleThreadExecutor("Dicomize").execute(dicomizeTask); //$NON-NLS-1$
}
private List<AcquireImageInfo> getSelectedImages(PublishTree tree) {
return Arrays.stream(tree.getModel().getCheckingPaths())
.map(o1 -> DefaultMutableTreeNode.class.cast(o1.getLastPathComponent()))
.filter(o2 -> AcquireImageInfo.class.isInstance(o2.getUserObject()))
.map(o3 -> AcquireImageInfo.class.cast(o3.getUserObject())).collect(Collectors.toList());
}
private List<AcquireImageInfo> getOversizedSelected(PublishTree tree) {
return getSelectedImages(tree).stream().filter(oversizedImages()).collect(Collectors.toList());
}
private Predicate<AcquireImageInfo> oversizedImages() {
return acqImg -> {
PlanarImage img = acqImg.getImage().getImage(acqImg.getPostProcessOpManager());
Integer width = img.getWidth();
Integer height = img.getHeight();
return width > Resolution.ULTRA_HD.maxSize || height > Resolution.ULTRA_HD.maxSize;
};
}
public void clearAndHide() {
Resolution resolution = (Resolution) resolutionCombo.getSelectedItem();
dispose();
Preferences prefs =
BundlePreferences.getDefaultPreferences(FrameworkUtil.getBundle(this.getClass()).getBundleContext());
if (prefs != null) {
Preferences p = prefs.node(PREFERENCE_NODE);
BundlePreferences.putStringPreferences(p, P_LAST_RES, resolution.name());
}
}
}