diff --git a/notes.md b/notes.md index 2dd3f02..06a0cd8 100644 --- a/notes.md +++ b/notes.md @@ -1,4 +1,4 @@ -* Lines can be added directly from the Chart panel +* Lines tool is added to charts * Adding drag&drop in the tree of servers (in the Server List dialog) * Server connect/disconnect actions from the status bar * adding selection of auth.method into the status bar diff --git a/src/studio/ui/chart/ChartConfigPanel.java b/src/studio/ui/chart/ChartConfigPanel.java index 82a4d26..a6ea753 100644 --- a/src/studio/ui/chart/ChartConfigPanel.java +++ b/src/studio/ui/chart/ChartConfigPanel.java @@ -3,6 +3,8 @@ import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.List; public class ChartConfigPanel extends Box { @@ -13,6 +15,7 @@ public class ChartConfigPanel extends Box { private final LegendListPanel listSeries; private final LegendListPanel listLines; + private final List lines = new ArrayList<>(); public ChartConfigPanel(Chart chart, String[] names) { @@ -85,12 +88,15 @@ public LegendIcon getLegendIcon(int index) { return listSeries.getIcon(index); } - public void addLine(Line aLine) { - LegendIcon icon = new LegendIcon(Color.BLACK, null, LegendButton.getDefaultStroke()); - listLines.add("Line " + (1+ listLines.getListSize()), icon); + public void addLine(Line line) { + lines.add(line); + listLines.add("Line " + (1+ listLines.getListSize()), line.getIcon()); } private void refresh() { + for (int index = 0; index < lines.size(); index++) { + lines.get(index).setVisible(listLines.isSelected(index)); + } invalidate(); repaint(); chart.refreshPlot(); diff --git a/src/studio/ui/chart/LegendButton.java b/src/studio/ui/chart/LegendButton.java index f2f742e..4452ae2 100644 --- a/src/studio/ui/chart/LegendButton.java +++ b/src/studio/ui/chart/LegendButton.java @@ -61,8 +61,8 @@ private static class StrokeWidth { new StrokeWidth("x 3", 3), }; - //@TODO: May be it is better to have a cache of all possible strokes to avoid unneseccary garbage ? - private static BasicStroke strokeWithWidth(BasicStroke stroke, float width) { + //@TODO: May be it is better to have a cache of all possible strokes to avoid unnecessary garbage ? + public static BasicStroke strokeWithWidth(BasicStroke stroke, float width) { if (stroke.getLineWidth() == width) return stroke; return new BasicStroke(width, stroke.getEndCap(), stroke.getLineJoin(), diff --git a/src/studio/ui/chart/LegendListPanel.java b/src/studio/ui/chart/LegendListPanel.java index 8241055..a249ba4 100644 --- a/src/studio/ui/chart/LegendListPanel.java +++ b/src/studio/ui/chart/LegendListPanel.java @@ -92,7 +92,7 @@ private void updateLayout() { chkGroup.addComponent(chk); iconGroup.addComponent(button); - rowsGroup.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) + rowsGroup.addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) .addComponent(chk) .addComponent(button) ); } diff --git a/src/studio/ui/chart/Line.java b/src/studio/ui/chart/Line.java index ab2b09f..7591dbc 100644 --- a/src/studio/ui/chart/Line.java +++ b/src/studio/ui/chart/Line.java @@ -18,15 +18,18 @@ public class Line extends AbstractAnnotation implements XYAnnotation { private final ChartPanel chartPanel; private Point2D.Double p0, p1; + private LegendIcon icon; private Point screenP0, screenP1; private boolean selected = false; - private boolean visible = false; + private boolean off = false; private boolean init = false; + private boolean visible = true; public Line(ChartPanel chartPanel, Point2D.Double p0) { this.chartPanel = chartPanel; this.p0 = p0; + icon = new LegendIcon(Color.BLACK, null, LegendButton.getDefaultStroke()); XYPlot plot = chartPanel.getChart().getXYPlot(); plot.getDomainAxis().addChangeListener(e -> refresh()); plot.getRangeAxis().addChangeListener(e -> refresh()); @@ -65,9 +68,9 @@ private void refresh() { Point2D.Double p1 = points.get(1); screenP0 = chartPanel.fromPlot(p0); screenP1 = chartPanel.fromPlot(p1); - visible = true; + off = true; } else { - visible = false; + off = false; selected = false; } } @@ -85,7 +88,7 @@ private static boolean within(double d0, double d1, double d2) { } public double distanceSqr(int x, int y) { - if (!init || !visible) return Double.POSITIVE_INFINITY; + if (!init || !off || !visible) return Double.POSITIVE_INFINITY; double s2 = x*(screenP0.y-screenP1.y) + screenP0.x*(screenP1.y-y) + screenP1.x*(y-screenP0.y); double l2 = screenDist(screenP0, screenP1); @@ -121,6 +124,10 @@ public void dragTo(Point p) { refresh(); } + public LegendIcon getIcon() { + return icon; + } + public void setSelected(boolean selected) { this.selected = selected; } @@ -129,21 +136,37 @@ public boolean isSelected() { return selected; } + public void setVisible(boolean visible) { + this.visible = visible; + } + @Override public void draw(Graphics2D g2, XYPlot plot, Rectangle2D dataArea, ValueAxis domainAxis, ValueAxis rangeAxis, int rendererIndex, PlotRenderingInfo info) { if (!init) { Point p = chartPanel.fromPlot(p0); Shape shape = new Ellipse2D.Double(p.x-2, p.y-2, 4,4); - g2.setColor(Color.black); + g2.setPaint(icon.getColor()); g2.fill(shape); return; } - if (!visible) return; + if (!off || !visible) return; + + BasicStroke stroke = icon.getStroke(); + if (selected) { + float width = 2 * stroke.getLineWidth(); + float[] dash = stroke.getDashArray(); + if (dash != null) { + for (int i=0; i