package iiuf.swing.graph;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.GraphicsEnvironment;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Stroke;
import java.awt.BasicStroke;
import java.awt.Shape;
import java.util.ArrayList;
import java.util.Enumeration;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JPanel;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JCheckBox;
import javax.swing.JRadioButton;
import javax.swing.JColorChooser;
import javax.swing.JSlider;
import javax.swing.JComponent;
import javax.swing.AbstractButton;
import javax.swing.DefaultListCellRenderer;
import javax.swing.ButtonGroup;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.basic.BasicComboBoxEditor;
import iiuf.awt.Awt;
import iiuf.util.Attributable;
import iiuf.util.Preferences;
import iiuf.swing.Resource;
import iiuf.swing.LocatedIcon;
import iiuf.swing.JNumberField;
import iiuf.swing.SetSelectionModel;
import iiuf.util.graph.GraphNode;
/**
Editor panel for edge style.<p>
(c) 2001, DIUF<p>
@author $Author: ohitz $
@version $Name: $ $Revision: 1.1 $
*/
public class EdgeEditor
extends
JPanel
implements
ChangeListener
{
static final String GP_NULL = "Graph panel not set. Call setGraphPanel() first.";
static final String PLINE_WIDTH = "edge_editor.line_width";
static final String PCOLOR = "edge_editor.line_color";
static final String PDASH = "edge_editor.line_dash";
static final String PCAP = "edge_editor.line_cap";
static final String PMARKER = "edge_editor.line_marker";
protected GraphPanel gp;
Color foreground;
BasicStroke stroke = new BasicStroke();
EdgeMarker[] markers = new EdgeMarker[0];
double[] markerPos = new double[0];
JComboBox lineWidth = new JComboBox(new Stroke[] {
new StrokeWrapper(new BasicStroke(1), LINE_WIDTH), new StrokeWrapper(new BasicStroke(2), LINE_WIDTH),
new StrokeWrapper(new BasicStroke(3), LINE_WIDTH), new StrokeWrapper(new BasicStroke(4), LINE_WIDTH),
new StrokeWrapper(new BasicStroke(6), LINE_WIDTH), new StrokeWrapper(new BasicStroke(8), LINE_WIDTH)
});
JComboBox dash = new JComboBox(new Stroke[] {
new StrokeWrapper(new BasicStroke(1), DASH),
new StrokeWrapper(StrokeWrapper.setDash(new BasicStroke(1), new float[]{1, 1}, 0), DASH),
new StrokeWrapper(StrokeWrapper.setDash(new BasicStroke(1), new float[]{2, 2}, 0), DASH),
new StrokeWrapper(StrokeWrapper.setDash(new BasicStroke(1), new float[]{4, 4}, 0), DASH),
new StrokeWrapper(StrokeWrapper.setDash(new BasicStroke(1), new float[]{5, 2, 1, 2}, 0), DASH),
});
JComboBox cap = new JComboBox(new Stroke[] {
new StrokeWrapper(StrokeWrapper.setEndCap(new BasicStroke(9), BasicStroke.CAP_BUTT), CAP),
new StrokeWrapper(StrokeWrapper.setEndCap(new BasicStroke(9), BasicStroke.CAP_ROUND), CAP),
new StrokeWrapper(StrokeWrapper.setEndCap(new BasicStroke(9), BasicStroke.CAP_SQUARE), CAP),
});
JComboBox marker = new JComboBox(new MarkerWrapper[] {
new MarkerWrapper(new EdgeMarker[0], new double[0])});
ColorIcon color = new ColorIcon();
JLabel colorc = new JLabel(color);
int selectLineWidthCnt;
int selectDashCnt;
int selectCapCnt;
int markerPrefIdx;
public EdgeEditor(GraphPanel graphPanel) {
setGraphPanel(graphPanel);
colorc.setBorder(new EmptyBorder(5, 5, 5, 5));
foreground = (Color)Preferences.get(PCOLOR);
lineWidth.setEditor(new LineWidthEditor());
lineWidth.setRenderer(new StrokeRenderer());
lineWidth.setEditable(true);
lineWidth.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setLineWidths();
}
});
selectLineWidth(((Float)Preferences.get(PLINE_WIDTH, new Float(1.0))).floatValue());
dash.setRenderer(new StrokeRenderer());
dash.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setDashes();
}
});
dash.setSelectedIndex(((Integer)Preferences.get(PDASH, new Integer(0))).intValue());
setDashes();
cap.setRenderer(new StrokeRenderer());
cap.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setCaps();
}
});
cap.setSelectedIndex(((Integer)Preferences.get(PCAP, new Integer(0))).intValue());
setCaps();
marker.setRenderer(new MarkerRenderer());
marker.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setMarkers();
}
});
markerPrefIdx = ((Integer)Preferences.get(PMARKER, new Integer(0))).intValue();
setLayout(new GridBagLayout());
add(lineWidth, Awt.constraints(false));
add(colorc, Awt.constraints(false));
add(dash, Awt.constraints(true));
GridBagConstraints gc = Awt.constraints(false, GridBagConstraints.HORIZONTAL);
gc.gridwidth = 2;
add(marker, gc);
add(cap, Awt.constraints(true));
colorc.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
int x = e.getX() - color.getX();
int y = e.getY() - color.getY();
if(x >= 0 && x < 17 && y >= 0 && y < 17) {
Color c = JColorChooser.showDialog(EdgeEditor.this, "Foreground color", foreground);
if(c != null) {
foreground = c;
setForegrounds();
}
e.getComponent().repaint();
}
}
});
set(null);
}
public void addDash(float[] dashArray, int dashPhase) {
dash.addItem(new StrokeWrapper(StrokeWrapper.setDash(new BasicStroke(1), dashArray, dashPhase), DASH));
}
public void addMarkers(EdgeMarker[] markers_, double[] markerPos_) {
marker.addItem(new MarkerWrapper(markers_, markerPos_));
if(marker.getItemCount() == markerPrefIdx + 1) {
marker.setSelectedIndex(markerPrefIdx);
markers = markers_;
markerPos = markerPos_;
} else
setMarkers();
}
void setForegrounds() {
if(foreground == null) return;
if(gp != null) {
Object[] sel = gp.getSelectionModel().getSelection();
for(int i = 0; i < sel.length; i++)
if(sel[i] instanceof Attributable) {
GraphEdge e = (GraphEdge)((Attributable)sel[i]).get(gp.GRAPH_EDGE);
if(e != null)
e.setColor(foreground);
}
}
Preferences.set(PCOLOR, foreground);
}
void setLineWidths() {
if(gp != null && selectLineWidthCnt == 0) {
Object[] sel = gp.getSelectionModel().getSelection();
try {
float lw = Float.parseFloat((String)lineWidth.getEditor().getItem());
for(int i = 0; i < sel.length; i++)
if(sel[i] instanceof Attributable) {
GraphEdge e = (GraphEdge)((Attributable)sel[i]).get(gp.GRAPH_EDGE);
if(e != null)
e.setStroke(StrokeWrapper.setLineWidth(e.getStroke(), lw));
}
stroke = (BasicStroke)StrokeWrapper.setLineWidth(stroke, lw);
Preferences.set(PLINE_WIDTH, new Float(lw));
} catch(Exception e) {}
gp.repaint();
}
}
void setDashes() {
if(gp != null) {
Object[] sel = gp.getSelectionModel().getSelection();
StrokeWrapper s = (StrokeWrapper)dash.getSelectedItem();
for(int i = 0; i < sel.length; i++)
if(sel[i] instanceof Attributable) {
GraphEdge e = (GraphEdge)((Attributable)sel[i]).get(gp.GRAPH_EDGE);
if(e != null)
e.setStroke(StrokeWrapper.setDash(e.getStroke(), s.getDashArray(), s.getDashPhase()));
}
stroke = (BasicStroke)StrokeWrapper.setDash(stroke, s.getDashArray(), s.getDashPhase());
Preferences.set(PDASH, new Integer(dash.getSelectedIndex()));
gp.repaint();
}
}
void setCaps() {
if(gp != null) {
Object[] sel = gp.getSelectionModel().getSelection();
StrokeWrapper s = (StrokeWrapper)cap.getSelectedItem();
for(int i = 0; i < sel.length; i++)
if(sel[i] instanceof Attributable) {
GraphEdge e = (GraphEdge)((Attributable)sel[i]).get(gp.GRAPH_EDGE);
if(e != null)
e.setStroke(StrokeWrapper.setEndCap(e.getStroke(), s.getEndCap()));
}
stroke = (BasicStroke)StrokeWrapper.setEndCap(stroke, s.getEndCap());
Preferences.set(PCAP, new Integer(cap.getSelectedIndex()));
gp.repaint();
}
}
void setMarkers() {
if(gp != null) {
Object[] sel = gp.getSelectionModel().getSelection();
MarkerWrapper s = (MarkerWrapper)marker.getSelectedItem();
for(int i = 0; i < sel.length; i++)
if(sel[i] instanceof Attributable) {
GraphEdge e = (GraphEdge)((Attributable)sel[i]).get(gp.GRAPH_EDGE);
if(e != null) {
e.setMarkers(s.markers, s.markerPos);
}
}
markers = s.markers;
markerPos = s.markerPos;
Preferences.set(PMARKER, new Integer(marker.getSelectedIndex()));
gp.repaint();
}
}
public void setGraphPanel(GraphPanel graphPanel) {
if(graphPanel == gp) return;
if(gp != null)
gp.getSelectionModel().removeChangeListener(this);
gp = graphPanel;
gp.getSelectionModel().addChangeListener(this);
}
public Dimension getMaximumSize() {
return getPreferredSize();
}
public void stateChanged(ChangeEvent e) {
SetSelectionModel sm = (SetSelectionModel)e.getSource();
Attributable[] sel = (Attributable[])sm.getSelection(Attributable.class);
int edgCnt = 0;
for(int i = 0; i < sel.length; i++)
if(sel[i].get(gp.GRAPH_EDGE) != null)
edgCnt++;
iiuf.swing.graph.GraphEdge[] edges = new iiuf.swing.graph.GraphEdge[edgCnt];
edgCnt = 0;
for(int i = 0; i < sel.length; i++) {
iiuf.swing.graph.GraphEdge ed = (iiuf.swing.graph.GraphEdge)sel[i].get(gp.GRAPH_EDGE);
if(ed != null)
edges[edgCnt++] = ed;
}
set(edges);
}
void set(GraphEdge[] e) {
float lw = -1;
float[] da = null;
int cp = -1;
if(e != null && e.length != 0) {
foreground = e[0].getColor();
for(int i = 0; i < e.length; i++) {
if(foreground != null && !e[i].getColor().equals(foreground))
foreground = null;
if(e[i].getStroke() instanceof BasicStroke) {
BasicStroke b = (BasicStroke)e[i].getStroke();
lw = b.getLineWidth();
cp = b.getEndCap();
da = b.getDashArray();
}
}
if(e.length > 0)
selectDash(da);
if(lw != -1)
selectLineWidth(lw);
if(cp != -1)
selectCap(cp);
}
repaint();
}
void selectLineWidth(float width) {
selectLineWidthCnt++;
for(int i = 0; i < lineWidth.getItemCount(); i++)
if(((StrokeWrapper)lineWidth.getItemAt(i)).getLineWidth() == width) {
lineWidth.setSelectedIndex(i);
selectLineWidthCnt--;
return;
}
selectLineWidthCnt--;
}
void selectDash(float[] da) {
selectDashCnt++;
if(da == null)
dash.setSelectedIndex(0);
else {
for(int i = 0; i < dash.getItemCount(); i++)
if(da.equals(((StrokeWrapper)dash.getItemAt(i)).getDashArray())) {
dash.setSelectedIndex(i);
selectDashCnt--;
return;
}
}
selectDashCnt--;
}
void selectCap(int ec) {
selectCapCnt++;
for(int i = 0; i < cap.getItemCount(); i++) {
StrokeWrapper s = (StrokeWrapper)cap.getItemAt(i);
if(s.getEndCap() == ec) {
cap.setSelectedIndex(i);
selectCapCnt--;
return;
}
}
selectCapCnt--;
}
/*
void selectMarker(int ec) {
selectMarkerCnt++;
for(int i = 0; i < cap.getItemCount(); i++) {
Object o = cap.getItemAt(i);
if(o instanceof StrokeWrapper && ((StrokeWrapper)o).getEndCap() == ec) {
cap.setSelectedIndex(i);
selectCapCnt--;
return;
}
}
selectMarkerCnt--;
}
*/
public Color getColor() {
return foreground;
}
public Stroke getStroke() {
return stroke;
}
public double[] getMarkerPos() {
return markerPos;
}
public EdgeMarker[] getMarkers() {
return markers;
}
static class LineWidthEditor extends BasicComboBoxEditor {
LineWidthEditor() {
editor = new JNumberField(3, 0.0, 100.0);
}
}
class ColorIcon extends LocatedIcon {
ColorIcon() {
super(Resource.ONE_COLOR);
}
public void paintIcon(Component c, Graphics g, int x, int y) {
super.paintIcon(c, g, x, y);
if(foreground != null) {
g.setColor(foreground);
g.fillRect(x + 1, y + 1, 14, 14);
}
}
}
static final int LINE_WIDTH = 0;
static final int DASH = 1;
static final int CAP = 2;
static class StrokeWrapper implements Stroke {
Stroke stroke;
int mode;
StrokeWrapper(Stroke stroke_, int mode_) {
stroke = stroke_;
mode = mode_;
}
public Shape createStrokedShape(Shape p) {
return stroke.createStrokedShape(p);
}
public String toString() {
if(stroke instanceof BasicStroke && mode == LINE_WIDTH)
return ((BasicStroke)stroke).getLineWidth() + "";
return " ";
}
float getLineWidth() {
if(stroke instanceof BasicStroke)
return ((BasicStroke)stroke).getLineWidth();
return 0;
}
static Stroke setLineWidth(Stroke s, float lw) {
if(s instanceof BasicStroke) {
BasicStroke b = (BasicStroke)s;
float[] da = b.getDashArray();
if(da != null) {
float[] dsa = new float[da.length];
for(int i = 0; i < dsa.length; i++)
dsa[i] = da[i] * (lw / b.getLineWidth());
da = dsa;
}
return new BasicStroke(lw,
b.getEndCap(),
b.getLineJoin(),
b.getMiterLimit(),
da,
b.getDashPhase());
}
else return s;
}
float[] getDashArray() {
if(stroke instanceof BasicStroke)
return ((BasicStroke)stroke).getDashArray();
return new float[0];
}
float getDashPhase() {
if(stroke instanceof BasicStroke)
return ((BasicStroke)stroke).getDashPhase();
return 0;
}
static Stroke setDash(Stroke s, float[] da, float phase) {
if(s instanceof BasicStroke) {
BasicStroke b = (BasicStroke)s;
if(da != null) {
float[] dsa = new float[da.length];
for(int i = 0; i < dsa.length; i++)
dsa[i] = da[i] * b.getLineWidth();
da = dsa;
}
return new BasicStroke(b.getLineWidth(),
b.CAP_BUTT,
b.getLineJoin(),
b.getMiterLimit(),
da,
phase);
}
else return s;
}
int getEndCap() {
if(stroke instanceof BasicStroke)
return ((BasicStroke)stroke).getEndCap();
return -1;
}
static Stroke setEndCap(Stroke s, int cap) {
if(s instanceof BasicStroke) {
BasicStroke b = (BasicStroke)s;
return new BasicStroke(b.getLineWidth(),
cap,
b.getLineJoin(),
b.getMiterLimit(),
b.getDashArray(),
b.getDashPhase());
}
else return s;
}
}
static Dimension SRDIM = new Dimension(40, 18);
static BasicStroke BASIC = new BasicStroke();
static class StrokeRenderer
extends
DefaultListCellRenderer
{
StrokeWrapper stroke;
public Component getListCellRendererComponent(JList list,
Object value,
int index,
boolean sel,
boolean hasFocus) {
super.getListCellRendererComponent(list, value, index, sel, hasFocus);
stroke = (StrokeWrapper)value;
return this;
}
public Dimension getPreferredSize() {
return SRDIM;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setStroke(stroke.stroke);
int h = getHeight();
int w = getWidth();
switch(stroke.mode) {
case LINE_WIDTH:
g.drawLine(30, h / 2, w, h / 2);
break;
case CAP:
g.drawLine(10, h / 2, w - 10, h / 2);
g2.setStroke(BASIC);
g.setColor(Color.white);
g.drawLine(10, h / 2, w - 10, h / 2);
break;
default:
g.drawLine(0, h / 2, w, h / 2);
break;
}
}
}
static class MarkerWrapper {
EdgeMarker[] markers;
double[] markerPos;
MarkerWrapper(EdgeMarker[] markers_, double[] markerPos_) {
markers = markers_;
markerPos = markerPos_;
}
public String toString() {
return " ";
}
}
static Dimension MRDIM = new Dimension(50, 18);
static class MarkerRenderer
extends
DefaultListCellRenderer
{
MarkerWrapper marker;
public Component getListCellRendererComponent(JList list,
Object value,
int index,
boolean sel,
boolean hasFocus) {
super.getListCellRendererComponent(list, value, index, sel, hasFocus);
marker = (MarkerWrapper)value;
return this;
}
public Dimension getPreferredSize() {
return MRDIM;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
int h = getHeight();
int w = getWidth();
g.drawLine(10, h / 2, w - 10, h / 2);
for(int i = 0; i < marker.markers.length; i++) {
int yoff = (h / 2) - marker.markers[i].getBaseline();
int mw = Math.min(w - 20, marker.markers[i].getPreferredSize().width);
int xoff = (int)(10 + marker.markerPos[i] * (w - 20) - (marker.markerPos[i] * mw));
g.translate(xoff, yoff);
marker.markers[i].paint(g, mw);
g.translate(-xoff, -yoff);
}
}
}
}
/*
$Log: EdgeEditor.java,v $
Revision 1.1 2002/07/11 12:09:52 ohitz
Initial checkin
Revision 1.3 2001/03/11 17:59:38 schubige
Fixed various soundium and iiuf.swing.graph bugs
Revision 1.2 2001/03/09 21:24:58 schubige
Added preferences to edge editor
Revision 1.1 2001/03/09 15:55:08 schubige
Added markers to graph panel
Revision 1.2 2001/03/07 17:36:28 schubige
soundium properties panel beta
Revision 1.1 2001/03/07 07:52:07 schubige
soundium properites panel
*/