From 20308fa155d558e3e74b4dec03bf7598935ad8c0 Mon Sep 17 00:00:00 2001 From: dzmipt Date: Sun, 17 Nov 2024 20:25:10 +0100 Subject: [PATCH] adding LineInfoFrame: added controls to view dx, dy, x, y --- src/studio/ui/chart/ChartConfigPanel.java | 6 +- src/studio/ui/chart/Line.java | 29 +++- src/studio/ui/chart/LineInfoFrame.java | 155 ++++++++++++++++++++++ 3 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 src/studio/ui/chart/LineInfoFrame.java diff --git a/src/studio/ui/chart/ChartConfigPanel.java b/src/studio/ui/chart/ChartConfigPanel.java index a6ea753..2297719 100644 --- a/src/studio/ui/chart/ChartConfigPanel.java +++ b/src/studio/ui/chart/ChartConfigPanel.java @@ -89,8 +89,12 @@ public LegendIcon getLegendIcon(int index) { } public void addLine(Line line) { + String title = "Line " + (1+ listLines.getListSize()); + line.setTitle(title); lines.add(line); - listLines.add("Line " + (1+ listLines.getListSize()), line.getIcon()); + listLines.add(title, line.getIcon()); + + new LineInfoFrame(line); } private void refresh() { diff --git a/src/studio/ui/chart/Line.java b/src/studio/ui/chart/Line.java index 7591dbc..529de0d 100644 --- a/src/studio/ui/chart/Line.java +++ b/src/studio/ui/chart/Line.java @@ -19,6 +19,7 @@ public class Line extends AbstractAnnotation implements XYAnnotation { private final ChartPanel chartPanel; private Point2D.Double p0, p1; private LegendIcon icon; + private String title = ""; private Point screenP0, screenP1; private boolean selected = false; @@ -106,6 +107,7 @@ public void moveTo(Point2D.Double p) { p0 = new Point2D.Double(x0, y0); p1 = p; refresh(); + fireAnnotationChanged(); } public void dragTo(Point p) { @@ -122,6 +124,31 @@ public void dragTo(Point p) { p0 = chartPanel.toPlot(screenP0); p1 = chartPanel.toPlot(screenP1); refresh(); + fireAnnotationChanged(); + } + + public double getDX(double dy) { + return dy * (p1.x - p0.x) / (p1.y - p0.y); + } + + public double getDY(double dx) { + return dx * (p1.y - p0.y) / (p1.x - p0.x); + } + + public double getX(double y) { + return intersectHorizontal(new Line2D.Double(p0, p1), y); + } + + public double getY(double x) { + return intersectVertical(new Line2D.Double(p0, p1), x); + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; } public LegendIcon getIcon() { @@ -168,6 +195,6 @@ public void draw(Graphics2D g2, XYPlot plot, Rectangle2D dataArea, ValueAxis dom g2.setPaint(icon.getColor()); g2.setStroke(stroke); g2.drawLine(screenP0.x, screenP0.y, screenP1.x, screenP1.y); - } + } diff --git a/src/studio/ui/chart/LineInfoFrame.java b/src/studio/ui/chart/LineInfoFrame.java new file mode 100644 index 0000000..0e8a0df --- /dev/null +++ b/src/studio/ui/chart/LineInfoFrame.java @@ -0,0 +1,155 @@ +package studio.ui.chart; + +import studio.ui.GroupLayoutSimple; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.function.DoubleConsumer; + +public class LineInfoFrame extends JFrame { + + private final Line line; + private final JLabel lblDX = new JLabel(""); + private final JLabel lblDY = new JLabel(""); + private final JLabel lblX = new JLabel(""); + private final JLabel lblY = new JLabel(""); + private final JTextField txtTitle = new JTextField(); + private final JTextField txtDX = new JTextField(); + private final JTextField txtDY = new JTextField(); + private final JTextField txtX = new JTextField(); + private final JTextField txtY = new JTextField(); + + private double dx = 1; + private double dy = Double.NaN; + private double x = 0; + private double y = Double.NaN; + private boolean lockDX = true; + private boolean lockX = true; + + public LineInfoFrame(Line line) { + this.line = line; + line.addChangeListener(e -> refresh()); + initComponents(); + } + + + private JComponent createPanelLabel(JLabel label, Runnable action) { + JPanel panel = new JPanel(new BorderLayout(0,0)); + panel.add(label, BorderLayout.EAST); + panel.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + action.run(); + refresh(); + } + }); + return panel; + } + + private void performAction(JTextField textField, DoubleConsumer action) { + try { + double value = Double.parseDouble(textField.getText()); + action.accept(value); + } catch (NumberFormatException e) {} + refresh(); + } + + private JTextField withAction(JTextField textField, DoubleConsumer action) { + textField.addActionListener(e -> performAction(textField, action)); + textField.addFocusListener(new FocusAdapter() { + @Override + public void focusLost(FocusEvent e) { + performAction(textField, action); + } + }); + return textField; + } + + private void initComponents() { + setTitle(getTitle()); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + + JLabel lblTitle = new JLabel("Title"); + + + + JPanel content = new JPanel(); + GroupLayoutSimple layout = new GroupLayoutSimple(content); + + layout.setStacks( + new GroupLayoutSimple.Stack() + .addLine(Box.createGlue(),lblTitle) + .addLine(createPanelLabel(lblDX, () -> lockDX=true ) ) + .addLine(createPanelLabel(lblDY, () -> lockDX=false )) + .addLine(createPanelLabel(lblX, () -> lockX=true )) + .addLine(createPanelLabel(lblY, () -> lockX=false )), + new GroupLayoutSimple.Stack() + .addLine(txtTitle) + .addLine(withAction(txtDX, this::updateDX)) + .addLine(withAction(txtDY, this::updateDY)) + .addLine(withAction(txtX, this::updateX)) + .addLine(withAction(txtY, this::updateY)) + ); + + refresh(); + setContentPane(content); + pack(); + setSize(getPreferredSize()); + setVisible(true); + } + + @Override + public String getTitle() { + return line.getTitle() + " info"; + } + + private String fmtLabel(String text, boolean locked) { + if (locked) { + return "" + text + ""; + } else { + return text; + } + } + + private void updateDX(double newDX) { + dx = newDX; + } + + private void updateDY(double newDY) { + dy = newDY; + } + + private void updateX(double newX) { + x = newX; + } + + private void updateY(double newY) { + y = newY; + } + + private void refresh() { + if (lockDX) dy = line.getDY(dx); + else dx = line.getDX(dy); + + if (lockX) y = line.getY(x); + else x = line.getDX(y); + + txtDX.setText("" + dx); + txtDY.setText("" + dy); + txtX.setText("" + x); + txtY.setText("" + y); + + txtTitle.setText(line.getTitle()); + + lblDX.setText(fmtLabel("Δx", lockDX)); + lblDY.setText(fmtLabel("Δy", !lockDX)); + lblX.setText(fmtLabel("x", lockX)); + lblY.setText(fmtLabel("y", !lockX)); + + } + +}