/*******************************************************************************
* 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.mip;
import java.awt.Component;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.util.Comparator;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.DefaultBoundedRangeModel;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.weasis.core.api.gui.util.ActionState;
import org.weasis.core.api.gui.util.ActionW;
import org.weasis.core.api.gui.util.DecFormater;
import org.weasis.core.api.gui.util.Filter;
import org.weasis.core.api.gui.util.JSliderW;
import org.weasis.core.api.gui.util.SliderChangeListener;
import org.weasis.core.api.gui.util.SliderCineListener;
import org.weasis.core.api.media.data.MediaSeries;
import org.weasis.core.api.media.data.SeriesComparator;
import org.weasis.core.api.util.StringUtil;
import org.weasis.dicom.codec.DicomImageElement;
import org.weasis.dicom.viewer2d.Messages;
public class MipPopup {
private final Logger LOGGER = LoggerFactory.getLogger(MipPopup.class);
public static MipDialog buildDialog(final MipView view) {
if (view == null || view.IsProcessRunning()) {
return null;
}
return new MipDialog(view);
}
static JSliderW createSlider(String title, int labelDivision, boolean displayValueInTitle,
DefaultBoundedRangeModel model) {
final JPanel palenSlider1 = new JPanel();
palenSlider1.setLayout(new BoxLayout(palenSlider1, BoxLayout.Y_AXIS));
palenSlider1.setBorder(new TitledBorder(title));
JSliderW slider = new JSliderW(model.getMinimum(), model.getMaximum() / 2 + 1, 1);
slider.setLabelDivision(labelDivision);
slider.setdisplayValueInTitle(displayValueInTitle);
slider.setPaintTicks(true);
palenSlider1.add(slider);
if (labelDivision > 0) {
slider.setPaintLabels(true);
SliderChangeListener.setSliderLabelValues(slider, slider.getMinimum(), slider.getMaximum());
}
return slider;
}
static void updateSliderProoperties(JSliderW slider, String title) {
JPanel panel = (JPanel) slider.getParent();
if (slider.isdisplayValueInTitle() && panel != null && panel.getBorder() instanceof TitledBorder) {
((TitledBorder) panel.getBorder()).setTitle(title);
panel.repaint();
} else {
slider.setToolTipText(title);
}
}
public static class MipDialog extends JDialog {
final MipView view;
JSliderW frameSlider;
JSliderW thickness;
ChangeListener scrollListerner;
public MipDialog(MipView view) {
super(SwingUtilities.getWindowAncestor(view), Messages.getString("MipPopup.title"), //$NON-NLS-1$
ModalityType.APPLICATION_MODAL);
this.view = view;
this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
this.setIconImage(MipView.MIP_ICON_SETTING.getImage());
init();
}
private void init() {
final Container panel_1 = getContentPane();
panel_1.setLayout(new BoxLayout(panel_1, BoxLayout.Y_AXIS));
final JPanel framePanel = new JPanel();
framePanel.setBorder(new TitledBorder(null, Messages.getString("MipPopup.projection"), TitledBorder.LEADING, //$NON-NLS-1$
TitledBorder.TOP, null, null));
final ButtonGroup ratioGroup = new ButtonGroup();
JRadioButton rdbtnMinProjection = new JRadioButton(Messages.getString("MipPopup.min")); //$NON-NLS-1$
framePanel.add(rdbtnMinProjection);
JRadioButton rdbtnMeanProjection = new JRadioButton(Messages.getString("MipPopup.mean")); //$NON-NLS-1$
framePanel.add(rdbtnMeanProjection);
JRadioButton rdbtnMaxProjection = new JRadioButton(Messages.getString("MipPopup.max")); //$NON-NLS-1$
framePanel.add(rdbtnMaxProjection);
panel_1.add(framePanel);
ratioGroup.add(rdbtnMinProjection);
ratioGroup.add(rdbtnMeanProjection);
ratioGroup.add(rdbtnMaxProjection);
MipView.Type type = (MipView.Type) view.getActionValue(MipView.MIP.cmd());
if (MipView.Type.MIN.equals(type)) {
rdbtnMinProjection.setSelected(true);
} else if (MipView.Type.MEAN.equals(type)) {
rdbtnMeanProjection.setSelected(true);
} else {
rdbtnMaxProjection.setSelected(true);
}
rdbtnMinProjection.addActionListener(e -> {
if (e.getSource() instanceof JRadioButton) {
JRadioButton btn = (JRadioButton) e.getSource();
if (btn.isSelected()) {
view.setActionsInView(MipView.MIP.cmd(), MipView.Type.MIN);
MipView.buildMip(MipDialog.this, view, false);
}
}
});
rdbtnMeanProjection.addActionListener(e -> {
if (e.getSource() instanceof JRadioButton) {
JRadioButton btn = (JRadioButton) e.getSource();
if (btn.isSelected()) {
view.setActionsInView(MipView.MIP.cmd(), MipView.Type.MEAN);
MipView.buildMip(MipDialog.this, view, false);
}
}
});
rdbtnMaxProjection.addActionListener(e -> {
if (e.getSource() instanceof JRadioButton) {
JRadioButton btn = (JRadioButton) e.getSource();
if (btn.isSelected()) {
view.setActionsInView(MipView.MIP.cmd(), MipView.Type.MAX);
MipView.buildMip(MipDialog.this, view, false);
}
}
});
ActionListener close = e -> dispose();
ActionState sequence = view.getEventManager().getAction(ActionW.SCROLL_SERIES);
if (sequence instanceof SliderCineListener) {
SliderCineListener cineAction = (SliderCineListener) sequence;
frameSlider = cineAction.createSlider(2, true);
panel_1.add(frameSlider.getParent());
final JSliderW sliderThickness =
createSlider(MipView.MIP_THICKNESS.getTitle(), 4, true, cineAction.getSliderModel());
thickness = sliderThickness;
panel_1.add(sliderThickness.getParent());
Integer extend = (Integer) view.getActionValue(MipView.MIP_THICKNESS.cmd());
sliderThickness.setValue(extend == null ? 2 : extend);
updateSliderProoperties(sliderThickness,
MipView.MIP_THICKNESS.getTitle() + StringUtil.COLON_AND_SPACE + sliderThickness.getValue());
scrollListerner = e -> {
JSliderW slider = (JSliderW) e.getSource();
getThickness(sliderThickness);
if (!slider.getValueIsAdjusting()) {
view.setActionsInView(ActionW.SCROLL_SERIES.cmd(), slider.getValue());
MipView.buildMip(MipDialog.this, view, false);
}
};
frameSlider.addChangeListener(scrollListerner);
sliderThickness.addChangeListener(e -> {
JSliderW slider = (JSliderW) e.getSource();
getThickness(slider);
if (!slider.getValueIsAdjusting()) {
view.setActionsInView(MipView.MIP_THICKNESS.cmd(), slider.getValue());
MipView.buildMip(MipDialog.this, view, false);
}
});
}
JPanel panel = new JPanel();
FlowLayout flowLayout = (FlowLayout) panel.getLayout();
flowLayout.setAlignment(FlowLayout.TRAILING);
panel.setBorder(new EmptyBorder(20, 15, 10, 15));
getContentPane().add(panel);
JButton btnExitMipMode = new JButton(Messages.getString("MipPopup.rebuild_series")); //$NON-NLS-1$
btnExitMipMode.addActionListener(e -> {
MipView.buildMip(MipDialog.this, view, true);
dispose();
});
panel.add(btnExitMipMode);
Component horizontalStrut = Box.createHorizontalStrut(20);
panel.add(horizontalStrut);
JButton btnClose = new JButton(Messages.getString("MipPopup.close")); //$NON-NLS-1$
btnClose.addActionListener(close);
panel.add(btnClose);
}
private void getThickness(final JSliderW sliderThickness) {
StringBuilder buf = new StringBuilder(MipView.MIP_THICKNESS.getTitle());
buf.append(StringUtil.COLON_AND_SPACE);
int val = sliderThickness.getValue();
buf.append(val);
MediaSeries<DicomImageElement> series = view.getSeries();
if (series != null) {
int slice = frameSlider.getValue() - 1;
SeriesComparator sort = (SeriesComparator) view.getActionValue(ActionW.SORTSTACK.cmd());
Boolean reverse = (Boolean) view.getActionValue(ActionW.INVERSESTACK.cmd());
Comparator sortFilter = (reverse != null && reverse) ? sort.getReversOrderComparator() : sort;
Filter filter = (Filter) view.getActionValue(ActionW.FILTERED_SERIES.cmd());
int min = Math.max(0, slice - val);
int max = Math.min(series.size(filter) - 1, slice + val);
DicomImageElement fimg = series.getMedia(min, filter, sortFilter);
DicomImageElement limg = series.getMedia(max, filter, sortFilter);
if (fimg != null && limg != null) {
buf.append(" ("); //$NON-NLS-1$
buf.append(DecFormater.oneDecimal(SeriesBuilder.getThickness(fimg, limg)));
buf.append(" "); //$NON-NLS-1$
buf.append(fimg.getPixelSpacingUnit().getAbbreviation());
buf.append(")"); //$NON-NLS-1$
}
}
updateSliderProoperties(sliderThickness, buf.toString());
}
public void updateThickness() {
getThickness(thickness);
}
@Override
public void dispose() {
if (frameSlider != null) {
frameSlider.removeChangeListener(scrollListerner);
ActionState sequence = view.getEventManager().getAction(ActionW.SCROLL_SERIES);
if (sequence instanceof SliderCineListener) {
SliderCineListener cineAction = (SliderCineListener) sequence;
cineAction.unregisterActionState(frameSlider);
}
}
view.exitMipMode(view.getSeries(), null);
super.dispose();
}
}
}