diff --git a/src/main/java/io/github/mzmine/datamodel/FeatureStatus.java b/src/main/java/io/github/mzmine/datamodel/FeatureStatus.java index bcd44c960dc..bf38d357831 100644 --- a/src/main/java/io/github/mzmine/datamodel/FeatureStatus.java +++ b/src/main/java/io/github/mzmine/datamodel/FeatureStatus.java @@ -17,6 +17,8 @@ package io.github.mzmine.datamodel; +import io.github.mzmine.util.color.SimpleColorPalette; +import io.github.mzmine.util.javafx.FxColorUtil; import java.awt.Color; import io.github.mzmine.main.MZmineCore; import io.github.mzmine.util.color.Colors; @@ -46,36 +48,37 @@ public enum FeatureStatus { MANUAL; public Color getColor() { - Vision vision = - MZmineCore.getConfiguration() != null ? MZmineCore.getConfiguration().getColorVision() - : Vision.DEUTERANOPIA; + SimpleColorPalette palette = + (MZmineCore.getConfiguration().getDefaultColorPalette() != null) ? MZmineCore.getConfiguration() + .getDefaultColorPalette() : SimpleColorPalette.DEFAULT.get(Vision.DEUTERANOPIA); switch (this) { case DETECTED: - return Colors.getPositiveColor(vision); + return palette.getPositiveColorAWT(); case ESTIMATED: - return Colors.getNeutralColor(); + return palette.getNeutralColorAWT(); case MANUAL: return Color.BLACK; case UNKNOWN: default: - return Colors.getNegativeColor(vision); + return palette.getNegativeColorAWT(); } } public javafx.scene.paint.Color getColorFX() { - Vision vision = - MZmineCore.getConfiguration() != null ? MZmineCore.getConfiguration().getColorVision() - : Vision.DEUTERANOPIA; + SimpleColorPalette palette = + (MZmineCore.getConfiguration().getDefaultColorPalette() != null) ? MZmineCore.getConfiguration() + .getDefaultColorPalette() : SimpleColorPalette.DEFAULT.get(Vision.DEUTERANOPIA); + switch (this) { case DETECTED: - return ColorsFX.getPositiveColor(vision); + return palette.getPositiveColor(); case ESTIMATED: - return ColorsFX.getNeutralColor(); + return palette.getNeutralColor(); case MANUAL: return javafx.scene.paint.Color.BLACK; case UNKNOWN: default: - return ColorsFX.getNegativeColor(vision); + return palette.getNegativeColor(); } } } diff --git a/src/main/java/io/github/mzmine/gui/chartbasics/chartthemes/ChartThemeParameters.java b/src/main/java/io/github/mzmine/gui/chartbasics/chartthemes/ChartThemeParameters.java index a861854ba0a..528e81fe322 100644 --- a/src/main/java/io/github/mzmine/gui/chartbasics/chartthemes/ChartThemeParameters.java +++ b/src/main/java/io/github/mzmine/gui/chartbasics/chartthemes/ChartThemeParameters.java @@ -19,10 +19,7 @@ package io.github.mzmine.gui.chartbasics.chartthemes; -import java.util.List; import org.jfree.chart.JFreeChart; -import org.jfree.chart.plot.XYPlot; -import org.jfree.chart.title.Title; import io.github.mzmine.parameters.Parameter; import io.github.mzmine.parameters.dialogs.ParameterSetupDialog; import io.github.mzmine.parameters.impl.SimpleParameterSet; @@ -82,7 +79,7 @@ public class ChartThemeParameters extends SimpleParameterSet { public static final BooleanParameter showYAxis = new BooleanParameter("Show y axis", "", true); public ChartThemeParameters() { - super(new Parameter[] {showLegends, showTitle, changeTitle, xlabel, ylabel, color, masterFont, + super(new Parameter[]{showLegends, showTitle, changeTitle, xlabel, ylabel, color, masterFont, titleFont, captionFont, labelFont, xGridPaint, yGridPaint, showXAxis, showYAxis}); changeTitle.setValue(false); xlabel.setValue(false); @@ -96,13 +93,15 @@ public ExitCode showSetupDialog(boolean valueCheckRequired) { assert Platform.isFxApplicationThread(); - if ((parameters == null) || (parameters.length == 0)) + if ((parameters == null) || (parameters.length == 0)) { return ExitCode.OK; + } ParameterSetupDialog dialog = new ChartThemeParametersSetupDialog(valueCheckRequired, this); dialog.showAndWait(); return dialog.getExitCode(); } + @Deprecated public void applyToChart(JFreeChart chart) { // // apply chart settings // boolean showTitle = this.getParameter(ChartThemeParameters.showTitle).getValue(); @@ -169,29 +168,29 @@ public void applyToChartTheme(EStandardChartTheme theme) { String ylabel = this.getParameter(ChartThemeParameters.ylabel).getEmbeddedParameter().getValue(); FontSpecs master = this.getParameter(ChartThemeParameters.masterFont).getValue(); - FontSpecs large = this.getParameter(ChartThemeParameters.titleFont).getValue(); - FontSpecs medium = this.getParameter(ChartThemeParameters.captionFont).getValue(); - FontSpecs small = this.getParameter(ChartThemeParameters.labelFont).getValue(); + FontSpecs titleFont = this.getParameter(ChartThemeParameters.titleFont).getValue(); + FontSpecs captionFont = this.getParameter(ChartThemeParameters.captionFont).getValue(); + FontSpecs labelFont = this.getParameter(ChartThemeParameters.labelFont).getValue(); Color bgColor = this.getParameter(ChartThemeParameters.color).getValue(); theme.setShowTitle(showTitle); - theme.getShowSubtitles(showLegends); + theme.getShowSubtitles(showTitle); theme.setChartBackgroundPaint(FxColorUtil.fxColorToAWT(bgColor)); theme.setPlotBackgroundPaint(FxColorUtil.fxColorToAWT(bgColor)); theme.setMasterFont(FxFontUtil.fxFontToAWT(master.getFont())); - theme.setExtraLargeFont(FxFontUtil.fxFontToAWT(large.getFont())); - theme.setLargeFont(FxFontUtil.fxFontToAWT(medium.getFont())); - theme.setRegularFont(FxFontUtil.fxFontToAWT(small.getFont())); - theme.setSmallFont(FxFontUtil.fxFontToAWT(small.getFont())); + theme.setExtraLargeFont(FxFontUtil.fxFontToAWT(titleFont.getFont())); + theme.setLargeFont(FxFontUtil.fxFontToAWT(captionFont.getFont())); + theme.setRegularFont(FxFontUtil.fxFontToAWT(labelFont.getFont())); + theme.setSmallFont(FxFontUtil.fxFontToAWT(labelFont.getFont())); theme.setMasterFontColor(FxColorUtil.fxColorToAWT(master.getColor())); - theme.setAxisLabelPaint(FxColorUtil.fxColorToAWT(medium.getColor())); - theme.setTickLabelPaint(FxColorUtil.fxColorToAWT(small.getColor())); - theme.setTitlePaint(FxColorUtil.fxColorToAWT(large.getColor())); - theme.setItemLabelPaint(FxColorUtil.fxColorToAWT(small.getColor())); - theme.setLegendItemPaint(FxColorUtil.fxColorToAWT(medium.getColor())); - theme.setAxisLinePaint(FxColorUtil.fxColorToAWT(medium.getColor())); + theme.setAxisLabelPaint(FxColorUtil.fxColorToAWT(captionFont.getColor())); + theme.setTickLabelPaint(FxColorUtil.fxColorToAWT(labelFont.getColor())); + theme.setTitlePaint(FxColorUtil.fxColorToAWT(titleFont.getColor())); + theme.setItemLabelPaint(FxColorUtil.fxColorToAWT(labelFont.getColor())); + theme.setLegendItemPaint(FxColorUtil.fxColorToAWT(captionFont.getColor())); + theme.setAxisLinePaint(FxColorUtil.fxColorToAWT(captionFont.getColor())); theme.setShowXAxis(showXAxis); theme.setShowYAxis(showYAxis); diff --git a/src/main/java/io/github/mzmine/gui/chartbasics/chartthemes/EStandardChartTheme.java b/src/main/java/io/github/mzmine/gui/chartbasics/chartthemes/EStandardChartTheme.java index 83bd128eb4c..3a0433ec457 100644 --- a/src/main/java/io/github/mzmine/gui/chartbasics/chartthemes/EStandardChartTheme.java +++ b/src/main/java/io/github/mzmine/gui/chartbasics/chartthemes/EStandardChartTheme.java @@ -18,20 +18,25 @@ package io.github.mzmine.gui.chartbasics.chartthemes; +import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Paint; +import java.awt.Stroke; +import javax.annotation.Nonnull; import org.jfree.chart.JFreeChart; import org.jfree.chart.StandardChartTheme; import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.block.BlockBorder; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.category.StandardBarPainter; import org.jfree.chart.renderer.xy.StandardXYBarPainter; import org.jfree.chart.title.LegendTitle; import org.jfree.chart.title.PaintScaleLegend; +import org.jfree.chart.title.TextTitle; import org.jfree.chart.ui.RectangleEdge; import io.github.mzmine.gui.chartbasics.chartthemes.ChartThemeFactory.THEME; -import io.github.mzmine.util.javafx.FxColorUtil; +import org.jfree.chart.ui.RectangleInsets; /** * More options for the StandardChartTheme @@ -42,6 +47,14 @@ public class EStandardChartTheme extends StandardChartTheme { private static final long serialVersionUID = 1L; private static final Color DEFAULT_GRID_COLOR = Color.BLACK; + private static final Color DEFAULT_CROSS_HAIR_COLOR = Color.BLACK; + + private static final boolean DEFAULT_CROSS_HAIR_VISIBLE = true; + private static final Stroke DEFAULT_CROSS_HAIR_STROKE = new BasicStroke(1.0F, BasicStroke.CAP_BUTT, + BasicStroke.JOIN_BEVEL, 1.0f, new float[] {5.0F, 3.0F}, 0.0F); + + private static final RectangleInsets DEFAULT_AXIS_OFFSET = new RectangleInsets(5.0, 5.0, 5.0, 5.0); + private static final double TITLE_TOP_MARGIN = 5.0; public static final String XML_DESC = "ChartTheme"; // master font @@ -126,9 +139,50 @@ public void setAll(boolean antiAlias, boolean showTitle, boolean noBG, Color cBG public void apply(JFreeChart chart) { super.apply(chart); XYPlot p = chart.getXYPlot(); + + // Cross hair and axis visibility colors + applyToCrosshair(chart); + applyToAxes(chart); + +// applyToTitles(chart); + + // apply bg + chart.setBackgroundPaint(this.getChartBackgroundPaint()); + chart.getPlot().setBackgroundPaint(this.getPlotBackgroundPaint()); + // - p.setDomainGridlinesVisible(showXGrid); - p.setRangeGridlinesVisible(showYGrid); + chart.setAntiAlias(isAntiAliased()); + p.setBackgroundAlpha(isNoBackground() ? 0 : 1); + + applyToLegend(chart); + + } + + + public void applyToCrosshair(@Nonnull JFreeChart chart){ + XYPlot p = chart.getXYPlot(); + p.setDomainCrosshairPaint(DEFAULT_CROSS_HAIR_COLOR); + p.setRangeCrosshairPaint(DEFAULT_CROSS_HAIR_COLOR); + p.setDomainCrosshairStroke(DEFAULT_CROSS_HAIR_STROKE); + p.setRangeCrosshairStroke(DEFAULT_CROSS_HAIR_STROKE); + p.setDomainCrosshairVisible(DEFAULT_CROSS_HAIR_VISIBLE); + p.setRangeCrosshairVisible(DEFAULT_CROSS_HAIR_VISIBLE); + } + + public void applyToAxes(@Nonnull JFreeChart chart){ + XYPlot p = chart.getXYPlot(); + p.getDomainAxis().setVisible(isShowXAxis()); + p.getRangeAxis().setVisible(isShowYAxis()); + p.setDomainGridlinesVisible(isShowXGrid()); + p.setDomainGridlinePaint(getClrXGrid()); + p.setRangeGridlinesVisible(isShowYGrid()); + p.setRangeGridlinePaint(getClrYGrid()); + + if (isUseXLabel()) + p.getDomainAxis().setLabel(getXlabel()); + if (isUseYLabel()) + p.getRangeAxis().setLabel(getYlabel()); + // all axes for (int i = 0; i < p.getDomainAxisCount(); i++) { NumberAxis a = (NumberAxis) p.getDomainAxis(i); @@ -144,42 +198,35 @@ public void apply(JFreeChart chart) { // visible? a.setVisible(showYAxis); } - // apply bg - chart.setBackgroundPaint(this.getChartBackgroundPaint()); - chart.getPlot().setBackgroundPaint(this.getPlotBackgroundPaint()); - for (int i = 0; i < chart.getSubtitleCount(); i++) { - // visible? - chart.getSubtitle(i).setVisible(subtitleVisible); - // - if (PaintScaleLegend.class.isAssignableFrom(chart.getSubtitle(i).getClass())) - ((PaintScaleLegend) chart.getSubtitle(i)) - .setBackgroundPaint(this.getChartBackgroundPaint()); - } - if (chart.getLegend() != null) - chart.getLegend().setBackgroundPaint(this.getChartBackgroundPaint()); - - if (isUseXLabel()) - p.getDomainAxis().setLabel(getXlabel()); - if (isUseYLabel()) - p.getRangeAxis().setLabel(getYlabel()); - - p.getDomainAxis().setVisible(isShowXAxis()); - p.getRangeAxis().setVisible(isShowYAxis()); + p.setAxisOffset(DEFAULT_AXIS_OFFSET); + } - p.setDomainGridlinesVisible(isShowXGrid()); - p.setDomainGridlinePaint(getClrXGrid()); - p.setRangeGridlinesVisible(isShowYGrid()); - p.setRangeGridlinePaint(getClrYGrid()); + public void applyToLegend(@Nonnull JFreeChart chart){ - // - chart.setAntiAlias(isAntiAliased()); - chart.getTitle().setVisible(isShowTitle()); - p.setBackgroundAlpha(isNoBackground() ? 0 : 1); + if (chart.getLegend() != null) + chart.getLegend().setBackgroundPaint(this.getChartBackgroundPaint()); fixLegend(chart); } +// public void applyToTitles(@Nonnull JFreeChart chart){ +// chart.getSubtitles().forEach(s -> { +// if(s instanceof TextTitle && s != chart.getTitle()){ +// ((TextTitle) s).setFont(getRegularFont()); +// ((TextTitle) s).setMargin(TITLE_TOP_MARGIN, 0d, 0d, 0d); +// ((TextTitle) s).setVisible(isShowTitle()); +//// ((TextTitle) s).setPaint(subtitleFontColor); // should be set by the theme itself. +//// subtitle color is set by the chart theme parameters +// +// if (PaintScaleLegend.class.isAssignableFrom(s.getClass())) { +// ((PaintScaleLegend) s) +// .setBackgroundPaint(this.getChartBackgroundPaint()); +// } +// } +// }); +// } + public boolean isNoBackground() { return ((Color) this.getPlotBackgroundPaint()).getAlpha() == 0; } @@ -194,6 +241,8 @@ public void setNoBackground(boolean state) { new Color(cchart.getRed(), cchart.getGreen(), cchart.getBlue(), state ? 0 : 255)); } + + /** * Fixes the legend item's colour after the colours of the datasets/series in the plot were * changed. @@ -211,6 +260,7 @@ public static void fixLegend(JFreeChart chart) { newLegend.setItemFont(oldLegend.getItemFont()); chart.addLegend(newLegend); newLegend.setVisible(oldLegend.isVisible()); + newLegend.setFrame(BlockBorder.NONE); } // GETTERS AND SETTERS @@ -349,4 +399,5 @@ public Color getClrYGrid() { public void setClrYGrid(Color clrYGrid) { this.clrYGrid = clrYGrid; } + } diff --git a/src/main/java/io/github/mzmine/gui/chartbasics/graphicsexport/GraphicsExportDialogFX.java b/src/main/java/io/github/mzmine/gui/chartbasics/graphicsexport/GraphicsExportDialogFX.java index 3026a2ff70c..47da013b4c7 100644 --- a/src/main/java/io/github/mzmine/gui/chartbasics/graphicsexport/GraphicsExportDialogFX.java +++ b/src/main/java/io/github/mzmine/gui/chartbasics/graphicsexport/GraphicsExportDialogFX.java @@ -18,6 +18,8 @@ package io.github.mzmine.gui.chartbasics.graphicsexport; +import io.github.mzmine.util.color.SimpleColorPalette; +import io.github.mzmine.util.javafx.FxColorUtil; import java.awt.Color; import java.io.File; import java.util.logging.Level; @@ -60,7 +62,7 @@ public class GraphicsExportDialogFX extends ParameterSetupDialog { protected JFreeChart chart; protected EChartViewer chartPanel; protected ChartThemeParameters chartParam; - protected Color[] colors; + protected SimpleColorPalette colors; private Button btnRenewPreview; private Button btnApply; @@ -74,7 +76,7 @@ public GraphicsExportDialogFX(boolean valueCheckRequired, ParameterSet parameter chartParam = (ChartThemeParameters) parameterSet .getParameter(GraphicsExportParameters.chartParameters).getValue(); - colors = Colors.getSevenColorPalette(MZmineCore.getConfiguration().getColorVision(), true); + colors = parameterSet.getParameter(GraphicsExportParameters.colorPalette).getValue(); try { this.chart = (JFreeChart) chart.clone(); @@ -115,9 +117,11 @@ public GraphicsExportDialogFX(boolean valueCheckRequired, ParameterSet parameter protected void applyTheme() { // update param updateParameterSetFromComponents(); + chartParam = (ChartThemeParameters) parameterSet + .getParameter(GraphicsExportParameters.chartParameters).getValue(); + colors = parameterSet.getParameter(GraphicsExportParameters.colorPalette).getValue(); // apply settings chartParam.applyToChartTheme(theme); - chartParam.applyToChart(chartPanel.getChart()); setStandardColors(); theme.apply(chartPanel.getChart()); disableCrosshair(); @@ -130,7 +134,11 @@ protected void disableCrosshair() { } protected void setStandardColors() { - DrawingSupplier ds = new DefaultDrawingSupplier(colors, colors, colors, + Color[] clrs = new Color[colors.size()]; + for(int i = 0; i < colors.size(); i++) + clrs[i] = colors.getAWT(i); + + DrawingSupplier ds = new DefaultDrawingSupplier(clrs, clrs, clrs, DefaultDrawingSupplier.DEFAULT_STROKE_SEQUENCE, DefaultDrawingSupplier.DEFAULT_OUTLINE_STROKE_SEQUENCE, DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE); diff --git a/src/main/java/io/github/mzmine/gui/chartbasics/graphicsexport/GraphicsExportParameters.java b/src/main/java/io/github/mzmine/gui/chartbasics/graphicsexport/GraphicsExportParameters.java index f9dd7ee9b88..d01c009d145 100644 --- a/src/main/java/io/github/mzmine/gui/chartbasics/graphicsexport/GraphicsExportParameters.java +++ b/src/main/java/io/github/mzmine/gui/chartbasics/graphicsexport/GraphicsExportParameters.java @@ -18,6 +18,7 @@ package io.github.mzmine.gui.chartbasics.graphicsexport; +import io.github.mzmine.parameters.parametertypes.colorpalette.ColorPaletteParameter; import java.awt.Dimension; import java.io.File; import java.text.DecimalFormat; @@ -82,9 +83,11 @@ public enum FixedSize { public static final ParameterSetParameter chartParameters = new ParameterSetParameter( "Chart parameters", "Manually set the chart parameters", new ChartThemeParameters()); + public static final ColorPaletteParameter colorPalette = new ColorPaletteParameter("Color palette", "The color palette used for export."); + public GraphicsExportParameters() { super(new Parameter[] {path, unit, exportFormat, fixedSize, width, height, dpi, color, alpha, - chartParameters}); + chartParameters, colorPalette}); height.setValue(true); } diff --git a/src/main/java/io/github/mzmine/gui/chartbasics/gui/javafx/EChartViewer.java b/src/main/java/io/github/mzmine/gui/chartbasics/gui/javafx/EChartViewer.java index c690911bcaf..e710d507641 100644 --- a/src/main/java/io/github/mzmine/gui/chartbasics/gui/javafx/EChartViewer.java +++ b/src/main/java/io/github/mzmine/gui/chartbasics/gui/javafx/EChartViewer.java @@ -135,6 +135,9 @@ public EChartViewer(JFreeChart chart, boolean graphicsExportMenu, boolean dataEx // Add Export to Excel and graphics export menu if (graphicsExportMenu || dataExportMenu) addExportMenu(graphicsExportMenu, dataExportMenu); + + // apply the theme here, let's see how that works + MZmineCore.getConfiguration().getDefaultChartTheme().apply(this.getChart()); } protected void addMenuItem(Menu parent, String title, EventHandler al) { diff --git a/src/main/java/io/github/mzmine/gui/preferences/MZminePreferences.java b/src/main/java/io/github/mzmine/gui/preferences/MZminePreferences.java index f52b80a564a..cbbe0338bd0 100644 --- a/src/main/java/io/github/mzmine/gui/preferences/MZminePreferences.java +++ b/src/main/java/io/github/mzmine/gui/preferences/MZminePreferences.java @@ -38,10 +38,10 @@ public class MZminePreferences extends SimpleParameterSet { - public static final ComboParameter colorPalettes = new ComboParameter<>( - "Color palettes (color blindness mode)", - "Some modules use the color blindness aware palettes for a higher contrast. Think about using this mode even with \"normal vision\" to reach everyone.", - FXCollections.observableArrayList(Vision.values()), Vision.DEUTERANOPIA); +// public static final ComboParameter colorPalettes = new ComboParameter<>( +// "Color palettes (color blindness mode)", +// "Some modules use the color blindness aware palettes for a higher contrast. Think about using this mode even with \"normal vision\" to reach everyone.", +// FXCollections.observableArrayList(Vision.values()), Vision.DEUTERANOPIA); public static final NumberFormatParameter mzFormat = new NumberFormatParameter("m/z value format", "Format of m/z values", false, new DecimalFormat("0.0000")); @@ -83,7 +83,7 @@ public class MZminePreferences extends SimpleParameterSet { public static final BooleanParameter darkMode = new BooleanParameter("Dark mode", "Enables dark mode throughout MZmine.", false); public MZminePreferences() { - super(new Parameter[] {colorPalettes, mzFormat, rtFormat, intensityFormat, numOfThreads, + super(new Parameter[]{mzFormat, rtFormat, intensityFormat, numOfThreads, proxySettings, rExecPath, sendStatistics, windowSetttings, sendErrorEMail, stdColorPalette, chartParam}); } diff --git a/src/main/java/io/github/mzmine/main/MZmineConfiguration.java b/src/main/java/io/github/mzmine/main/MZmineConfiguration.java index 70f45d9127a..14434cbf6b3 100644 --- a/src/main/java/io/github/mzmine/main/MZmineConfiguration.java +++ b/src/main/java/io/github/mzmine/main/MZmineConfiguration.java @@ -81,7 +81,7 @@ public interface MZmineConfiguration { * * @return */ - public Vision getColorVision(); +// public Vision getColorVision(); public SimpleColorPalette getDefaultColorPalette(); diff --git a/src/main/java/io/github/mzmine/main/impl/MZmineConfigurationImpl.java b/src/main/java/io/github/mzmine/main/impl/MZmineConfigurationImpl.java index dc7d3cdcc68..43d5bbd0ac5 100644 --- a/src/main/java/io/github/mzmine/main/impl/MZmineConfigurationImpl.java +++ b/src/main/java/io/github/mzmine/main/impl/MZmineConfigurationImpl.java @@ -138,10 +138,10 @@ public void setModuleParameters(Class moduleClass, } // color palettes - @Override - public Vision getColorVision() { - return preferences.getParameter(MZminePreferences.colorPalettes).getValue(); - } +// @Override +// public Vision getColorVision() { +// return preferences.getParameter(MZminePreferences.colorPalettes).getValue(); +// } // Number formatting functions @Override @@ -340,7 +340,7 @@ public FileNameListSilentParameter getLastProjectsParameter() { @Override public SimpleColorPalette getDefaultColorPalette() { SimpleColorPalette p = preferences.getParameter(MZminePreferences.stdColorPalette).getValue(); - if (!p.isValidPalette()) { + if (!p.isValid()) { logger.warning( "Current default color palette set in preferences is invalid. Returning standard " + "colors."); @@ -358,9 +358,9 @@ public ChartThemeParameters getDefaultChartThemeParameters() { @Override public EStandardChartTheme getDefaultChartTheme() { // update the theme settings first - ChartThemeParameters ctp = MZmineCore.getConfiguration().getDefaultChartThemeParameters(); + ChartThemeParameters ctp = this.getDefaultChartThemeParameters(); ctp.applyToChartTheme(standardChartTheme); - SimpleColorPalette scp = MZmineCore.getConfiguration().getDefaultColorPalette(); + SimpleColorPalette scp = this.getDefaultColorPalette(); scp.applyToChartTheme(standardChartTheme); return standardChartTheme; diff --git a/src/main/java/io/github/mzmine/modules/dataprocessing/id_lipididentification/lipids/LipidDatabaseTableController.java b/src/main/java/io/github/mzmine/modules/dataprocessing/id_lipididentification/lipids/LipidDatabaseTableController.java index 1475491cdfb..8bb56b87964 100644 --- a/src/main/java/io/github/mzmine/modules/dataprocessing/id_lipididentification/lipids/LipidDatabaseTableController.java +++ b/src/main/java/io/github/mzmine/modules/dataprocessing/id_lipididentification/lipids/LipidDatabaseTableController.java @@ -18,6 +18,8 @@ package io.github.mzmine.modules.dataprocessing.id_lipididentification.lipids; +import io.github.mzmine.util.color.SimpleColorPalette; +import io.github.mzmine.util.javafx.FxColorUtil; import java.text.NumberFormat; import org.jfree.chart.ChartFactory; import org.jfree.chart.JFreeChart; @@ -178,18 +180,19 @@ public void initialize(ParameterSet parameters, LipidClasses[] selectedLipids) { selectedLipids[i].getMainClass().getName(), // main class selectedLipids[i].getName(), // lipid class lipidChain.getFormula(), // molecular formula - selectedLipids[i].getAbbr() + " (" + chainLength + ":" + chainDoubleBonds + ")", // abbr + selectedLipids[i].getAbbr() + " (" + chainLength + ":" + chainDoubleBonds + ")", + // abbr ionizationType.toString(), // ionization type numberFormat.format(lipidChain.getMass() + ionizationType.getAddedMass()), // exact - // mass + // mass "", // info "", // status String.join(", ", selectedLipids[i].getMsmsFragmentsPositiveIonization()), // msms - // fragments - // postive + // fragments + // postive String.join(", ", selectedLipids[i].getMsmsFragmentsNegativeIonization()))); // msms - // fragments - // negative + // fragments + // negative id++; if (useModification) { for (int j = 0; j < lipidModification.length; j++) { @@ -200,11 +203,12 @@ public void initialize(ParameterSet parameters, LipidClasses[] selectedLipids) { // class lipidChain.getFormula() + lipidModification[j].getLipidModificatio(), // sum // formula - selectedLipids[i].getAbbr() + " (" + chainLength + ":" + chainDoubleBonds + ")"// abbr + selectedLipids[i].getAbbr() + " (" + chainLength + ":" + chainDoubleBonds + ")" +// abbr + lipidModification[j].getLipidModificatio(), ionizationType.toString(), // ionization type numberFormat.format(lipidChain.getMass() + ionizationType.getAddedMass() // exact - // mass + // mass + lipidModification[j].getModificationMass()), "", // info "", // status @@ -234,17 +238,20 @@ public void initialize(ParameterSet parameters, LipidClasses[] selectedLipids) { checkInterferences(); // set colors depending on colors - Vision vision = MZminePreferences.colorPalettes.getValue(); + SimpleColorPalette palette = + (MZmineCore.getConfiguration().getDefaultColorPalette() != null) ? MZmineCore + .getConfiguration() + .getDefaultColorPalette() : SimpleColorPalette.DEFAULT.get(Vision.DEUTERANOPIA); // fx colors - noInterFX = ColorsFX.getPositiveColor(vision); - possibleInterFX = ColorsFX.getNeutralColor(); - interFX = ColorsFX.getNegativeColor(vision); + noInterFX = palette.getPositiveColor(); + possibleInterFX = palette.getNeutralColor(); + interFX = palette.getNegativeColor(); // awt/swing colors or jfreechart - noInterSwing = Colors.getPositiveColor(vision); - possibleInterSwing = Colors.getNeutralColor(); - interSwing = Colors.getNegativeColor(vision); + noInterSwing = palette.getPositiveColorAWT(); + possibleInterSwing = palette.getNeutralColorAWT(); + interSwing = palette.getNegativeColorAWT(); // create cell factory statusColumn.setCellFactory(e -> new TableCell() { diff --git a/src/main/java/io/github/mzmine/modules/io/spectraldbsubmit/view/ScanSelectPanel.java b/src/main/java/io/github/mzmine/modules/io/spectraldbsubmit/view/ScanSelectPanel.java index f69a5d44f7e..f98cba786ab 100644 --- a/src/main/java/io/github/mzmine/modules/io/spectraldbsubmit/view/ScanSelectPanel.java +++ b/src/main/java/io/github/mzmine/modules/io/spectraldbsubmit/view/ScanSelectPanel.java @@ -18,6 +18,7 @@ package io.github.mzmine.modules.io.spectraldbsubmit.view; +import io.github.mzmine.util.color.SimpleColorPalette; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; @@ -157,9 +158,9 @@ public ScanSelectPanel(Scan[] scansEntry, ScanSortMode sort, double noiseLevel, public ScanSelectPanel(ScanSortMode sort, double noiseLevel, int minNumberOfSignals, String massListName) { // get colors for vision - Vision vision = MZmineCore.getConfiguration().getColorVision(); - colorUsedData = Colors.getPositiveColor(vision); - colorRemovedData = Colors.getNegativeColor(vision); + SimpleColorPalette palette = MZmineCore.getConfiguration().getDefaultColorPalette(); + colorUsedData = palette.getPositiveColorAWT(); + colorRemovedData = palette.getNegativeColorAWT(); setBorder(new LineBorder(UIManager.getColor("textHighlight"))); this.massListName = massListName; @@ -545,7 +546,6 @@ public void createChart() { .format("NO MS2 SPECTRA: 0 of {0} match the minimum criteria", getTotalScans())); error.setFont(new Font("Tahoma", Font.BOLD, 13)); error.setHorizontalAlignment(SwingConstants.CENTER); - error.setForeground(new Color(220, 20, 60)); pnChart.add(error, BorderLayout.CENTER); // } diff --git a/src/main/java/io/github/mzmine/modules/tools/kovats/KovatsIndexExtractionDialog.java b/src/main/java/io/github/mzmine/modules/tools/kovats/KovatsIndexExtractionDialog.java index baf085107e0..1a74fa00b90 100644 --- a/src/main/java/io/github/mzmine/modules/tools/kovats/KovatsIndexExtractionDialog.java +++ b/src/main/java/io/github/mzmine/modules/tools/kovats/KovatsIndexExtractionDialog.java @@ -18,6 +18,7 @@ package io.github.mzmine.modules.tools.kovats; +import io.github.mzmine.util.javafx.FxColorUtil; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; @@ -382,7 +383,9 @@ private void kovatsValuesChanged() { for (Entry e : parsedValues.entrySet()) { ValueMarker marker = new ValueMarker(e.getValue(), - Colors.getPositiveColor(MZmineCore.getConfiguration().getColorVision()), markerStroke); + MZmineCore.getConfiguration().getDefaultColorPalette() + .getPositiveColorAWT(), markerStroke); + marker.setLabelOffset(new RectangleInsets(10, 0, 0, 0)); marker.setLabelFont(new Font("Arial", Font.PLAIN, 12)); marker.setLabelBackgroundColor(Color.WHITE); diff --git a/src/main/java/io/github/mzmine/modules/visualization/chromatogram/TICPlot.java b/src/main/java/io/github/mzmine/modules/visualization/chromatogram/TICPlot.java index d08159a28df..db0153e31ef 100644 --- a/src/main/java/io/github/mzmine/modules/visualization/chromatogram/TICPlot.java +++ b/src/main/java/io/github/mzmine/modules/visualization/chromatogram/TICPlot.java @@ -18,12 +18,13 @@ package io.github.mzmine.modules.visualization.chromatogram; -import java.awt.BasicStroke; +import io.github.mzmine.gui.chartbasics.chartthemes.EStandardChartTheme; +import io.github.mzmine.gui.chartbasics.gui.javafx.EChartViewer; +import io.github.mzmine.gui.chartbasics.listener.ZoomHistory; +import io.github.mzmine.main.MZmineCore; import java.awt.Color; -import java.awt.Font; import java.awt.Paint; import java.awt.Shape; -import java.awt.Stroke; import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; @@ -31,10 +32,15 @@ import java.util.Arrays; import java.util.logging.Level; import java.util.logging.Logger; +import javafx.scene.Cursor; +import javafx.scene.control.ContextMenu; +import javafx.scene.control.MenuItem; +import javafx.scene.control.SeparatorMenuItem; +import javafx.stage.Stage; +import javafx.stage.Window; import org.jfree.chart.ChartFactory; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.block.BlockBorder; import org.jfree.chart.event.ChartProgressEvent; import org.jfree.chart.labels.XYItemLabelGenerator; import org.jfree.chart.labels.XYToolTipGenerator; @@ -46,18 +52,8 @@ import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.chart.title.LegendTitle; import org.jfree.chart.title.TextTitle; -import org.jfree.chart.ui.RectangleInsets; import org.jfree.data.general.DatasetUtils; import org.jfree.data.xy.XYDataset; -import io.github.mzmine.gui.chartbasics.gui.javafx.EChartViewer; -import io.github.mzmine.gui.chartbasics.listener.ZoomHistory; -import io.github.mzmine.main.MZmineCore; -import javafx.scene.Cursor; -import javafx.scene.control.ContextMenu; -import javafx.scene.control.MenuItem; -import javafx.scene.control.SeparatorMenuItem; -import javafx.stage.Stage; -import javafx.stage.Window; /** * TIC plot. @@ -72,45 +68,18 @@ public class TICPlot extends EChartViewer { // Zoom factor. private static final double ZOOM_FACTOR = 1.2; - // Plot colors for plotted files. - private static final Color[] PLOT_COLORS = {new Color(0, 0, 192), // blue - new Color(192, 0, 0), // red - new Color(0, 192, 0), // green - Color.MAGENTA, Color.CYAN, Color.ORANGE}; - - // Peak colours. - private static final Color[] PEAK_COLORS = {Color.PINK, Color.RED, Color.YELLOW, Color.BLUE, - Color.LIGHT_GRAY, Color.ORANGE, Color.GREEN}; - - // peak labels color - private static final Color LABEL_COLOR = Color.DARK_GRAY; - - // grid color - private static final Color GRID_COLOR = Color.LIGHT_GRAY; - - // Cross-hair (selection) color. - private static final Color CROSS_HAIR_COLOR = Color.GRAY; - - // Cross-hair stroke. - private static final Stroke CROSS_HAIR_STROKE = new BasicStroke(1.0F, BasicStroke.CAP_BUTT, - BasicStroke.JOIN_BEVEL, 1.0f, new float[] {5.0F, 3.0F}, 0.0F); + // peak labels color - moved to EStandardChartTheme ~SteffenHeu // data points shape private static final Shape DATA_POINT_SHAPE = new Ellipse2D.Double(-2.0, -2.0, 5.0, 5.0); - // Fonts. - private static final Font TITLE_FONT = new Font("SansSerif", Font.BOLD, 12); - private static final Font SUBTITLE_FONT = new Font("SansSerif", Font.PLAIN, 11); - private static final Font LEGEND_FONT = new Font("SansSerif", Font.PLAIN, 11); - - // Axis offsets. - private static final RectangleInsets AXIS_OFFSET = new RectangleInsets(5.0, 5.0, 5.0, 5.0); + // Fonts. - moved to EStandardChartTheme ~SteffenHeu // Axis margins. private static final double AXIS_MARGINS = 0.001; // Title margin. - private static final double TITLE_TOP_MARGIN = 5.0; +// private static final double TITLE_TOP_MARGIN = 5.0; // Plot type. private TICPlotType plotType; @@ -135,6 +104,8 @@ public class TICPlot extends EChartViewer { private MenuItem RemoveFilePopupMenu; + EStandardChartTheme theme; + /** * Indicates whether we have a request to show spectra visualizer for selected data point. Since * the selection (cross-hair) is updated with some delay after clicking with mouse, we cannot open @@ -159,6 +130,8 @@ public TICPlot() { false // generate URLs? )); + theme = MZmineCore.getConfiguration().getDefaultChartTheme(); + // Initialize. // visualizer = listener; labelsVisible = 1; @@ -180,52 +153,27 @@ public TICPlot() { // Initialize the chart by default time series chart from factory. chart = getChart(); - chart.setBackgroundPaint(Color.white); chart.getXYPlot().getRangeAxis().setLabel(yAxisLabel); // setChart(chart); - - // Title. chartTitle = chart.getTitle(); - chartTitle.setFont(TITLE_FONT); - chartTitle.setMargin(TITLE_TOP_MARGIN, 0.0, 0.0, 0.0); // Subtitle. chartSubTitle = new TextTitle(); - chartSubTitle.setFont(SUBTITLE_FONT); - chartSubTitle.setMargin(TITLE_TOP_MARGIN, 0.0, 0.0, 0.0); chart.addSubtitle(chartSubTitle); // Disable maximum size (we don't want scaling). // setMaximumDrawWidth(Integer.MAX_VALUE); // setMaximumDrawHeight(Integer.MAX_VALUE); - // Legend constructed by ChartFactory. - final LegendTitle legend = chart.getLegend(); - legend.setItemFont(LEGEND_FONT); - legend.setFrame(BlockBorder.NONE); - // Set the plot properties. plot = chart.getXYPlot(); - plot.setBackgroundPaint(Color.white); - plot.setAxisOffset(AXIS_OFFSET); plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD); - // Set grid properties. - plot.setDomainGridlinePaint(GRID_COLOR); - plot.setRangeGridlinePaint(GRID_COLOR); - // Set cross-hair (selection) properties. // if (listener instanceof TICVisualizerWindow) { - plot.setDomainCrosshairVisible(true); - plot.setRangeCrosshairVisible(true); - plot.setDomainCrosshairPaint(CROSS_HAIR_COLOR); - plot.setRangeCrosshairPaint(CROSS_HAIR_COLOR); - plot.setDomainCrosshairStroke(CROSS_HAIR_STROKE); - plot.setRangeCrosshairStroke(CROSS_HAIR_STROKE); - // Set cursor. setCursor(Cursor.CROSSHAIR); @@ -250,7 +198,6 @@ public TICPlot() { defaultRenderer.setDefaultShapesFilled(true); defaultRenderer.setDrawOutlines(false); defaultRenderer.setUseFillPaint(true); - defaultRenderer.setDefaultItemLabelPaint(LABEL_COLOR); // Set label generator final XYItemLabelGenerator labelGenerator = new TICItemLabelGenerator(this); @@ -343,8 +290,8 @@ public TICPlot() { ZoomHistory history = getZoomHistory(); if (history != null) history.clear(); - - MZmineCore.getConfiguration().getDefaultChartTheme().apply(this.getChart()); + +// theme.apply(this.getChart()); } // @Override @@ -546,9 +493,12 @@ public synchronized void addTICDataset(final XYDataset dataSet) { + "' does not have a compatible plotType. Expected '" + this.plotType.toString() + "'"); try { final TICPlotRenderer renderer = (TICPlotRenderer) defaultRenderer.clone(); -// final Color rendererColor = PLOT_COLORS[numOfDataSets % PLOT_COLORS.length]; +// SimpleColorPalette palette = MZmineCore.getConfiguration().getDefaultColorPalette(); +// final Color rendererColor = palette.getAWT(numOfDataSets % palette.size()); // renderer.setSeriesPaint(0, rendererColor); // renderer.setSeriesFillPaint(0, rendererColor); + renderer.setSeriesPaint(0, plot.getDrawingSupplier().getNextPaint()); + renderer.setSeriesFillPaint(0, plot.getDrawingSupplier().getNextFillPaint()); renderer.setSeriesShape(0, DATA_POINT_SHAPE); renderer.setDefaultItemLabelsVisible(labelsVisible == 1); addDataSetRenderer(dataSet, renderer); @@ -596,7 +546,7 @@ public synchronized void addLabelledPeakDataset(final XYDataset dataSet, final S // Add peak label renderer and data set. final XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(false, false); renderer.setDefaultItemLabelsVisible(labelsVisible == 2); - renderer.setDefaultItemLabelPaint(LABEL_COLOR); + renderer.setDefaultItemLabelPaint(theme.getItemLabelPaint()); addDataSetRenderer(dataSet, renderer); renderer.setDrawSeriesLineAsPath(true); renderer.setDefaultItemLabelGenerator(new XYItemLabelGenerator() { diff --git a/src/main/java/io/github/mzmine/modules/visualization/rawdataoverview/RawDataOverviewWindowController.java b/src/main/java/io/github/mzmine/modules/visualization/rawdataoverview/RawDataOverviewWindowController.java index d80daaf15e7..131c925d047 100644 --- a/src/main/java/io/github/mzmine/modules/visualization/rawdataoverview/RawDataOverviewWindowController.java +++ b/src/main/java/io/github/mzmine/modules/visualization/rawdataoverview/RawDataOverviewWindowController.java @@ -18,6 +18,8 @@ package io.github.mzmine.modules.visualization.rawdataoverview; +import io.github.mzmine.main.MZmineCore; +import io.github.mzmine.util.color.SimpleColorPalette; import java.awt.BasicStroke; import java.awt.Color; import org.jfree.chart.fx.interaction.ChartMouseEventFX; @@ -111,10 +113,10 @@ public void initialize(RawDataFile rawDataFile) { int numberOfScans = rawDataFile.getNumOfScans(); // set colors depending on vision - vision = MZminePreferences.colorPalettes.getValue(); - posColor = Colors.getPositiveColor(vision); - negColor = Colors.getNegativeColor(vision); - neuColor = Colors.getNeutralColor(); + SimpleColorPalette palette = MZmineCore.getConfiguration().getDefaultColorPalette(); + posColor = palette.getPositiveColorAWT(); + negColor = palette.getNegativeColorAWT(); + neuColor = palette.getNeutralColorAWT(); // add meta data rawDataLabel.setText(rawDataLabel.getText() + " " + rawDataFile.getName()); diff --git a/src/main/java/io/github/mzmine/modules/visualization/spectra/simplespectra/SpectraPlot.java b/src/main/java/io/github/mzmine/modules/visualization/spectra/simplespectra/SpectraPlot.java index 0a3ffa83a9f..be559ca564d 100644 --- a/src/main/java/io/github/mzmine/modules/visualization/spectra/simplespectra/SpectraPlot.java +++ b/src/main/java/io/github/mzmine/modules/visualization/spectra/simplespectra/SpectraPlot.java @@ -18,6 +18,7 @@ package io.github.mzmine.modules.visualization.spectra.simplespectra; +import io.github.mzmine.gui.chartbasics.chartthemes.EStandardChartTheme; import java.awt.Color; import java.awt.Font; import java.text.NumberFormat; @@ -69,13 +70,13 @@ public class SpectraPlot extends EChartViewer { // grid color private static final Color gridColor = Color.lightGray; - // title font - private static final Font titleFont = new Font("SansSerif", Font.BOLD, 12); - private static final Font subTitleFont = new Font("SansSerif", Font.PLAIN, 11); + // title font - moved to EStandardChartTheme ~SteffenHeu +// private static final Font titleFont = new Font("SansSerif", Font.BOLD, 12); +// private static final Font subTitleFont = new Font("SansSerif", Font.PLAIN, 11); private TextTitle chartTitle, chartSubTitle; - // legend - private static final Font legendFont = new Font("SansSerif", Font.PLAIN, 11); + // legend - moved to EStandardChartTheme ~SteffenHeu +// private static final Font legendFont = new Font("SansSerif", Font.PLAIN, 11); private boolean isotopesVisible = true, peaksVisible = true, itemLabelsVisible = true, dataPointsVisible = false; @@ -85,9 +86,11 @@ public class SpectraPlot extends EChartViewer { private int numOfDataSets = 0; // Spectra processing - DataPointProcessingController controller; + protected DataPointProcessingController controller; private boolean processingAllowed; + protected EStandardChartTheme theme; + public SpectraPlot() { this(false); } @@ -111,42 +114,26 @@ public SpectraPlot(boolean processingAllowed) { chart = getChart(); chart.setBackgroundPaint(Color.white); + plot = chart.getXYPlot(); + theme = MZmineCore.getConfiguration().getDefaultChartTheme(); + // title chartTitle = chart.getTitle(); - chartTitle.setMargin(5, 0, 0, 0); - chartTitle.setFont(titleFont); - chartSubTitle = new TextTitle(); - chartSubTitle.setFont(subTitleFont); - chartSubTitle.setMargin(5, 0, 0, 0); chart.addSubtitle(chartSubTitle); - // legend constructed by ChartFactory - LegendTitle legend = chart.getLegend(); - legend.setItemFont(legendFont); - legend.setFrame(BlockBorder.NONE); - // disable maximum size (we don't want scaling) // setMaximumDrawWidth(Integer.MAX_VALUE); // setMaximumDrawHeight(Integer.MAX_VALUE); // setMinimumDrawHeight(0); - // set the plot properties - plot = chart.getXYPlot(); - plot.setBackgroundPaint(Color.white); - plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0)); - // set rendering order plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD); - // set grid properties + // set grid properties - TODO: do we want gridlines in spectra? plot.setDomainGridlinePaint(gridColor); plot.setRangeGridlinePaint(gridColor); - // set crosshair (selection) properties - plot.setDomainCrosshairVisible(false); - plot.setRangeCrosshairVisible(false); - NumberFormat mzFormat = MZmineCore.getConfiguration().getMZFormat(); NumberFormat intensityFormat = MZmineCore.getConfiguration().getIntensityFormat(); @@ -205,17 +192,24 @@ public SpectraPlot(boolean processingAllowed) { * * FxMenuUtil.addMenuItem(popupMenu, "Set same range to all windows", masterPlot, * "SET_SAME_RANGE"); - * + * * popupMenu.addSeparator(); - * + * * FxMenuUtil.addMenuItem(popupMenu, "Add isotope pattern", masterPlot, "ADD_ISOTOPE_PATTERN"); * } */ // reset zoom history ZoomHistory history = getZoomHistory(); - if (history != null) + if (history != null) { history.clear(); + } + + theme.apply(chart); + + // set crosshair (selection) properties + plot.setDomainCrosshairVisible(false); + plot.setRangeCrosshairVisible(false); // set processingAllowed setProcessingAllowed(processingAllowed); @@ -284,7 +278,7 @@ public void setPlotMode(MassSpectrumType plotMode) { SpectraItemLabelGenerator labelGenerator = new SpectraItemLabelGenerator(this); newRenderer.setDefaultItemLabelGenerator(labelGenerator); newRenderer.setDefaultItemLabelsVisible(itemLabelsVisible); - newRenderer.setDefaultItemLabelPaint(labelsColor); + newRenderer.setDefaultItemLabelPaint(theme.getItemLabelPaint()); plot.setRenderer(0, newRenderer); @@ -386,7 +380,7 @@ public synchronized void addDataSet(XYDataset dataSet, Color color, boolean tran SpectraItemLabelGenerator labelGenerator = new SpectraItemLabelGenerator(this); newRenderer.setDefaultItemLabelGenerator(labelGenerator); newRenderer.setDefaultItemLabelsVisible(itemLabelsVisible); - newRenderer.setDefaultItemLabelPaint(labelsColor); + newRenderer.setDefaultItemLabelPaint(theme.getItemLabelPaint()); } else { newRenderer = new PeakRenderer(color, transparency); @@ -419,14 +413,14 @@ public synchronized void addDataSet(XYDataset dataSet, Color color, boolean tran // Add label generator for the dataset newRenderer.setDefaultItemLabelGenerator(labelGenerator); newRenderer.setDefaultItemLabelsVisible(itemLabelsVisible); - newRenderer.setDefaultItemLabelPaint(labelsColor); + newRenderer.setDefaultItemLabelPaint(theme.getItemLabelPaint()); } else { newRenderer = new PeakRenderer(color, transparency); // Add label generator for the dataset newRenderer.setDefaultItemLabelGenerator(labelGenerator); newRenderer.setDefaultItemLabelsVisible(itemLabelsVisible); - newRenderer.setDefaultItemLabelPaint(labelsColor); + newRenderer.setDefaultItemLabelPaint(theme.getItemLabelPaint()); } plot.setDataset(numOfDataSets, dataSet); diff --git a/src/main/java/io/github/mzmine/modules/visualization/spectra/simplespectra/SpectraVisualizerWindow.java b/src/main/java/io/github/mzmine/modules/visualization/spectra/simplespectra/SpectraVisualizerWindow.java index ced4d50c32f..3413b22e825 100644 --- a/src/main/java/io/github/mzmine/modules/visualization/spectra/simplespectra/SpectraVisualizerWindow.java +++ b/src/main/java/io/github/mzmine/modules/visualization/spectra/simplespectra/SpectraVisualizerWindow.java @@ -18,6 +18,8 @@ package io.github.mzmine.modules.visualization.spectra.simplespectra; +import io.github.mzmine.util.color.SimpleColorPalette; +import io.github.mzmine.util.javafx.FxColorUtil; import java.awt.Color; import java.io.File; import java.text.NumberFormat; @@ -101,11 +103,12 @@ public class SpectraVisualizerWindow extends Stage { FxIconUtil.loadImageFromResources("icons/DBSpectraIcon.png"); private static final Image sumFormulaIcon = FxIconUtil.loadImageFromResources("icons/search.png"); - public static final Color scanColor = new Color(0, 0, 192); - public static final Color peaksColor = Color.red; - public static final Color singlePeakColor = Color.magenta; - public static final Color detectedIsotopesColor = Color.magenta; - public static final Color predictedIsotopesColor = Color.green; + // initialize colors to some default before the color palette is loaded + public static Color scanColor = new Color(0, 0, 192); + public static Color peaksColor = Color.red; + public static Color singlePeakColor = Color.magenta; + public static Color detectedIsotopesColor = Color.magenta; + public static Color predictedIsotopesColor = Color.green; private final Scene mainScene; private final BorderPane mainPane; @@ -137,6 +140,8 @@ public SpectraVisualizerWindow(RawDataFile dataFile, boolean enableProcessing) { setTitle("Spectrum loading..."); this.dataFile = dataFile; + loadColorSettings(); + mainPane = new BorderPane(); mainScene = new Scene(mainPane); setScene(mainScene); @@ -270,6 +275,14 @@ public SpectraVisualizerWindow(RawDataFile dataFile) { this(dataFile, false); } + private void loadColorSettings() { + SimpleColorPalette p = MZmineCore.getConfiguration().getDefaultColorPalette(); + scanColor = FxColorUtil.fxColorToAWT(p.get(0)); + peaksColor = FxColorUtil.fxColorToAWT(p.getNextColor()); + singlePeakColor = FxColorUtil.fxColorToAWT(p.getNextColor()); + detectedIsotopesColor = FxColorUtil.fxColorToAWT(p.getNextColor()); + predictedIsotopesColor = FxColorUtil.fxColorToAWT(p.getNextColor()); + } public void loadRawData(Scan scan) { diff --git a/src/main/java/io/github/mzmine/modules/visualization/spectra/simplespectra/mirrorspectra/MirrorScanWindow.java b/src/main/java/io/github/mzmine/modules/visualization/spectra/simplespectra/mirrorspectra/MirrorScanWindow.java index 0debb2e8184..498ad8a1aba 100644 --- a/src/main/java/io/github/mzmine/modules/visualization/spectra/simplespectra/mirrorspectra/MirrorScanWindow.java +++ b/src/main/java/io/github/mzmine/modules/visualization/spectra/simplespectra/mirrorspectra/MirrorScanWindow.java @@ -1,22 +1,23 @@ /* * Copyright 2006-2020 The MZmine Development Team - * + * * This file is part of MZmine. - * + * * MZmine is free software; you can redistribute it and/or modify it under the terms of the GNU * General Public License as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. - * + * * MZmine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. - * + * * You should have received a copy of the GNU General Public License along with MZmine; if not, * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA */ package io.github.mzmine.modules.visualization.spectra.simplespectra.mirrorspectra; +import io.github.mzmine.util.color.SimpleColorPalette; import java.awt.BorderLayout; import java.awt.Color; import java.util.Arrays; @@ -46,7 +47,7 @@ /** * Creates a window with a mirror chart to compare to scans - * + * * @author Robin Schmid */ public class MirrorScanWindow extends JFrame { @@ -84,7 +85,7 @@ public void setScans(String labelA, double precursorMZA, double rtA, DataPoint[] /** * Set scan and mirror scan and create chart - * + * * @param scan * @param mirror */ @@ -109,7 +110,7 @@ public void setScans(Scan scan, Scan mirror, String labelA, String labelB) { /** * Based on a data base match to a spectral library - * + * * @param row * @param db */ @@ -134,11 +135,11 @@ public void setScans(SpectralDBPeakIdentity db) { return; // get colors for vision - Vision vision = MZmineCore.getConfiguration().getColorVision(); + SimpleColorPalette palette = MZmineCore.getConfiguration().getDefaultColorPalette(); // colors for the different DataPointsTags: - final Color[] colors = new Color[] {Color.black, // black = filtered - Colors.getNegativeColor(vision), // unaligned - Colors.getPositiveColor(vision) // aligned + final Color[] colors = new Color[]{Color.black, // black = filtered + palette.getNegativeColorAWT(), // unaligned + palette.getPositiveColorAWT()// aligned }; // scan a diff --git a/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/ColorPaletteCell.java b/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/ColorPaletteCell.java index 6b5e373bc02..42b39f1a3b4 100644 --- a/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/ColorPaletteCell.java +++ b/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/ColorPaletteCell.java @@ -1,16 +1,16 @@ /* * Copyright 2006-2020 The MZmine Development Team - * + * * This file is part of MZmine. - * + * * MZmine is free software; you can redistribute it and/or modify it under the terms of the GNU * General Public License as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. - * + * * MZmine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. - * + * * You should have received a copy of the GNU General Public License along with MZmine; if not, * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA @@ -21,6 +21,8 @@ import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; +import javafx.geometry.Insets; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import io.github.mzmine.util.color.SimpleColorPalette; import javafx.geometry.Pos; @@ -37,29 +39,31 @@ import javafx.scene.layout.HBox; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; +import org.graphstream.stream.file.FileSourceGEXF.GEXFConstants.COLORAttribute; /** * Implementation of ListCell to display color palettes and select between them. - * - * @author SteffenHeu steffen.heuckeroth@gmx.de / s_heuc03@uni-muenster.de * + * @author SteffenHeu steffen.heuckeroth@gmx.de / s_heuc03@uni-muenster.de */ public class ColorPaletteCell extends ListCell { private final static int MAX_PREVIEW_COLORS = 15; private static final Color BORDER_CLR = Color.DARKGRAY; private static final Color TEXT_CLR = Color.BLACK; + private static final Color STROKE_CLR = Color.BLACK; + private static final double STROKE_WIDTH = 0.5; private static final Logger logger = Logger.getLogger(ColorPaletteCell.class.getName()); private final double height; private final List rects; + private final Rectangle positiveRect, negativeRect, neutralRect; private final FlowPane clrPane; - private final Label label; + private final Label lblName; private final GridPane pane; /** - * * @param h The height of the combo box. */ public ColorPaletteCell(double h) { @@ -73,39 +77,63 @@ public ColorPaletteCell(double h) { clrPane.setMaxHeight(h); clrPane.setMaxWidth(MAX_PREVIEW_COLORS * h); clrPane.setPrefHeight(h); - clrPane.setPrefWidth(MAX_PREVIEW_COLORS * h); +// clrPane.setPrefWidth(MAX_PREVIEW_COLORS * h); rects = new ArrayList(); - label = new Label(); - label.setTextFill(TEXT_CLR); + positiveRect = makeRect(Color.TRANSPARENT); + negativeRect = makeRect(Color.TRANSPARENT); + neutralRect = makeRect(Color.TRANSPARENT); + lblName = new Label(); + lblName.setTextFill(TEXT_CLR); // nasty way to align the palettes in the dropdown menu - label.setMinWidth(80); - label.setMaxWidth(150); - label.setPrefWidth(150); - label.setAlignment(Pos.CENTER_LEFT); + lblName.setMinWidth(80); + lblName.setMaxWidth(110); + lblName.setPrefWidth(110); + lblName.setAlignment(Pos.CENTER_LEFT); // palette in the second row... pane = new GridPane(); pane.setBorder(new Border(new BorderStroke(BORDER_CLR, BorderStrokeStyle.SOLID, new CornerRadii(2.0), new BorderWidths(1.0)))); - pane.add(clrPane, 0, 1); - pane.add(label, 0, 0); + pane.setVgap(3); + pane.setHgap(5); + + pane.add(lblName, 0, 0); + pane.add(clrPane, 0, 1, 7, 1); + + Label label = new Label("Pos.:"); + label.setTextFill(TEXT_CLR); + pane.add(label, 1, 0); + pane.add(positiveRect, 2, 0); + + label = new Label("Neu.:"); + label.setTextFill(TEXT_CLR); + pane.add(label, 3, 0); + pane.add(neutralRect, 4, 0); + + label = new Label("Neg.:"); + label.setTextFill(TEXT_CLR); + pane.add(label, 5, 0); + pane.add(negativeRect, 6, 0); } private void setRectangles(@Nullable SimpleColorPalette palette) { rects.clear(); - if (palette == null || palette.isEmpty()) + if (palette == null || palette.isEmpty()) { return; + } for (int i = 0; i < palette.size(); i++) { Color clr = palette.get(i); - Rectangle rect = new Rectangle(height, height); - rect.setFill(clr); + Rectangle rect = makeRect(clr); rects.add(rect); } + positiveRect.setFill(palette.getPositiveColor()); + neutralRect.setFill(palette.getNeutralColor()); + negativeRect.setFill(palette.getNegativeColor()); } @Override @@ -117,9 +145,17 @@ protected void updateItem(@Nullable SimpleColorPalette palette, boolean empty) { } else { setRectangles(palette); clrPane.getChildren().clear(); - label.setText(palette.getName()); + lblName.setText(palette.getName()); clrPane.getChildren().addAll(rects); setGraphic(pane); } } + + protected Rectangle makeRect(@Nonnull Color clr) { + Rectangle rect = new Rectangle(height - STROKE_WIDTH * 2, height - STROKE_WIDTH * 2); + rect.setFill(clr); + rect.setStroke(STROKE_CLR); + rect.setStrokeWidth(STROKE_WIDTH); + return rect; + } }; diff --git a/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/ColorPaletteComponent.java b/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/ColorPaletteComponent.java index 9c93293057a..16a124cb230 100644 --- a/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/ColorPaletteComponent.java +++ b/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/ColorPaletteComponent.java @@ -25,11 +25,12 @@ import io.github.mzmine.util.color.Vision; import java.util.List; import java.util.logging.Logger; -import javafx.collections.ListChangeListener; +import javafx.geometry.Insets; import javafx.scene.control.Button; import javafx.scene.control.ComboBox; import javafx.scene.layout.FlowPane; import javafx.scene.layout.GridPane; +import javafx.scene.paint.Color; /** * Gui component for a SimpleColorPalette. Allows editing and selection of different palettes. @@ -40,13 +41,12 @@ public class ColorPaletteComponent extends GridPane { private static final Logger logger = Logger.getLogger(ColorPaletteComponent.class.getName()); - protected ComboBox box; - protected Button addPalette; - protected Button editPalette; - protected Button deletePalette; - protected Button duplicatePalette; - protected Button addDefault; - protected FlowPane pnButtons; + protected final ComboBox box; + protected final Button btnAddPalette; + protected final Button btnEditPalette; + protected final Button btnDeletePalette; + protected final Button duplicatePalette; + protected final FlowPane pnButtons; public ColorPaletteComponent() { super(); @@ -57,18 +57,16 @@ public ColorPaletteComponent() { return new ColorPaletteCell(17); }); box.setButtonCell(new ColorPaletteCell(15)); - box.setMinHeight(35); - box.setMaxHeight(35); + box.setMinHeight(37); + box.setMaxHeight(37); - box.getItems().addListener((ListChangeListener) e -> - logger.info("Item added" + e.toString())); - - addPalette = new Button("New"); - addPalette.setOnAction(e -> { + btnAddPalette = new Button("New"); + btnAddPalette.setOnAction(e -> { SimpleColorPalette pal = new SimpleColorPalette(); - box.getItems().add(pal); -// box.getSelectionModel().select(box.getItems().indexOf(pal)); -// box.setValue(pal); + pal.setName("New palette"); + pal.add(Color.BLACK); + addPalette(pal); + setValue(pal); }); duplicatePalette = new Button("Duplicate"); @@ -80,18 +78,20 @@ public ColorPaletteComponent() { } SimpleColorPalette newPal = pal.clone(); - newPal.setName(pal.getName() + " (cpy)"); + newPal.setName(pal.getName() + " (copy)"); if (addPalette(newPal)) { box.setValue(newPal); } - logger.info("index of new value: " + box.getItems().indexOf(newPal)); - logger.info("hash - old: " + pal.hashCode() + " new: " + newPal.hashCode()); - }); - editPalette = new Button("Edit"); - editPalette.setOnAction(e -> { + btnEditPalette = new Button("Edit"); + btnEditPalette.setOnAction(e -> { + if (SimpleColorPalette.DEFAULT.values().contains(box.getValue())) { + MZmineCore.getDesktop().displayErrorMessage("Cannot edit default palette."); + return; + } + ColorPalettePickerDialog d = new ColorPalettePickerDialog(box.getValue().clone()); d.show(); @@ -106,10 +106,9 @@ public ColorPaletteComponent() { if (!addPalette(newVal)) { addPalette(oldVal); setValue(oldVal); + d.show(); MZmineCore.getDesktop().displayErrorMessage( "Cannot add duplicates. Palette with same name and colors already exists."); - - d.show(); // return; } @@ -118,8 +117,13 @@ public ColorPaletteComponent() { }); }); - deletePalette = new Button("Delete"); - deletePalette.setOnAction(e -> { + btnDeletePalette = new Button("Delete"); + btnDeletePalette.setOnAction(e -> { + if (SimpleColorPalette.DEFAULT.values().contains(box.getValue())) { + MZmineCore.getDesktop().displayErrorMessage("Cannot delete default palette."); + return; + } + if (box.getItems().size() <= 1) { logger.warning( "Cannot remove palettes. Only 1 palette present. Please add a new palette first."); @@ -129,20 +133,15 @@ public ColorPaletteComponent() { box.setValue(box.getItems().get(0)); }); - addDefault = new Button("Add default"); - addDefault.setOnAction(e -> { - SimpleColorPalette pal; - pal = new SimpleColorPalette(ColorsFX.getSevenColorPalette(Vision.DEUTERANOPIA, true)); - pal.setName("Deuternopia"); - addPalette(pal); - }); - pnButtons = new FlowPane(); pnButtons.getChildren() - .addAll(addPalette, duplicatePalette, editPalette, deletePalette, addDefault); + .addAll(btnAddPalette, duplicatePalette, btnEditPalette, btnDeletePalette); add(box, 0, 0); add(pnButtons, 0, 1); + +// getChildren().forEach(c -> GridPane.setMargin(c, new Insets(5.0, 0.0, 5.0, 0.0))); + pnButtons.getChildren().forEach(c -> FlowPane.setMargin(c, new Insets(5.0, 5.0, 0.0, 0.0))); } public SimpleColorPalette getValue() { @@ -186,6 +185,13 @@ protected boolean itemsContainDefaultPalette() { return false; } + /** + * Palettes should be added via this method and not via {@link ComboBox#getItems#add()}, since this + * method provides additional checks for duplicates. + * + * @param pal + * @return + */ public boolean addPalette(SimpleColorPalette pal) { if (box.getItems().contains(pal)) { logger.fine("Cannot add duplicates. A palette with same name and colors already exists."); diff --git a/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/ColorPaletteParameter.java b/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/ColorPaletteParameter.java index 8aa138bdefc..6cf2780f930 100644 --- a/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/ColorPaletteParameter.java +++ b/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/ColorPaletteParameter.java @@ -1,16 +1,16 @@ /* * Copyright 2006-2020 The MZmine Development Team - * + * * This file is part of MZmine. - * + * * MZmine is free software; you can redistribute it and/or modify it under the terms of the GNU * General Public License as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. - * + * * MZmine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. - * + * * You should have received a copy of the GNU General Public License along with MZmine; if not, * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA @@ -18,9 +18,12 @@ package io.github.mzmine.parameters.parametertypes.colorpalette; +import io.github.mzmine.util.color.Vision; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.logging.Logger; +import javax.annotation.Nonnull; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; @@ -29,9 +32,8 @@ /** * User parameter for color palette selection. - * - * @author SteffenHeu steffen.heuckeroth@gmx.de / s_heuc03@uni-muenster.de * + * @author SteffenHeu steffen.heuckeroth@gmx.de / s_heuc03@uni-muenster.de */ public class ColorPaletteParameter implements UserParameter { @@ -39,6 +41,8 @@ public class ColorPaletteParameter private static final String PALETTE_ELEMENT = "palette"; private static final String SELECTED_INDEX = "selected"; + private static final Logger logger = Logger.getLogger(ColorPaletteParameter.class.getName()); + protected String name; protected String descr; protected SimpleColorPalette value; @@ -47,7 +51,7 @@ public class ColorPaletteParameter public ColorPaletteParameter(String name, String descr) { this.name = name; this.descr = descr; - value = new SimpleColorPalette(); + value = SimpleColorPalette.DEFAULT.get(Vision.DEUTERANOPIA); palettes = new ArrayList<>(); palettes.add(value); } @@ -64,14 +68,16 @@ public SimpleColorPalette getValue() { @Override public void setValue(SimpleColorPalette newValue) { - if (!palettes.contains(newValue)) + if (!palettes.contains(newValue)) { palettes.add(newValue); + logger.fine("Did not contain palette " + newValue.toString() + ". Value was added."); + } value = newValue; } @Override public boolean checkValue(Collection errorMessages) { - if(getValue() == null || !getValue().isValidPalette()) { + if (getValue() == null || !getValue().isValid()) { errorMessages.add("Not enough colors in color palette " + getName()); return false; } @@ -86,10 +92,22 @@ public void loadValueFromXML(Element xmlElement) { palettes.clear(); for (int i = 0; i < childs.getLength(); i++) { Element p = (Element) childs.item(i); - if (p.getNodeName().equals(PALETTE_ELEMENT)) + if (p.getNodeName().equals(PALETTE_ELEMENT)) { palettes.add(SimpleColorPalette.createFromXML(p)); + } } + setValue(palettes.get(selected)); + + int index = 0; + for (SimpleColorPalette def : SimpleColorPalette.DEFAULT.values()) { + if (!palettes.contains(def)) { + palettes.add(index, def); + logger.info("Loaded color palettes did not contain default " + def.getName() + + " palette. Adding..."); + } + index++; + } } @Override @@ -114,12 +132,6 @@ public String getDescription() { public ColorPaletteComponent createEditingComponent() { ColorPaletteComponent comp = new ColorPaletteComponent(); -// for (Vision v : Vision.values()) { -// palettes.add(new SimpleColorPalette(ColorsFX.getSevenColorPalette(v, true))); -// } -// -// comp.setPalettes(palettes); - return comp; } @@ -131,15 +143,27 @@ public void setValueFromComponent(ColorPaletteComponent component) { @Override public void setValueToComponent(ColorPaletteComponent component, SimpleColorPalette newValue) { - component.setValue(newValue); component.setPalettes(palettes); + component.setValue(newValue); } - protected List getPalettes() { + protected @Nonnull + List getPalettes() { return palettes; } - protected void setPalettes(List palettes) { + protected void setPalettes(@Nonnull List palettes) { + + int index = 0; + for (SimpleColorPalette def : SimpleColorPalette.DEFAULT.values()) { + if (!palettes.contains(def)) { + palettes.add(index, def); + logger.info("Loaded color palettes did not contain default " + def.getName() + + " palette. Adding..."); + } + index++; + } + this.palettes = palettes; } @@ -147,11 +171,11 @@ protected void setPalettes(List palettes) { public UserParameter cloneParameter() { ColorPaletteParameter clone = new ColorPaletteParameter(name, descr); clone.setValue(getValue().clone()); - + List pals = new ArrayList<>(); palettes.forEach(p -> pals.add(p.clone())); clone.setPalettes(pals); - + return clone; } diff --git a/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/ColorPalettePickerDialog.java b/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/ColorPalettePickerDialog.java index aa1d7e93d7c..9767f667445 100644 --- a/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/ColorPalettePickerDialog.java +++ b/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/ColorPalettePickerDialog.java @@ -1,16 +1,16 @@ /* * Copyright 2006-2020 The MZmine Development Team - * + * * This file is part of MZmine. - * + * * MZmine is free software; you can redistribute it and/or modify it under the terms of the GNU * General Public License as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. - * + * * MZmine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. - * + * * You should have received a copy of the GNU General Public License along with MZmine; if not, * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA @@ -18,41 +18,56 @@ package io.github.mzmine.parameters.parametertypes.colorpalette; +import static javafx.scene.layout.Region.USE_COMPUTED_SIZE; + +import io.github.mzmine.main.MZmineCore; +import java.util.logging.Logger; +import javafx.geometry.HPos; +import javafx.geometry.Insets; +import javafx.scene.control.ButtonBar; +import javafx.scene.control.ScrollPane; +import javafx.scene.layout.ColumnConstraints; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.Priority; +import javafx.scene.paint.Color; import javax.annotation.Nonnull; import javax.annotation.Nullable; import io.github.mzmine.util.ExitCode; import io.github.mzmine.util.color.SimpleColorPalette; -import javafx.geometry.Orientation; -import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.ColorPicker; import javafx.scene.control.Label; -import javafx.scene.control.Separator; import javafx.scene.control.TextField; import javafx.scene.layout.BorderPane; -import javafx.scene.layout.FlowPane; import javafx.stage.Stage; /** * Dialog to pick colors for a color palette. - * - * @author SteffenHeu steffen.heuckeroth@gmx.de / s_heuc03@uni-muenster.de * + * @author SteffenHeu steffen.heuckeroth@gmx.de / s_heuc03@uni-muenster.de */ public class ColorPalettePickerDialog extends Stage { + private static final Logger logger = Logger.getLogger(ColorPalettePickerDialog.class.getName()); + protected ExitCode exitCode; - protected BorderPane pnSuper; - protected BorderPane pnPicker; - protected FlowPane pnButtons; + // protected BorderPane pnSuper; + // protected BorderPane pnPicker; + protected BorderPane pnMain; + protected ScrollPane pnWrapParam; + protected GridPane pnParam; + protected ButtonBar pnButtons; protected ColorPalettePreviewField pnPalette; protected Button btnAccept; protected Button btnCancel; protected Button btnAddColor; protected Button btnRemoveColor; - protected ColorPicker colorPicker; + protected ColorPicker colorPickerPalette; + protected ColorPicker colorPickerPositive; + protected ColorPicker colorPickerNegative; + protected ColorPicker colorPickerNeutral; protected TextField txtName; protected SimpleColorPalette palette; @@ -61,41 +76,105 @@ public class ColorPalettePickerDialog extends Stage { public ColorPalettePickerDialog(@Nullable SimpleColorPalette palette) { super(); + pnMain = new BorderPane(); + pnWrapParam = new ScrollPane(); + pnButtons = new ButtonBar(); + + pnWrapParam.setPadding(new Insets(10.0)); + + setTitle("Editing of color palette " + palette.getName()); + + Scene scene = new Scene(pnMain); + setScene(scene); + scene.getStylesheets() + .addAll(MZmineCore.getDesktop().getMainWindow().getScene().getStylesheets()); + exitCode = ExitCode.CANCEL; - if (palette == null) + if (palette == null) { palette = new SimpleColorPalette(); + } this.palette = palette; + selected = 0; // Create gui components - pnSuper = new BorderPane(); - pnPicker = new BorderPane(); + pnParam = new GridPane(); pnPalette = new ColorPalettePreviewField(palette); - pnButtons = new FlowPane(); - btnAccept = new Button("Accept"); + btnAccept = new Button("OK"); btnCancel = new Button("Cancel"); - btnAddColor = new Button("Add color"); - btnRemoveColor = new Button("Remove color"); - colorPicker = new ColorPicker(); + btnAddColor = new Button("Add"); + btnRemoveColor = new Button("Remove"); + colorPickerPalette = new ColorPicker(); + colorPickerPositive = new ColorPicker(); + colorPickerNegative = new ColorPicker(); + colorPickerNeutral = new ColorPicker(); txtName = new TextField(palette.getName()); + txtName.setMaxWidth(250); // organize gui components - pnSuper.setTop(pnPalette); - pnSuper.setCenter(pnPicker); - pnSuper.setBottom(pnButtons); - pnPicker.setCenter(colorPicker); - pnPicker.setBottom(new FlowPane(new Label("Name "), txtName)); - pnButtons.getChildren().addAll(btnAddColor, btnRemoveColor, new Separator(Orientation.VERTICAL), - btnAccept, btnCancel); - pnButtons.setAlignment(Pos.TOP_CENTER); - - // colorPicker.getStyleClass().add("split-button"); - colorPicker.setOnAction(e -> { - if (colorPicker.getValue() != null) { + pnParam.add(new Label("Name"), 0, 0); + pnParam.add(txtName, 1, 0, 4, 1); + + pnParam.add(new Label("Palette"), 0, 1); + pnParam.add(pnPalette, 1, 1, 4, 1); + + pnParam.add(new Label("Color"), 0, 2); + pnParam.add(colorPickerPalette, 1, 2, 1, 1); + pnParam.add(btnAddColor, 3, 2); + pnParam.add(btnRemoveColor, 4, 2); + + pnParam.add(new Label("Positive"), 0, 3); + pnParam.add(colorPickerPositive, 1, 3, 1, 1); + pnParam.add(new Label("Neutral"), 0, 4); + pnParam.add(colorPickerNeutral, 1, 4, 1, 1); + pnParam.add(new Label("Negative"), 0, 5); + pnParam.add(colorPickerNegative, 1, 5, 1, 1); + +// ColumnConstraints columnConstraints = new ColumnConstraints(USE_COMPUTED_SIZE, +// USE_COMPUTED_SIZE, USE_COMPUTED_SIZE, Priority.NEVER, HPos.LEFT, true); +// pnParam.getColumnConstraints() +// .addAll(columnConstraints, columnConstraints, columnConstraints, columnConstraints, +// columnConstraints); + + pnButtons.getButtons().add(btnCancel); + pnButtons.getButtons().add(btnAccept); + pnButtons.setPadding(new Insets(10.0)); + + // color picker actions + colorPickerPalette.setOnAction(e -> { + if (colorPickerPalette.getValue() != null) { int selected = pnPalette.getSelected(); - this.palette.set(selected, colorPicker.getValue()); + if (selected >= 0 && selected < this.palette.size()) { + this.palette.set(selected, colorPickerPalette.getValue()); + } } }); + colorPickerPalette.setValue(palette.get(pnPalette.getSelected())); + + colorPickerPositive.setOnAction(e -> { + if (colorPickerPositive.getValue() != null) { + this.palette.setPositiveColor(colorPickerPositive.getValue()); + } + }); + colorPickerPositive.setValue(palette.getPositiveColor()); + + colorPickerNeutral.setOnAction(e -> { + if (colorPickerNeutral.getValue() != null) { + this.palette.setNeutralColor(colorPickerNeutral.getValue()); + } + }); + colorPickerNeutral.setValue(palette.getNeutralColor()); + + colorPickerNegative.setOnAction(e -> { + if (colorPickerNegative.getValue() != null) { + this.palette.setNegativeColor(colorPickerNegative.getValue()); + } + }); + colorPickerNegative.setValue(palette.getNegativeColor()); + + pnPalette.addListener((Color newColor, int newIndex) -> { + colorPickerPalette.setValue(newColor); + }); // set button actions btnAddColor.setOnAction(e -> btnAddColorAction()); @@ -103,26 +182,50 @@ public ColorPalettePickerDialog(@Nullable SimpleColorPalette palette) { btnAccept.setOnAction(e -> hideWindow(ExitCode.OK)); btnCancel.setOnAction(e -> hideWindow(ExitCode.CANCEL)); - Scene scene = new Scene(pnSuper); - setScene(scene); + // add panels together + pnWrapParam.setContent(pnParam); + pnMain.setCenter(pnWrapParam); + pnParam.getChildren().forEach(c -> GridPane.setMargin(c, new Insets(5.0, 0.0, 5.0, 5.0))); + pnMain.setBottom(pnButtons); + + // size is computed when shown, so show here and set minimum size to the computed one + show(); + this.setMinHeight(getHeight()); + this.setMinWidth(getWidth()); } private void btnAddColorAction() { - if(palette.size() == 0) + if (palette.size() == 0) { this.setHeight(this.getHeight() + 17); - palette.add(colorPicker.getValue()); + } + palette.add(colorPickerPalette.getValue()); // pnPalette.updatePreview(); } private void btnRemoveColorAction() { - palette.remove(pnPalette.getSelected()); -// pnPalette.updatePreview(); + if (palette.size() > 0) { + palette.remove(pnPalette.getSelected()); + } } private void hideWindow(ExitCode exitCode) { + if (exitCode == ExitCode.CANCEL) { + hide(); + this.exitCode = exitCode; + return; + } + + if (!palette.isValid()) { + MZmineCore.getDesktop().displayErrorMessage("Current color palette is not valid.\n" + + "Does it contain enough colors? The minimum amount of colors is 3."); + return; + } + String name = txtName.getText(); - if(name == null || name == "") - name = "unnamed"; + if (name == null || name == "" || name.replaceAll("\\s+", "").equals("")) { + MZmineCore.getDesktop().displayErrorMessage("Please set a name for the color palette."); + return; + } palette.setName(name); this.exitCode = exitCode; hide(); @@ -132,7 +235,8 @@ public ExitCode getExitCode() { return exitCode; } - public @Nonnull SimpleColorPalette getPalette() { + public @Nonnull + SimpleColorPalette getPalette() { return palette; } } diff --git a/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/ColorPalettePreviewField.java b/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/ColorPalettePreviewField.java index 32de525b098..a832ef584ad 100644 --- a/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/ColorPalettePreviewField.java +++ b/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/ColorPalettePreviewField.java @@ -1,16 +1,16 @@ /* * Copyright 2006-2020 The MZmine Development Team - * + * * This file is part of MZmine. - * + * * MZmine is free software; you can redistribute it and/or modify it under the terms of the GNU * General Public License as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. - * + * * MZmine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. - * + * * You should have received a copy of the GNU General Public License along with MZmine; if not, * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA @@ -18,95 +18,89 @@ package io.github.mzmine.parameters.parametertypes.colorpalette; +import io.github.mzmine.util.javafx.DraggableRectangle; +import io.github.mzmine.util.javafx.DraggableRectangleContainer; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; import io.github.mzmine.util.color.SimpleColorPalette; import javafx.collections.ListChangeListener; import javafx.geometry.Point2D; +import javafx.scene.Parent; +import javafx.scene.image.WritableImage; +import javafx.scene.input.ClipboardContent; +import javafx.scene.input.Dragboard; +import javafx.scene.input.TransferMode; import javafx.scene.layout.FlowPane; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; /** * A pane showing a color palette and allowing the selection of single colors within the palette. - * - * @author SteffenHeu steffen.heuckeroth@gmx.de / s_heuc03@uni-muenster.de * + * @author SteffenHeu steffen.heuckeroth@gmx.de / s_heuc03@uni-muenster.de */ -public class ColorPalettePreviewField extends FlowPane { +public class ColorPalettePreviewField extends FlowPane implements DraggableRectangleContainer { private static final Logger logger = Logger.getLogger(ColorPalettePreviewField.class.getName()); - private static final int RECT_HEIGHT = 17; - private static final Color OUTLINE_CLR = Color.BLACK; + private static final int RECT_HEIGHT = 18; + private static final Color STROKE_CLR_SELECTED = Color.WHITE; + private static final Color STROKE_CLR_DEFAULT = Color.BLACK; + private static final double STROKE_WIDTH = 0.5; protected final List rects; protected SimpleColorPalette palette; protected int selected; - + + protected List listeners; + protected boolean validDrag; public ColorPalettePreviewField(SimpleColorPalette palette) { super(); - rects = new ArrayList(); - setMaxWidth(400); + rects = new ArrayList<>(); + listeners = new ArrayList<>(); setPalette(palette); - + + setMinWidth(RECT_HEIGHT * 10); + setMaxWidth(RECT_HEIGHT * 20); + setPrefWidth(palette.size() * RECT_HEIGHT); + validDrag = false; - - palette.addListener((ListChangeListener) c -> updatePreview()); + + palette.addListener((ListChangeListener) c -> { + while (c.next()) { + this.setPrefWidth(palette.size() * RECT_HEIGHT); + if (c.wasRemoved() && selected >= palette.size()) { + selected = palette.size() - 1; + } + } + updatePreview(); + }); } private void setRectangles() { rects.clear(); - if (palette == null || palette.isEmpty()) + if (palette == null || palette.isEmpty()) { return; + } for (int i = 0; i < palette.size(); i++) { Color clr = palette.get(i); - Rectangle rect = new Rectangle(RECT_HEIGHT, RECT_HEIGHT); + Rectangle rect = new DraggableRectangle(RECT_HEIGHT - STROKE_WIDTH / 2, + RECT_HEIGHT - STROKE_WIDTH / 2); + + rects.add(rect); + rect.setFill(clr); - -// rect.setOnMouseClicked(e -> { -// if (e.getClickCount() == 1) { -// setSelected(rect); -// } -// }); + rect.setStroke(STROKE_CLR_DEFAULT); + rect.setStrokeWidth(STROKE_WIDTH); rect.setOnMousePressed(e -> { - rect.setOpacity(rect.getOpacity() / 2); - setSelected(rect); - }); - - rect.setOnMouseDragged(e -> { - validDrag = true; - }); - - rect.setOnMouseReleased(e -> { - rect.setOpacity(rect.getOpacity() * 2); - - if(!validDrag) - return; - - Point2D exit = new Point2D(e.getSceneX(), e.getSceneY()); - - double x = this.sceneToLocal(exit).getX(); - int newIndex = (int) (x / RECT_HEIGHT + .5); - - // we just have to move the color, the listener will update the preview - palette.moveColor(getSelected(), newIndex); setSelected(rect); - validDrag = false; }); - - rects.add(rect); - } - - if (selected < rects.size() && selected >= 0) { - rects.get(selected).setStroke(OUTLINE_CLR); - rects.get(selected).setStrokeWidth(1.0); } } @@ -115,8 +109,13 @@ private void setSelected(Rectangle rect) { } private void setSelected(int i) { + if (i < 0 || i >= palette.size()) { + return; + } this.selected = i; - updatePreview(); + rects.forEach(r -> r.setStroke(STROKE_CLR_DEFAULT)); + rects.get(i).setStroke(STROKE_CLR_SELECTED); + listeners.forEach(l -> l.selectionChanged(palette.get(getSelected()), getSelected())); } public int getSelected() { @@ -127,6 +126,7 @@ public void updatePreview() { setRectangles(); getChildren().clear(); getChildren().addAll(rects); + setSelected(selected); } public SimpleColorPalette getPalette() { @@ -137,4 +137,28 @@ public void setPalette(SimpleColorPalette palette) { this.palette = palette; updatePreview(); } + + public boolean addListener(SelectionChangeListener listener) { + return listeners.add(listener); + } + + public boolean removeListener(SelectionChangeListener listener) { + return listeners.remove(listener); + } + + /** + * When a rectangle is drag and dropped this method is called by the rectangles, the actual moving + * is done here. + * + * @param oldIndex + * @param newIndex + */ + @Override + public void moveRectangle(int oldIndex, int newIndex) { + newIndex = palette.moveColor(oldIndex, newIndex); + if (newIndex != -1) { + updatePreview(); + setSelected(newIndex); + } + } } diff --git a/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/SelectionChangeListener.java b/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/SelectionChangeListener.java new file mode 100644 index 00000000000..d3bb5ea2ada --- /dev/null +++ b/src/main/java/io/github/mzmine/parameters/parametertypes/colorpalette/SelectionChangeListener.java @@ -0,0 +1,28 @@ +/* + * Copyright 2006-2020 The MZmine Development Team + * + * This file is part of MZmine. + * + * MZmine is free software; you can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * MZmine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with MZmine; if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + + +package io.github.mzmine.parameters.parametertypes.colorpalette; + +import java.util.EventListener; +import javafx.scene.paint.Color; + +public interface SelectionChangeListener extends EventListener { + + void selectionChanged(Color newColor, int newIndex); +} diff --git a/src/main/java/io/github/mzmine/util/color/ColorPaletteChangeEventType.java b/src/main/java/io/github/mzmine/util/color/ColorPaletteChangeEventType.java new file mode 100644 index 00000000000..de44f19669e --- /dev/null +++ b/src/main/java/io/github/mzmine/util/color/ColorPaletteChangeEventType.java @@ -0,0 +1,25 @@ +/* + * Copyright 2006-2020 The MZmine Development Team + * + * This file is part of MZmine. + * + * MZmine is free software; you can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * MZmine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with MZmine; if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + + +package io.github.mzmine.util.color; + +public enum ColorPaletteChangeEventType { + LIST_PERMUTED, LIST_ADDED, LIST_REMOVED, POSITIVE_MARKER_UPDATED, NEUTRAL_MARKER_UPDATED, + NEGATIVE_MARKER_UPDATED; +} diff --git a/src/main/java/io/github/mzmine/util/color/ColorPaletteChangedEvent.java b/src/main/java/io/github/mzmine/util/color/ColorPaletteChangedEvent.java new file mode 100644 index 00000000000..4e4f0f478cc --- /dev/null +++ b/src/main/java/io/github/mzmine/util/color/ColorPaletteChangedEvent.java @@ -0,0 +1,108 @@ +/* + * Copyright 2006-2020 The MZmine Development Team + * + * This file is part of MZmine. + * + * MZmine is free software; you can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * MZmine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with MZmine; if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +package io.github.mzmine.util.color; + +import java.util.List; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; +import javafx.scene.paint.Color; +import javax.annotation.Nullable; + +public class ColorPaletteChangedEvent extends ListChangeListener.Change { + + protected ColorPaletteChangeEventType type; + + protected final int oldIndex; + protected final int newIndex; + + protected final Color newColor; + + /** + * Constructs a new Change instance on the given list. + * + * @param list The list that was changed + */ + public ColorPaletteChangedEvent(ObservableList list, int oldIndex, int newIndex) { + super(list); + type = ColorPaletteChangeEventType.LIST_PERMUTED; + this.newIndex = newIndex; + this.oldIndex = oldIndex; + newColor = null; + } + + /** + * @param list + * @param type + * @param color + */ + protected ColorPaletteChangedEvent(ObservableList list, ColorPaletteChangeEventType type, + Color color) { + super(list); + this.type = type; + this.newIndex = 0; + this.oldIndex = 0; + this.newColor = color; + } + + @Override + public boolean next() { + return false; + } + + @Override + public void reset() { + + } + + @Override + public int getFrom() { + return oldIndex; + } + + @Override + public int getTo() { + return newIndex; + } + + @Override + public List getRemoved() { + return null; + } + + @Override + protected int[] getPermutation() { + return new int[0]; + } + + /** + * @return The new color if a color was updated/added, null if no color was added/updated. + */ + @Nullable + public Color getNewColor() { + return this.newColor; + } + + /** + * + * @return The event type. See {@link ColorPaletteChangeEventType} + */ + public ColorPaletteChangeEventType getType() { + return type; + } +} diff --git a/src/main/java/io/github/mzmine/util/color/ColorsFX.java b/src/main/java/io/github/mzmine/util/color/ColorsFX.java index 21b35f713f7..d0522cbf79b 100644 --- a/src/main/java/io/github/mzmine/util/color/ColorsFX.java +++ b/src/main/java/io/github/mzmine/util/color/ColorsFX.java @@ -1,16 +1,16 @@ /* * Copyright 2006-2020 The MZmine Development Team - * + * * This file is part of MZmine. - * + * * MZmine is free software; you can redistribute it and/or modify it under the terms of the GNU * General Public License as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. - * + * * MZmine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. - * + * * You should have received a copy of the GNU General Public License along with MZmine; if not, * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA @@ -22,28 +22,29 @@ /** * ColorPalletes (some based on http://mkweb.bcgsc.ca/colorblind) for color blindness - * - * @author Robin Schmid * + * @author Robin Schmid */ public class ColorsFX { private static final Color NEUTRAL_MARKER = new Color(0.5f, 0.5f, 0.5f, 1f); // grey // colors to mark positive or negative results (color blindness aware) - private static final Color POSITIVE_MARKER_COLORBLIND = new Color(0.f, 0.447f, 0.698f, 1f); // blue - private static final Color NEGATIVE_MARKER_COLORBLIND = new Color(0.835f, 0.369f, 0.f, 1f); // orange + private static final Color POSITIVE_MARKER_COLORBLIND = new Color(0.f, 0.447f, 0.698f, + 1f); // blue + private static final Color NEGATIVE_MARKER_COLORBLIND = new Color(0.835f, 0.369f, 0.f, + 1f); // orange private static final Color POSITIVE_MARKER = new Color(0.220f, 0.557f, 0.235f, 1f); // green private static final Color NEGATIVE_MARKER = new Color(0.808f, 0.090f, 0.161f, 1f); // red /** - * Color palette with black+7colors for color blindness:
- * Black, orange, sky blue, bluish green, yellow, blue, vermillion (darker orange), reddish purple + * Color palette with black+7colors for color blindness:
Black, orange, sky blue, bluish + * green, yellow, blue, vermillion (darker orange), reddish purple *
* http://mkweb.bcgsc.ca/colorblind/img/colorblindness.palettes.trivial.png */ - private static Color[] COLORS_7_AND_BLACK = new Color[] { // + private static Color[] COLORS_DEUTERANOPIA_BLACK = new Color[]{ // Color.BLACK, // black new Color(0.902f, 0.624f, 0f, 1f), // orange new Color(0.337f, 0.706f, 0.914f, 1f), // sky blue @@ -54,11 +55,10 @@ public class ColorsFX { new Color(0.800f, 0.475f, 0.655f, 1f)}; // reddish purple /** - * Color palette with black+7colors for color blindness:
- * Orange, sky blue, bluish green, yellow, blue, vermillion (darker orange), reddish purple
- * http://mkweb.bcgsc.ca/colorblind/img/colorblindness.palettes.trivial.png + * Color palette with black+7colors for color blindness:
Orange, sky blue, bluish green, + * yellow, blue, vermillion (darker orange), reddish purple
http://mkweb.bcgsc.ca/colorblind/img/colorblindness.palettes.trivial.png */ - private static Color[] COLORS_7 = new Color[] { // + private static Color[] COLORS_DEUTERANOPIA = new Color[]{ // new Color(0.902f, 0.624f, 0f, 1f), // orange new Color(0.337f, 0.706f, 0.914f, 1f), // sky blue new Color(0.f, 0.620f, 0.451f, 1f), // bluish green @@ -67,30 +67,85 @@ public class ColorsFX { new Color(0.835f, 0.369f, 0.f, 1f), // vermillion (darker orange) new Color(0.800f, 0.475f, 0.655f, 1f)}; // reddish purple + private static Color[] COLORS_PROTANOPIA = new Color[]{ + new Color(0.902f, 0.624f, 0f, 1f), // orang + new Color(0.337f, 0.706f, 0.914f, 1f), // sky blue + Color.web("0xB38C70"), + Color.web("0xFFD44D"), + Color.web("0x0071AA"), + Color.web("0x9C6727"), + Color.web("0x6583A3") + }; + + private static Color[] COLORS_PROTANOPIA_BLACK = new Color[]{ + Color.BLACK, + new Color(0.902f, 0.624f, 0f, 1f), // orang + new Color(0.337f, 0.706f, 0.914f, 1f), // sky blue + Color.web("0xB38C70"), + Color.web("0xFFD44D"), + Color.web("0x0071AA"), + Color.web("0x9C6727"), + Color.web("0x6583A3") + }; + + private static Color[] COLORS_TRITANOPIA = new Color[]{ + Color.web("0xFF8695"), // orang + Color.web("0x00B7CA"), + Color.web("0x368D96"), + Color.web("0xFFCCD3"), + Color.web("0x007787"), + Color.web("0xEA4761"), + Color.web("0xCA7B84") + }; + + private static Color[] COLORS_TRITANOPIA_BLACK = new Color[]{ + Color.BLACK, + Color.web("0xFF8695"), // orang + Color.web("0x00B7CA"), + Color.web("0x368D96"), + Color.web("0xFFCCD3"), + Color.web("0x007787"), + Color.web("0xEA4761"), + Color.web("0xCA7B84") + }; + /** * Seven colors (+black) - * - * @param mode color blindness? + * + * @param vision color blindness? * @param includeBlack include black as the first color * @return */ public static Color[] getSevenColorPalette(Vision vision, boolean includeBlack) { // so far always the same color palette - return includeBlack ? COLORS_7_AND_BLACK : COLORS_7; + + switch (vision) { + case DEUTERANOPIA: + return includeBlack ? COLORS_DEUTERANOPIA_BLACK : COLORS_DEUTERANOPIA; + case PROTANOPIA: + return includeBlack ? COLORS_PROTANOPIA_BLACK : COLORS_PROTANOPIA; + case TRITANOPIA: + return includeBlack ? COLORS_TRITANOPIA_BLACK : COLORS_TRITANOPIA; + case NORMAL_VISION: + return includeBlack ? COLORS_DEUTERANOPIA_BLACK : COLORS_DEUTERANOPIA; + default: + return includeBlack ? COLORS_DEUTERANOPIA_BLACK : COLORS_DEUTERANOPIA; + } } /** * Return positive feedback color - * - * @param mode + * * @return */ public static Color getPositiveColor(Vision vision) { switch (vision) { // color blind case DEUTERANOPIA: + return POSITIVE_MARKER_COLORBLIND; case PROTANOPIA: + return POSITIVE_MARKER_COLORBLIND; case TRITANOPIA: return POSITIVE_MARKER_COLORBLIND; // normal vision @@ -102,15 +157,16 @@ public static Color getPositiveColor(Vision vision) { /** * Return positive feedback color - * - * @param mode + * * @return */ public static Color getNegativeColor(Vision vision) { switch (vision) { // color blind case DEUTERANOPIA: + return NEGATIVE_MARKER_COLORBLIND; case PROTANOPIA: + return NEGATIVE_MARKER_COLORBLIND; case TRITANOPIA: return NEGATIVE_MARKER_COLORBLIND; // normal vision diff --git a/src/main/java/io/github/mzmine/util/color/SimpleColorPalette.java b/src/main/java/io/github/mzmine/util/color/SimpleColorPalette.java index f748c34583c..99eaa547a8c 100644 --- a/src/main/java/io/github/mzmine/util/color/SimpleColorPalette.java +++ b/src/main/java/io/github/mzmine/util/color/SimpleColorPalette.java @@ -1,16 +1,16 @@ /* * Copyright 2006-2020 The MZmine Development Team - * + * * This file is part of MZmine. - * + * * MZmine is free software; you can redistribute it and/or modify it under the terms of the GNU * General Public License as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. - * + * * MZmine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. - * + * * You should have received a copy of the GNU General Public License along with MZmine; if not, * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA @@ -18,16 +18,16 @@ package io.github.mzmine.util.color; +import com.google.common.collect.ImmutableMap; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nonnull; -import javax.annotation.Nullable; import org.jfree.chart.plot.DefaultDrawingSupplier; import org.w3c.dom.Element; import io.github.mzmine.gui.chartbasics.chartthemes.EStandardChartTheme; -import io.github.mzmine.main.MZmineCore; import io.github.mzmine.util.javafx.FxColorUtil; import javafx.collections.ModifiableObservableListBase; import javafx.scene.paint.Color; @@ -36,11 +36,40 @@ * Implementation of a color palette. It's an observable list to allow addition of listeners. * * @author SteffenHeu steffen.heuckeroth@gmx.de / s_heuc03@uni-muenster.de - * */ public class SimpleColorPalette extends ModifiableObservableListBase implements Cloneable { + protected static final SimpleColorPalette DEFAULT_NORMAL = new SimpleColorPalette( + ColorsFX.getSevenColorPalette(Vision.NORMAL_VISION, true), "Normal", + ColorsFX.getPositiveColor(Vision.NORMAL_VISION), ColorsFX.getNeutralColor(), + ColorsFX.getNegativeColor(Vision.NORMAL_VISION)); + + protected static final SimpleColorPalette DEFAULT_DEUTERANOPIA = new SimpleColorPalette( + ColorsFX.getSevenColorPalette(Vision.DEUTERANOPIA, true), "Deuteranopia", + ColorsFX.getPositiveColor(Vision.DEUTERANOPIA), ColorsFX.getNeutralColor(), + ColorsFX.getNegativeColor(Vision.DEUTERANOPIA)); + + protected static final SimpleColorPalette DEFAULT_PROTANOPIA = new SimpleColorPalette( + ColorsFX.getSevenColorPalette(Vision.PROTANOPIA, true), "Protanopia", + ColorsFX.getPositiveColor(Vision.PROTANOPIA), ColorsFX.getNeutralColor(), + ColorsFX.getNegativeColor(Vision.PROTANOPIA)); + + protected static final SimpleColorPalette DEFAULT_TRITANOPIA = new SimpleColorPalette( + ColorsFX.getSevenColorPalette(Vision.TRITANOPIA, true), "Tritanopia", + ColorsFX.getPositiveColor(Vision.TRITANOPIA), ColorsFX.getNeutralColor(), + ColorsFX.getNegativeColor(Vision.TRITANOPIA)); + + /** + * Access via {@link Vision} + */ + public static final ImmutableMap DEFAULT = ImmutableMap + .of(Vision.NORMAL_VISION, DEFAULT_NORMAL, Vision.DEUTERANOPIA, DEFAULT_DEUTERANOPIA, + Vision.PROTANOPIA, DEFAULT_PROTANOPIA, Vision.TRITANOPIA, DEFAULT_TRITANOPIA); + private static final String NAME_ATTRIBUTE = "name"; + private static final String POS_ATTRIBUTE = "positive_color"; + private static final String NEG_ATTRIBUTE = "negative_color"; + private static final String NEU_ATTRIBUTE = "neutral_color"; private static final Color defclr = Color.BLACK; private static final Logger logger = Logger.getLogger(SimpleColorPalette.class.getName()); @@ -51,8 +80,13 @@ public class SimpleColorPalette extends ModifiableObservableListBase impl protected String name; protected int next; + protected Color positiveColor; + protected Color negativeColor; + + protected Color neutralColor; + /** - * + * */ private static final long serialVersionUID = 1L; @@ -61,19 +95,30 @@ public SimpleColorPalette() { delegate = new ArrayList<>(); next = 0; name = ""; + positiveColor = ColorsFX.getPositiveColor(Vision.DEUTERANOPIA); + negativeColor = ColorsFX.getNegativeColor(Vision.DEUTERANOPIA); + neutralColor = ColorsFX.getNeutralColor(); } - public SimpleColorPalette(Color[] clrs) { + public SimpleColorPalette(@Nonnull Color[] clrs) { this(); for (Color clr : clrs) { add(clr); } } - public SimpleColorPalette(SimpleColorPalette p) { - this(); - p.forEach(c -> add(c)); - name = p.getName() + " (cpy)"; + public SimpleColorPalette(@Nonnull Color[] clrs, @Nonnull String name) { + this(clrs); + setName(name); + } + + public SimpleColorPalette(@Nonnull Color[] clrs, @Nonnull String name, Color positiveColor, + Color neutralColor, Color negativeColor) { + this(clrs, name); + + setPositiveColor(positiveColor); + setNeutralColor(neutralColor); + setNegativeColor(negativeColor); } public void applyToChartTheme(EStandardChartTheme theme) { @@ -89,7 +134,6 @@ public void applyToChartTheme(EStandardChartTheme theme) { } /** - * * @return The next color in the color palette. */ public Color getNextColor() { @@ -105,14 +149,23 @@ public Color getNextColor() { return get(next - 1); } - @Nonnull public Color getMainColor() { - if (isValidPalette()) { + public java.awt.Color getNextColorAWT(int index) { + return FxColorUtil.fxColorToAWT(getNextColor()); + } + + @Nonnull + public Color getMainColor() { + if (isValid()) { return get(MAIN_COLOR); } return Color.BLACK; } - public boolean isValidPalette() { + public java.awt.Color getMainColorAWT() { + return FxColorUtil.fxColorToAWT(getMainColor()); + } + + public boolean isValid() { if (this.isEmpty()) { return false; } @@ -127,7 +180,8 @@ public boolean isValidPalette() { return true; } - @Nonnull public String getName() { + @Nonnull + public String getName() { return name; } @@ -135,50 +189,72 @@ public void setName(@Nonnull String name) { this.name = name; } - public void moveColor(Color color, int newIndex) { - moveColor(indexOf(color), newIndex); + /** + * @param color + * @param newIndex + * @return The new index of the moved color. -1 if called with invalid color. + */ + public int moveColor(Color color, int newIndex) { + return moveColor(indexOf(color), newIndex); } - public void moveColor(int oldIndex, int newIndex) { + /** + * @param oldIndex + * @param newIndex + * @return The new index of the moved color. -1 if called with invalid index. + */ + public int moveColor(int oldIndex, int newIndex) { if (oldIndex < 0 || newIndex < 0 || oldIndex >= size() || newIndex >= size()) { logger.info("move called with invalid parameters " + oldIndex + " to " + newIndex); - return; + return -1; } - List sublist = new ArrayList<>(); - delegate.subList(newIndex, delegate.size()).forEach(c -> sublist.add(c)); Color clr = delegate.get(oldIndex); - sublist.remove(clr); - delegate.remove(clr); + // if the color shall be moved to the end, we have to increment by 1, otherwise the last color + // will just move one to the right. + if (newIndex == size() - 1) { + newIndex++; + } + + delegate.add(newIndex, clr); + + if (oldIndex > newIndex) { + remove(oldIndex + 1); + } else { + remove(oldIndex); + } - delegate.removeAll(sublist); - delegate.add(clr); - delegate.addAll(sublist); + fireChange(new ColorPaletteChangedEvent(this, oldIndex, newIndex)); - fireChange(new ColorPaletteColorMovedEvent(this, oldIndex, newIndex)); + return indexOf(clr); } /** * Checks for equality between two color palettes. Does not take the name into account. - * + * * @param obj The palette. * @return true or false. */ - @Override public boolean equals(Object obj) { - if(obj == null) + @Override + public boolean equals(Object obj) { + if (obj == null) { return false; + } - if(obj == this) + if (obj == this) { return true; + } - if(!(obj instanceof SimpleColorPalette)) + if (!(obj instanceof SimpleColorPalette)) { return false; + } SimpleColorPalette palette = (SimpleColorPalette) obj; - if (size() != palette.size()) + if (size() != palette.size()) { return false; + } for (int i = 0; i < size(); i++) { if (!Objects.equals(get(i).toString(), palette.get(i).toString())) { @@ -186,15 +262,27 @@ public void moveColor(int oldIndex, int newIndex) { } } - if(!Objects.equals(getName(), palette.getName())) + if (!Objects.equals(getName(), palette.getName())) { + return false; + } + + if (!Objects.equals(getPositiveColor().toString(), palette.getPositiveColor().toString())) { + return false; + } + if (!Objects.equals(getNegativeColor().toString(), palette.getNegativeColor().toString())) { + return false; + } + if (!Objects.equals(getNeutralColor().toString(), palette.getNeutralColor().toString())) { return false; + } return true; } @Override public int hashCode() { - return super.hashCode() + name.hashCode(); + return super.hashCode() + name.hashCode() + getPositiveColor().hashCode() + getNeutralColor() + .hashCode() + getNegativeColor().hashCode(); } @Override @@ -204,31 +292,56 @@ public SimpleColorPalette clone() { clone.add(clr); } clone.setName(getName()); + clone.setNegativeColor(getNegativeColor()); + clone.setPositiveColor(getPositiveColor()); return clone; } @Override public String toString() { - return getName() + " " + super.toString(); + return getName() + " " + super.toString() + " pos " + getPositiveColor().toString() + " neg " + + getNegativeColor(); } public void loadFromXML(Element xmlElement) { this.setName(xmlElement.getAttribute(NAME_ATTRIBUTE)); String text = xmlElement.getTextContent(); - // not a single color in the palette - if (text.length() < 10) { - this.clear(); + String pos = xmlElement.getAttribute(POS_ATTRIBUTE); + String neg = xmlElement.getAttribute(NEG_ATTRIBUTE); + String neu = xmlElement.getAttribute(NEU_ATTRIBUTE); + + Color clrPos, clrNeg, clrNeu; + + try { + text = text.substring(1, text.length() - 1); + text = text.replaceAll("\\s", ""); + String[] clrs = text.split(","); + for (String clr : clrs) { + delegate.add(Color.web(clr)); + } + } catch (Exception e) { + logger.log(Level.WARNING, + "Could not load color palette " + name + ". Setting default colors.", e); this.addAll( - ColorsFX.getSevenColorPalette(MZmineCore.getConfiguration().getColorVision(), true)); - return; + ColorsFX.getSevenColorPalette(Vision.DEUTERANOPIA, true)); } - text = text.substring(1, text.length() - 1); - text = text.replaceAll("\\s", ""); - String[] clrs = text.split(","); - for (String clr : clrs) { - delegate.add(Color.web(clr)); + + try { + clrPos = Color.web(pos); + clrNeg = Color.web(neg); + clrNeu = Color.web(neu); + } catch (Exception e) { + logger.log(Level.WARNING, + "Could not load positve/negative colors of " + name + ". Setting default colors.", e); + clrPos = ColorsFX.getPositiveColor(Vision.DEUTERANOPIA); + clrNeg = ColorsFX.getNegativeColor(Vision.DEUTERANOPIA); + clrNeu = ColorsFX.getNeutralColor(); } + + setPositiveColor(clrPos); + setNegativeColor(clrNeg); + setNeutralColor(clrNeu); } public static SimpleColorPalette createFromXML(Element xmlElement) { @@ -245,7 +358,54 @@ public static SimpleColorPalette createFromXML(Element xmlElement) { public void saveToXML(Element xmlElement) { xmlElement.setAttribute(NAME_ATTRIBUTE, name); xmlElement.setTextContent(delegate.toString()); - logger.info(xmlElement.toString()); + xmlElement.setAttribute(POS_ATTRIBUTE, getPositiveColor().toString()); + xmlElement.setAttribute(NEG_ATTRIBUTE, getNegativeColor().toString()); + xmlElement.setAttribute(NEU_ATTRIBUTE, getNeutralColor().toString()); + } + + public Color getPositiveColor() { + return positiveColor; + } + + public java.awt.Color getPositiveColorAWT() { + return FxColorUtil.fxColorToAWT(getPositiveColor()); + } + + public void setPositiveColor(Color positiveColor) { + this.positiveColor = positiveColor; + fireChange( + new ColorPaletteChangedEvent(this, ColorPaletteChangeEventType.POSITIVE_MARKER_UPDATED, + positiveColor)); + } + + public Color getNegativeColor() { + return negativeColor; + } + + public java.awt.Color getNegativeColorAWT() { + return FxColorUtil.fxColorToAWT(getNegativeColor()); + } + + public void setNegativeColor(Color negativeColor) { + this.negativeColor = negativeColor; + fireChange( + new ColorPaletteChangedEvent(this, ColorPaletteChangeEventType.NEGATIVE_MARKER_UPDATED, + negativeColor)); + } + + public Color getNeutralColor() { + return neutralColor; + } + + public java.awt.Color getNeutralColorAWT() { + return FxColorUtil.fxColorToAWT(getNeutralColor()); + } + + public void setNeutralColor(Color neutralColor) { + this.neutralColor = neutralColor; + fireChange( + new ColorPaletteChangedEvent(this, ColorPaletteChangeEventType.NEUTRAL_MARKER_UPDATED, + neutralColor)); } // --- super type @@ -255,6 +415,10 @@ public Color get(int index) { return delegate.get(index); } + public java.awt.Color getAWT(int index) { + return FxColorUtil.fxColorToAWT(get(index)); + } + @Override public int size() { return delegate.size(); diff --git a/src/main/java/io/github/mzmine/util/javafx/DraggableRectangle.java b/src/main/java/io/github/mzmine/util/javafx/DraggableRectangle.java new file mode 100644 index 00000000000..ff5bee3c984 --- /dev/null +++ b/src/main/java/io/github/mzmine/util/javafx/DraggableRectangle.java @@ -0,0 +1,83 @@ +/* + * Copyright 2006-2020 The MZmine Development Team + * + * This file is part of MZmine. + * + * MZmine is free software; you can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * MZmine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with MZmine; if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +package io.github.mzmine.util.javafx; + +import javafx.scene.Parent; +import javafx.scene.image.WritableImage; +import javafx.scene.input.ClipboardContent; +import javafx.scene.input.Dragboard; +import javafx.scene.input.TransferMode; +import javafx.scene.shape.Rectangle; + +public class DraggableRectangle extends Rectangle { + + public DraggableRectangle(double w, double h) { + super(w, h); + + setOnDragDetected(e -> { + Dragboard dragboard = startDragAndDrop(TransferMode.MOVE); + ClipboardContent content = new ClipboardContent(); + int index = getParent().getChildrenUnmodifiable().indexOf(this); + content.putString(String.valueOf(index)); + WritableImage snapshot = this.snapshot(null, null); + dragboard.setDragView(snapshot); + dragboard.setContent(content); + e.consume(); + }); + + setOnDragOver(e -> { + if (e.getGestureSource() != this && e.getDragboard().hasString()) { + e.acceptTransferModes(TransferMode.MOVE); + } + e.consume(); + }); + + setOnDragEntered(e -> { + if (e.getGestureSource() != this && e.getDragboard().hasString()) { + setOpacity(getOpacity() * 0.3d); + } + e.consume(); + }); + + setOnDragExited(e -> { + if (e.getGestureSource() != this && e.getDragboard().hasString()) { + setOpacity(getOpacity() / 0.3d); + } + e.consume(); + }); + + setOnDragDropped(e -> { + Parent parent = getParent(); + if (parent instanceof DraggableRectangleContainer) { + + Dragboard dragboard = e.getDragboard(); + if (!dragboard.hasString()) { + return; + } + + int oldIndex = Integer.valueOf(dragboard.getString()); + int newIndex = parent.getChildrenUnmodifiable().indexOf(this); + + ((DraggableRectangleContainer) parent) + .moveRectangle(oldIndex, newIndex); + } + e.consume(); + }); + } +} diff --git a/src/main/java/io/github/mzmine/util/javafx/DraggableRectangleContainer.java b/src/main/java/io/github/mzmine/util/javafx/DraggableRectangleContainer.java new file mode 100644 index 00000000000..c006492b4f8 --- /dev/null +++ b/src/main/java/io/github/mzmine/util/javafx/DraggableRectangleContainer.java @@ -0,0 +1,24 @@ +/* + * Copyright 2006-2020 The MZmine Development Team + * + * This file is part of MZmine. + * + * MZmine is free software; you can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * MZmine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with MZmine; if not, + * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +package io.github.mzmine.util.javafx; + +public interface DraggableRectangleContainer { + + public void moveRectangle(int oldIndex, int newIndex); +}