/* * Copyright (c) 2005, Graph Builder * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * * Neither the name of Graph Builder nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import java.util.Vector; import com.graphbuilder.curve.*; public class EditCurvePanel extends JPanel implements ActionListener, ListSelectionListener, ValueVectorListener { private JList curveList = new JList(); private Vector curveListVec = new Vector(); private JButton insertButton = new JButton("Insert"); private JButton removeButton = new JButton("Remove"); private JLabel controlStringLabel = new JLabel("Control String:"); private JTextField controlStringTextField = new JTextField(6); private JCheckBox connectCheckBox = new JCheckBox("Connect"); private JLabel tminLabel = new JLabel("t_min:"); private JLabel tmaxLabel = new JLabel("t_max:"); private JTextField tminTextField = new JTextField(3); private JTextField tmaxTextField = new JTextField(3); private JLabel sampleLimitLabel = new JLabel("Sample Limit:"); private JTextField sampleLimitTextField = new JTextField(2); private JLabel alphaLabel = new JLabel("Alpha:"); private JTextField alphaTextField = new JTextField(4); private JLabel degreeLabel = new JLabel("Degree:"); private JTextField degreeTextField = new JTextField(2); private JLabel knotVectorTypeLabel = new JLabel("Knot Vector Type:"); private JComboBox knotVectorTypeComboBox = new JComboBox(new Object[] { "Uniform Clamped", "Uniform Unclamped", "Non-Uniform" }); private JCheckBox useDefaultIntervalCheckBox = new JCheckBox("Use Default Interval"); private JCheckBox interpolateEndpointsCheckBox = new JCheckBox("Interpolate Endpoints"); private JCheckBox closedCheckBox = new JCheckBox("Closed"); private UnsortedValueVectorPanel knotVectorPanel = new UnsortedValueVectorPanel(true); private UnsortedValueVectorPanel weightVectorPanel = new UnsortedValueVectorPanel(true); private JLabel baseIndexLabel = new JLabel("Base Index:"); private JTextField baseIndexTextField = new JTextField(3); private JLabel baseLengthLabel = new JLabel("Base Length:"); private JTextField baseLengthTextField = new JTextField(3); private JCheckBox interpolateFirstCheckBox = new JCheckBox("Interpolate First"); private JCheckBox interpolateLastCheckBox = new JCheckBox("Interpolate Last"); private JCheckBox useWeightVectorCheckBox = new JCheckBox("Use Weight Vector"); private JDialog pickCurveDialog = null; private JList availableCurveList = null; private JButton okButton = new JButton("OK"); private JButton cancelButton = new JButton("Cancel"); private JPanel listPanel = new JPanel(new BorderLayout()); private JPanel editPanel = new JPanel(new BorderLayout()); private ControlPath controlPath = null; private JPanel repaintPanel = null; private JPanel closePanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); private JButton applyButton = new JButton("Apply"); private JButton closeButton = new JButton("Close"); public EditCurvePanel() { super(); curveList.setPrototypeCellValue("Natural Cubic Spline"); curveList.setCellRenderer(new CurveListCellRenderer()); setLayout(new BorderLayout()); knotVectorPanel.addValueVectorListener(this); weightVectorPanel.addValueVectorListener(this); weightVectorPanel.setKnobFillColor(Color.red); weightVectorPanel.setRange(0, 3); JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); buttonPanel.add(insertButton); buttonPanel.add(removeButton); listPanel.add(new JScrollPane(curveList), BorderLayout.CENTER); listPanel.add(buttonPanel, BorderLayout.SOUTH); add(listPanel, BorderLayout.WEST); insertButton.addActionListener(this); removeButton.addActionListener(this); cancelButton.addActionListener(this); okButton.addActionListener(this); applyButton.addActionListener(this); closeButton.addActionListener(this); curveList.addListSelectionListener(this); connectCheckBox.addActionListener(this); interpolateEndpointsCheckBox.addActionListener(this); closedCheckBox.addActionListener(this); interpolateFirstCheckBox.addActionListener(this); interpolateLastCheckBox.addActionListener(this); knotVectorTypeComboBox.addActionListener(this); useDefaultIntervalCheckBox.addActionListener(this); useWeightVectorCheckBox.addActionListener(this); closePanel.add(applyButton); closePanel.add(closeButton); editPanel.add(closePanel, BorderLayout.SOUTH); add(editPanel, BorderLayout.CENTER); } public void setRepaintPanel(JPanel rp) { repaintPanel = rp; } public void setControlPath(ControlPath cp) { curveListVec = new Vector(); for (int i = 0; i < cp.numCurves(); i++) curveListVec.add(cp.getCurve(i)); controlPath = cp; curveList.setListData(curveListVec); } public void actionPerformed(ActionEvent evt) { Object src = evt.getSource(); if (src == insertButton) { if (pickCurveDialog == null) { String[] curves = new String[] { "Bezier Curve", "B-Spline", "Cardinal Spline", "Catmull-Rom Spline", "Cubic B-Spline", "Lagrange Curve", "Natural Cubic Spline", "NURB-Spline", "Polyline" }; availableCurveList = new JList(curves); Window w = SwingUtilities.windowForComponent(this); String title = "Insert Curve"; if (w instanceof Frame) pickCurveDialog = new JDialog((Frame) w, title); else if (w instanceof Dialog) pickCurveDialog = new JDialog((Dialog) w, title); else pickCurveDialog = new JDialog((Frame) null, title); JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); buttonPanel.add(okButton); buttonPanel.add(cancelButton); JPanel listPanel = new JPanel(new BorderLayout()); availableCurveList.setBorder(BorderFactory.createLineBorder(Color.darkGray)); listPanel.add(availableCurveList, BorderLayout.CENTER); listPanel.add(buttonPanel, BorderLayout.SOUTH); Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); pickCurveDialog.setContentPane(listPanel); pickCurveDialog.setModal(true); pickCurveDialog.pack(); pickCurveDialog.setLocation((d.width - pickCurveDialog.getWidth()) / 2, (d.height - pickCurveDialog.getHeight()) / 2); } pickCurveDialog.show(); } else if (src == okButton || src == cancelButton) { String name = (String) availableCurveList.getSelectedValue(); if (src == okButton && name != null) { Curve c = createCurve(name); int index = curveList.getSelectedIndex(); if (index < 0) index = curveListVec.size(); curveListVec.insertElementAt(c, index); curveList.setListData(curveListVec); controlPath.insertCurve(c, index); curveList.setSelectedValue(c, true); } pickCurveDialog.hide(); } else if (src == removeButton) { int[] indices = curveList.getSelectedIndices(); for (int i = indices.length - 1; i >= 0; i--) { curveListVec.removeElementAt(indices[i]); controlPath.removeCurve(indices[i]); } curveList.setListData(curveListVec); if (indices.length > 0) { int index = indices[0]; if (index >= controlPath.numCurves()) index = controlPath.numCurves() - 1; if (index >= 0) { curveList.setSelectedIndex(index); } } } else if (src == connectCheckBox) { Curve c = (Curve) curveList.getSelectedValue(); c.setConnect(connectCheckBox.isSelected()); } else if (src == interpolateEndpointsCheckBox) { CubicBSpline cbs = (CubicBSpline) curveList.getSelectedValue(); cbs.setInterpolateEndpoints(interpolateEndpointsCheckBox.isSelected()); } else if (src == interpolateFirstCheckBox) { LagrangeCurve lc = (LagrangeCurve) curveList.getSelectedValue(); lc.setInterpolateFirst(interpolateFirstCheckBox.isSelected()); } else if (src == interpolateLastCheckBox) { LagrangeCurve lc = (LagrangeCurve) curveList.getSelectedValue(); lc.setInterpolateLast(interpolateLastCheckBox.isSelected()); } else if (src == closedCheckBox) { NaturalCubicSpline ncs = (NaturalCubicSpline) curveList.getSelectedValue(); ncs.setClosed(closedCheckBox.isSelected()); } else if (src == useDefaultIntervalCheckBox) { BSpline bs = (BSpline) curveList.getSelectedValue(); bs.setUseDefaultInterval(useDefaultIntervalCheckBox.isSelected()); } else if (src == knotVectorTypeComboBox) { BSpline bs = (BSpline) curveList.getSelectedValue(); int type = knotVectorTypeComboBox.getSelectedIndex(); bs.setKnotVectorType(type); useDefaultIntervalCheckBox.setEnabled(type != BSpline.NON_UNIFORM); knotVectorPanel.setDisabled(type != BSpline.NON_UNIFORM); knotVectorPanel.repaint(); } else if (src == useWeightVectorCheckBox) { boolean b = useWeightVectorCheckBox.isSelected(); NURBSpline ns = (NURBSpline) curveList.getSelectedValue(); ns.setUseWeightVector(b); weightVectorPanel.setDisabled(!b); weightVectorPanel.repaint(); } else if (src == closeButton) { Window w = SwingUtilities.windowForComponent(this); w.hide(); } else if (src == applyButton) { applySettings(); } repaintPanel.repaint(); } private void applySettings() { Component comp = null; try { Curve c = (Curve) curveList.getSelectedValue(); if (c != null) { comp = controlStringTextField; c.setGroupIterator(new GroupIterator(controlStringTextField.getText(), controlPath.numPoints())); } if (c instanceof BezierCurve) { BezierCurve bc = (BezierCurve) c; comp = tminTextField; double t_min = Double.parseDouble(tminTextField.getText()); comp = tmaxTextField; double t_max = Double.parseDouble(tmaxTextField.getText()); bc.setInterval(t_min, t_max); comp = sampleLimitTextField; bc.setSampleLimit(Integer.parseInt(sampleLimitTextField.getText())); } else if (c instanceof BSpline) { BSpline bs = (BSpline) c; comp = tminTextField; double t_min = Double.parseDouble(tminTextField.getText()); comp = tmaxTextField; double t_max = Double.parseDouble(tmaxTextField.getText()); bs.setInterval(t_min, t_max); comp = sampleLimitTextField; bs.setSampleLimit(Integer.parseInt(sampleLimitTextField.getText())); comp = degreeTextField; bs.setDegree(Integer.parseInt(degreeTextField.getText())); } else if (c instanceof CardinalSpline) { CardinalSpline cs = (CardinalSpline) c; comp = alphaTextField; cs.setAlpha(Double.parseDouble(alphaTextField.getText())); } else if (c instanceof LagrangeCurve) { LagrangeCurve lc = (LagrangeCurve) c; comp = baseIndexTextField; lc.setBaseIndex(Integer.parseInt(baseIndexTextField.getText())); comp = baseLengthTextField; lc.setBaseLength(Integer.parseInt(baseLengthTextField.getText())); } } catch (Throwable err) { JOptionPane.showMessageDialog(this, err, "ERROR", JOptionPane.ERROR_MESSAGE); } if (comp != null) comp.requestFocus(); } private Curve createCurve(String name) { ControlPath cp = controlPath; GroupIterator gi = new GroupIterator("0:n-1", cp.numPoints()); if (name.equals("Bezier Curve")) return new BezierCurve(cp, gi); if (name.equals("B-Spline")) return new BSpline(cp, gi); if (name.equals("Cardinal Spline")) return new CardinalSpline(cp, gi); if (name.equals("Catmull-Rom Spline")) return new CatmullRomSpline(cp, gi); if (name.equals("Cubic B-Spline")) return new CubicBSpline(cp, gi); if (name.equals("Lagrange Curve")) return new LagrangeCurve(cp, gi); if (name.equals("Natural Cubic Spline")) return new NaturalCubicSpline(cp, gi); if (name.equals("NURB-Spline")) return new NURBSpline(cp, gi); return new Polyline(cp, gi); } public void valueChanged(ListSelectionEvent evt) { Curve c = (Curve) curveList.getSelectedValue(); if (c != null) { controlStringTextField.setText(c.getGroupIterator().getControlString()); connectCheckBox.setSelected(c.getConnect()); } editPanel.removeAll(); editPanel.add(closePanel, BorderLayout.SOUTH); if (c instanceof BezierCurve) { editPanel.add(getBezierCurvePanel(), BorderLayout.CENTER); BezierCurve bc = (BezierCurve) c; tminTextField.setText(String.valueOf(bc.t_min())); tmaxTextField.setText(String.valueOf(bc.t_max())); sampleLimitTextField.setText(String.valueOf(bc.getSampleLimit())); } else if (c instanceof BSpline) { boolean nurbs = (c instanceof NURBSpline); editPanel.add(getBSplinePanel(nurbs), BorderLayout.CENTER); BSpline bs = (BSpline) c; tminTextField.setText(String.valueOf(bs.t_min())); tmaxTextField.setText(String.valueOf(bs.t_max())); sampleLimitTextField.setText(String.valueOf(bs.getSampleLimit())); degreeTextField.setText(String.valueOf(bs.getDegree())); int type = bs.getKnotVectorType(); knotVectorTypeComboBox.setSelectedIndex(type); useDefaultIntervalCheckBox.setSelected(bs.getUseDefaultInterval()); useDefaultIntervalCheckBox.setEnabled(type != BSpline.NON_UNIFORM); knotVectorPanel.setValueVector(bs.getKnotVector()); if (nurbs) { NURBSpline ns = (NURBSpline) bs; boolean b = ns.getUseWeightVector(); weightVectorPanel.setValueVector(ns.getWeightVector()); useWeightVectorCheckBox.setSelected(b); weightVectorPanel.setDisabled(!b); } } else if (c instanceof CardinalSpline) { editPanel.add(getCardinalSplinePanel(), BorderLayout.CENTER); CardinalSpline cs = (CardinalSpline) c; alphaTextField.setText(String.valueOf(cs.getAlpha())); } else if (c instanceof CubicBSpline) { editPanel.add(getCubicBSplinePanel(), BorderLayout.CENTER); CubicBSpline cbs = (CubicBSpline) c; interpolateEndpointsCheckBox.setSelected(cbs.getInterpolateEndpoints()); } else if (c instanceof LagrangeCurve) { editPanel.add(getLagrangeCurvePanel(), BorderLayout.CENTER); LagrangeCurve lc = (LagrangeCurve) c; baseIndexTextField.setText(String.valueOf(lc.getBaseIndex())); baseLengthTextField.setText(String.valueOf(lc.getBaseLength())); interpolateFirstCheckBox.setSelected(interpolateFirstCheckBox.isSelected()); interpolateLastCheckBox.setSelected(interpolateLastCheckBox.isSelected()); knotVectorPanel.setValueVector(lc.getKnotVector()); knotVectorPanel.setDisabled(false); knotVectorPanel.repaint(); } else if (c instanceof NaturalCubicSpline) { editPanel.add(getNaturalCubicSplinePanel(), BorderLayout.CENTER); NaturalCubicSpline ncs = (NaturalCubicSpline) c; closedCheckBox.setSelected(ncs.getClosed()); } else if (c != null) { editPanel.add(getCurvePanel(), BorderLayout.CENTER); } revalidate(); repaint(); } public void valueInserted(ValueVector v, int index, double value) { repaintPanel.repaint(); } public void valueRemoved(ValueVector v, int index, double oldValue) { repaintPanel.repaint(); } public void valueChanged(ValueVector v, int index, double oldValue) { repaintPanel.repaint(); } private JPanel getCurvePanel() { JPanel panel = new JPanel(new BorderLayout()); JPanel p = new JPanel(new FlowLayout(FlowLayout.LEFT)); p.add(controlStringLabel); p.add(controlStringTextField); p.add(connectCheckBox); panel.add(p, BorderLayout.NORTH); return panel; } private JPanel getBezierCurvePanel() { JPanel panel = getCurvePanel(); JPanel p1 = new JPanel(new FlowLayout(FlowLayout.LEFT)); p1.add(tminLabel); p1.add(tminTextField); p1.add(tmaxLabel); p1.add(tmaxTextField); JPanel p2 = new JPanel(new FlowLayout(FlowLayout.LEFT)); p2.add(sampleLimitLabel); p2.add(sampleLimitTextField); JPanel p3 = new JPanel(new BorderLayout()); p3.add(p1, BorderLayout.NORTH); p3.add(p2, BorderLayout.CENTER); panel.add(p3, BorderLayout.CENTER); return panel; } private JPanel getBSplinePanel(boolean nurbs) { JPanel panel = getCurvePanel(); JPanel p1 = new JPanel(new FlowLayout(FlowLayout.LEFT)); p1.add(tminLabel); p1.add(tminTextField); p1.add(tmaxLabel); p1.add(tmaxTextField); JPanel p2 = new JPanel(new FlowLayout(FlowLayout.LEFT)); p2.add(sampleLimitLabel); p2.add(sampleLimitTextField); p2.add(degreeLabel); p2.add(degreeTextField); JPanel p3 = new JPanel(new FlowLayout(FlowLayout.LEFT)); p3.add(knotVectorTypeLabel); p3.add(knotVectorTypeComboBox); JPanel p4 = new JPanel(new FlowLayout(FlowLayout.LEFT)); p4.add(useDefaultIntervalCheckBox); if (nurbs) p4.add(useWeightVectorCheckBox); JPanel p5 = new JPanel(new BorderLayout()); p5.add(p3, BorderLayout.NORTH); p5.add(p4, BorderLayout.CENTER); JPanel p6 = new JPanel(new BorderLayout()); p6.add(p2, BorderLayout.NORTH); p6.add(p5, BorderLayout.CENTER); JPanel p7 = new JPanel(new BorderLayout()); p7.add(p1, BorderLayout.NORTH); p7.add(p6, BorderLayout.CENTER); JPanel p8 = new JPanel(new BorderLayout()); p8.add(p7, BorderLayout.NORTH); JPanel vvp = null; if (nurbs) { vvp = new JPanel(new GridLayout(1,2)); vvp.add(knotVectorPanel); vvp.add(weightVectorPanel); } else vvp = knotVectorPanel; p8.add(vvp, BorderLayout.CENTER); panel.add(p8, BorderLayout.CENTER); return panel; } private JPanel getCardinalSplinePanel() { JPanel panel = getCurvePanel(); JPanel p1 = new JPanel(new FlowLayout(FlowLayout.LEFT)); p1.add(alphaLabel); p1.add(alphaTextField); panel.add(p1, BorderLayout.CENTER); return panel; } private JPanel getCubicBSplinePanel() { JPanel panel = getCurvePanel(); JPanel p1 = new JPanel(new FlowLayout(FlowLayout.LEFT)); p1.add(interpolateEndpointsCheckBox); panel.add(p1, BorderLayout.CENTER); return panel; } private JPanel getLagrangeCurvePanel() { JPanel panel = getCurvePanel(); JPanel p1 = new JPanel(new FlowLayout(FlowLayout.LEFT)); p1.add(baseIndexLabel); p1.add(baseIndexTextField); p1.add(baseLengthLabel); p1.add(baseLengthTextField); JPanel p2 = new JPanel(new FlowLayout(FlowLayout.LEFT)); p2.add(interpolateFirstCheckBox); p2.add(interpolateLastCheckBox); JPanel p3 = new JPanel(new BorderLayout()); p3.add(p1, BorderLayout.NORTH); p3.add(p2, BorderLayout.CENTER); JPanel p4 = new JPanel(new BorderLayout()); p4.add(p3, BorderLayout.NORTH); p4.add(knotVectorPanel, BorderLayout.CENTER); panel.add(p4, BorderLayout.CENTER); return panel; } private JPanel getNaturalCubicSplinePanel() { JPanel panel = getCurvePanel(); JPanel p1 = new JPanel(new FlowLayout(FlowLayout.LEFT)); p1.add(closedCheckBox); panel.add(p1, BorderLayout.CENTER); return panel; } }