package com.kreative.paint.palette;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.SortedSet;
import javax.swing.*;
import javax.swing.event.*;
import com.kreative.paint.PaintContext;
import com.kreative.paint.PaintContextListener;
import com.kreative.paint.document.draw.PaintSettings;
import com.kreative.paint.material.MaterialManager;
import com.kreative.paint.material.stroke.Arrowhead;
import com.kreative.paint.material.stroke.EndCap;
import com.kreative.paint.material.stroke.PowerStroke;
public class StrokePresetPanel extends PaintContextPanel {
private static final long serialVersionUID = 1L;
private static final int ROW_HEIGHT = 16;
private static final int ROW_WIDTH = 100;
private static final int ARROW_OFFSET = 16;
private SortedSet<Float> widths;
private SortedSet<Integer> mults;
private LinkedHashSet<float[]> dashes;
private LinkedHashSet<Arrowhead> arrows;
private JList widthView;
private JList multView;
private JList dashView;
private JList arrowView1;
private JList arrowView2;
private JPopupMenu strokePopup;
private JPopupMenu arrowPopup1;
private JPopupMenu arrowPopup2;
private boolean eventexec = false;
public StrokePresetPanel(PaintContext pc, MaterialManager mm) {
super(pc, CHANGED_STROKE);
widths = mm.strokeLoader().getLineWidths();
mults = mm.strokeLoader().getLineMultiplicities();
dashes = mm.strokeLoader().getLineDashes();
arrows = mm.strokeLoader().getLineArrowheads();
widthView = new JList(widths.toArray(new Float[0]));
multView = new JList(mults.toArray(new Integer[0]));
dashView = new JList(dashes.toArray(new float[0][]));
arrowView1 = new JList(arrows.toArray(new Arrowhead[0]));
arrowView2 = new JList(arrows.toArray(new Arrowhead[0]));
widthView.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
multView.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
dashView.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
arrowView1.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
arrowView2.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
widthView.setVisibleRowCount(10);
multView.setVisibleRowCount(10);
dashView.setVisibleRowCount(10);
arrowView1.setVisibleRowCount(10);
arrowView2.setVisibleRowCount(10);
widthView.setCellRenderer(new DefaultListCellRenderer() {
private static final long serialVersionUID = 1L;
public Component getListCellRendererComponent(JList list, Object value, int index, boolean sel, boolean focus) {
JLabel l = (JLabel)super.getListCellRendererComponent(list, value, index, sel, focus);
l.setText(null);
l.setBorder(BorderFactory.createEmptyBorder());
l.setOpaque(true);
l.setBackground(new Color((sel ? SystemColor.textHighlight : SystemColor.text).getRGB(), true));
l.setToolTipText(PaletteUtilities.messages.getString("stroke.tooltip.width").replace("$", value.toString().replaceFirst("\\.0$", "")));
BufferedImage bi = new BufferedImage(Math.max(ROW_WIDTH, list.getWidth()), ROW_HEIGHT, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bi.createGraphics();
g.setPaint(new Color((sel ? SystemColor.textHighlightText : SystemColor.textText).getRGB(), true));
g.setStroke(PowerStroke.DEFAULT.deriveLineWidth(((Number)value).floatValue()));
g.drawLine(0, bi.getHeight()/2, bi.getWidth()-1, bi.getHeight()/2);
g.dispose();
l.setIcon(new ImageIcon(bi));
return l;
}
});
multView.setCellRenderer(new DefaultListCellRenderer() {
private static final long serialVersionUID = 1L;
public Component getListCellRendererComponent(JList list, Object value, int index, boolean sel, boolean focus) {
JLabel l = (JLabel)super.getListCellRendererComponent(list, value, index, sel, focus);
l.setText(null);
l.setBorder(BorderFactory.createEmptyBorder());
l.setOpaque(true);
l.setBackground(new Color((sel ? SystemColor.textHighlight : SystemColor.text).getRGB(), true));
l.setToolTipText(PaletteUtilities.messages.getString("stroke.tooltip.multiplicity").replace("$", value.toString()));
BufferedImage bi = new BufferedImage(Math.max(ROW_WIDTH, list.getWidth()), ROW_HEIGHT, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bi.createGraphics();
g.setPaint(new Color((sel ? SystemColor.textHighlightText : SystemColor.textText).getRGB(), true));
g.setStroke(PowerStroke.DEFAULT.deriveMultiplicity(((Number)value).intValue()));
g.drawLine(0, bi.getHeight()/2, bi.getWidth()-1, bi.getHeight()/2);
g.dispose();
l.setIcon(new ImageIcon(bi));
return l;
}
});
dashView.setCellRenderer(new DefaultListCellRenderer() {
private static final long serialVersionUID = 1L;
public Component getListCellRendererComponent(JList list, Object value, int index, boolean sel, boolean focus) {
JLabel l = (JLabel)super.getListCellRendererComponent(list, value, index, sel, focus);
l.setText(null);
l.setBorder(BorderFactory.createEmptyBorder());
l.setOpaque(true);
l.setBackground(new Color((sel ? SystemColor.textHighlight : SystemColor.text).getRGB(), true));
BufferedImage bi = new BufferedImage(Math.max(ROW_WIDTH, list.getWidth()), ROW_HEIGHT, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bi.createGraphics();
g.setPaint(new Color((sel ? SystemColor.textHighlightText : SystemColor.textText).getRGB(), true));
g.setStroke(PowerStroke.DEFAULT.deriveEndCap(EndCap.BUTT).deriveDashArray((float[])value));
g.drawLine(0, bi.getHeight()/2, bi.getWidth()-1, bi.getHeight()/2);
g.dispose();
l.setIcon(new ImageIcon(bi));
return l;
}
});
arrowView1.setCellRenderer(new DefaultListCellRenderer() {
private static final long serialVersionUID = 1L;
public Component getListCellRendererComponent(JList list, Object value, int index, boolean sel, boolean focus) {
JLabel l = (JLabel)super.getListCellRendererComponent(list, value, index, sel, focus);
l.setText(null);
l.setBorder(BorderFactory.createEmptyBorder());
l.setOpaque(true);
l.setBackground(new Color((sel ? SystemColor.textHighlight : SystemColor.text).getRGB(), true));
BufferedImage bi = new BufferedImage(Math.max(ROW_WIDTH, list.getWidth()), ROW_HEIGHT, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bi.createGraphics();
g.setPaint(new Color((sel ? SystemColor.textHighlightText : SystemColor.textText).getRGB(), true));
g.setStroke(PowerStroke.DEFAULT.deriveArrowOnStart((Arrowhead)value));
g.drawLine(ARROW_OFFSET, bi.getHeight()/2, bi.getWidth()-1, bi.getHeight()/2);
g.dispose();
l.setIcon(new ImageIcon(bi));
return l;
}
});
arrowView2.setCellRenderer(new DefaultListCellRenderer() {
private static final long serialVersionUID = 1L;
public Component getListCellRendererComponent(JList list, Object value, int index, boolean sel, boolean focus) {
JLabel l = (JLabel)super.getListCellRendererComponent(list, value, index, sel, focus);
l.setText(null);
l.setBorder(BorderFactory.createEmptyBorder());
l.setOpaque(true);
l.setBackground(new Color((sel ? SystemColor.textHighlight : SystemColor.text).getRGB(), true));
BufferedImage bi = new BufferedImage(Math.max(ROW_WIDTH, list.getWidth()), ROW_HEIGHT, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bi.createGraphics();
g.setPaint(new Color((sel ? SystemColor.textHighlightText : SystemColor.textText).getRGB(), true));
g.setStroke(PowerStroke.DEFAULT.deriveArrowOnEnd((Arrowhead)value));
g.drawLine(0, bi.getHeight()/2, bi.getWidth()-1-ARROW_OFFSET, bi.getHeight()/2);
g.dispose();
l.setIcon(new ImageIcon(bi));
return l;
}
});
widthView.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (!eventexec) {
eventexec = true;
if (StrokePresetPanel.this.pc != null) {
Stroke s = StrokePresetPanel.this.pc.getStroke();
if (s instanceof PowerStroke || s instanceof BasicStroke) {
PowerStroke ds = (s instanceof BasicStroke) ? PowerStroke.DEFAULT.deriveBasicStroke((BasicStroke)s) : (PowerStroke)s;
float width = ((Number)widthView.getSelectedValue()).floatValue();
StrokePresetPanel.this.pc.setStroke(ds.deriveLineWidth(width));
}
}
eventexec = false;
}
}
});
multView.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (!eventexec) {
eventexec = true;
if (StrokePresetPanel.this.pc != null) {
Stroke s = StrokePresetPanel.this.pc.getStroke();
if (s instanceof PowerStroke || s instanceof BasicStroke) {
PowerStroke ds = (s instanceof BasicStroke) ? PowerStroke.DEFAULT.deriveBasicStroke((BasicStroke)s) : (PowerStroke)s;
int mult = ((Number)multView.getSelectedValue()).intValue();
StrokePresetPanel.this.pc.setStroke(ds.deriveMultiplicity(mult));
}
}
eventexec = false;
}
}
});
dashView.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (!eventexec) {
eventexec = true;
if (StrokePresetPanel.this.pc != null) {
Stroke s = StrokePresetPanel.this.pc.getStroke();
if (s instanceof PowerStroke || s instanceof BasicStroke) {
PowerStroke ds = (s instanceof BasicStroke) ? PowerStroke.DEFAULT.deriveBasicStroke((BasicStroke)s) : (PowerStroke)s;
float[] dash = (float[])dashView.getSelectedValue();
StrokePresetPanel.this.pc.setStroke(ds.deriveDashArray(dash));
}
}
eventexec = false;
}
}
});
arrowView1.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (!eventexec) {
eventexec = true;
if (StrokePresetPanel.this.pc != null) {
Stroke s = StrokePresetPanel.this.pc.getStroke();
if (s instanceof PowerStroke || s instanceof BasicStroke) {
PowerStroke ds = (s instanceof BasicStroke) ? PowerStroke.DEFAULT.deriveBasicStroke((BasicStroke)s) : (PowerStroke)s;
Arrowhead a = (Arrowhead)arrowView1.getSelectedValue();
StrokePresetPanel.this.pc.setStroke(ds.deriveArrowOnStart(a));
}
}
eventexec = false;
}
}
});
arrowView2.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (!eventexec) {
eventexec = true;
if (StrokePresetPanel.this.pc != null) {
Stroke s = StrokePresetPanel.this.pc.getStroke();
if (s instanceof PowerStroke || s instanceof BasicStroke) {
PowerStroke ds = (s instanceof BasicStroke) ? PowerStroke.DEFAULT.deriveBasicStroke((BasicStroke)s) : (PowerStroke)s;
Arrowhead a = (Arrowhead)arrowView2.getSelectedValue();
StrokePresetPanel.this.pc.setStroke(ds.deriveArrowOnEnd(a));
}
}
eventexec = false;
}
}
});
setLayout(new GridLayout(1,0));
add(new JScrollPane(widthView, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER));
//add(new JScrollPane(multView, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER));
add(new JScrollPane(dashView, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER));
add(new JScrollPane(arrowView1, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER));
add(new JScrollPane(arrowView2, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER));
strokePopup = new StrokePopup();
arrowPopup1 = new ArrowPopup(false);
arrowPopup2 = new ArrowPopup(true);
update();
}
public void update() {
if (!eventexec) {
eventexec = true;
if (pc != null) {
widthView.clearSelection();
multView.clearSelection();
dashView.clearSelection();
arrowView1.clearSelection();
arrowView2.clearSelection();
Stroke s = pc.getStroke();
if (s instanceof PowerStroke) {
PowerStroke ds = (PowerStroke)s;
widthView.setSelectedValue(ds.lineWidth, true);
multView.setSelectedValue(ds.multiplicity, true);
{
ListModel m = dashView.getModel();
for (int i = 0; i < m.getSize(); i++) {
if (Arrays.equals((float[])m.getElementAt(i), ds.dashArray)) {
dashView.setSelectedIndex(i);
dashView.ensureIndexIsVisible(i);
break;
}
}
}
if (ds.arrowOnStart == null) {
ListModel m = arrowView1.getModel();
for (int i = 0; i < m.getSize(); i++) {
if (m.getElementAt(i) == null) {
arrowView1.setSelectedIndex(i);
arrowView1.ensureIndexIsVisible(i);
break;
}
}
} else {
arrowView1.setSelectedValue(ds.arrowOnStart, true);
}
if (ds.arrowOnEnd == null) {
ListModel m = arrowView2.getModel();
for (int i = 0; i < m.getSize(); i++) {
if (m.getElementAt(i) == null) {
arrowView2.setSelectedIndex(i);
arrowView2.ensureIndexIsVisible(i);
break;
}
}
} else {
arrowView2.setSelectedValue(ds.arrowOnEnd, true);
}
} else if (s instanceof BasicStroke) {
BasicStroke bs = (BasicStroke)s;
widthView.setSelectedValue(bs.getLineWidth(), true);
multView.setSelectedValue(1, true);
if (bs.getDashArray() == null) {
ListModel m = dashView.getModel();
for (int i = 0; i < m.getSize(); i++) {
if (m.getElementAt(i) == null) {
dashView.setSelectedIndex(i);
dashView.ensureIndexIsVisible(i);
break;
}
}
} else {
dashView.setSelectedValue(bs.getDashArray(), true);
}
ListModel m;
m = arrowView1.getModel();
for (int i = 0; i < m.getSize(); i++) {
if (m.getElementAt(i) == null) {
arrowView1.setSelectedIndex(i);
arrowView1.ensureIndexIsVisible(i);
break;
}
}
m = arrowView2.getModel();
for (int i = 0; i < m.getSize(); i++) {
if (m.getElementAt(i) == null) {
arrowView2.setSelectedIndex(i);
arrowView2.ensureIndexIsVisible(i);
break;
}
}
}
}
eventexec = false;
}
repaint();
}
public JPopupMenu getStrokePopup() {
return strokePopup;
}
public JPopupMenu getArrowPopup1() {
return arrowPopup1;
}
public JPopupMenu getArrowPopup2() {
return arrowPopup2;
}
private class WidthMenuItem extends JCheckBoxMenuItem implements PaintContextListener {
private static final long serialVersionUID = 1L;
private float width;
public WidthMenuItem(float width) {
this.width = width;
BufferedImage bi = new BufferedImage(ROW_WIDTH, ROW_HEIGHT, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bi.createGraphics();
g.setPaint(Color.black);
g.setStroke(PowerStroke.DEFAULT.deriveLineWidth(width));
g.drawLine(0, bi.getHeight()/2, bi.getWidth()-1, bi.getHeight()/2);
g.dispose();
setIcon(new ImageIcon(bi));
setText(null);
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (StrokePresetPanel.this.pc != null) {
Stroke s = StrokePresetPanel.this.pc.getStroke();
if (s instanceof PowerStroke || s instanceof BasicStroke) {
PowerStroke ds = (s instanceof BasicStroke) ? PowerStroke.DEFAULT.deriveBasicStroke((BasicStroke)s) : (PowerStroke)s;
StrokePresetPanel.this.pc.setStroke(ds.deriveLineWidth(WidthMenuItem.this.width));
}
}
}
});
StrokePresetPanel.this.pc.addPaintContextListener(WidthMenuItem.this);
paintSettingsChanged(StrokePresetPanel.this.pc, StrokePresetPanel.this.pc.getPaintSettings(), -1);
}
public void editingChanged(PaintContext src, boolean editingStroke, boolean editingBkgnd) {}
public void paintSettingsChanged(PaintContext src, PaintSettings ps, int delta) {
if ((delta & CHANGED_STROKE) != 0) {
Stroke s = ps.drawStroke;
if (s instanceof PowerStroke) {
WidthMenuItem.this.setSelected(((PowerStroke)s).lineWidth == width);
} else if (s instanceof BasicStroke) {
WidthMenuItem.this.setSelected(((BasicStroke)s).getLineWidth() == width);
} else {
WidthMenuItem.this.setSelected(false);
}
}
}
}
private class DashMenuItem extends JCheckBoxMenuItem implements PaintContextListener {
private static final long serialVersionUID = 1L;
private float[] dash;
public DashMenuItem(float[] dash) {
this.dash = dash;
BufferedImage bi = new BufferedImage(ROW_WIDTH, ROW_HEIGHT, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bi.createGraphics();
g.setPaint(Color.black);
g.setStroke(PowerStroke.DEFAULT.deriveEndCap(EndCap.BUTT).deriveDashArray(dash));
g.drawLine(0, bi.getHeight()/2, bi.getWidth()-1, bi.getHeight()/2);
g.dispose();
setIcon(new ImageIcon(bi));
setText(null);
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Stroke s = StrokePresetPanel.this.pc.getStroke();
if (s instanceof PowerStroke || s instanceof BasicStroke) {
PowerStroke ds = (s instanceof BasicStroke) ? PowerStroke.DEFAULT.deriveBasicStroke((BasicStroke)s) : (PowerStroke)s;
StrokePresetPanel.this.pc.setStroke(ds.deriveDashArray(DashMenuItem.this.dash));
}
}
});
StrokePresetPanel.this.pc.addPaintContextListener(DashMenuItem.this);
paintSettingsChanged(StrokePresetPanel.this.pc, StrokePresetPanel.this.pc.getPaintSettings(), -1);
}
public void editingChanged(PaintContext src, boolean editingStroke, boolean editingBkgnd) {}
public void paintSettingsChanged(PaintContext src, PaintSettings ps, int delta) {
if ((delta & CHANGED_STROKE) != 0) {
Stroke s = ps.drawStroke;
if (s instanceof PowerStroke) {
DashMenuItem.this.setSelected(Arrays.equals(((PowerStroke)s).dashArray, dash));
} else if (s instanceof BasicStroke) {
DashMenuItem.this.setSelected(Arrays.equals(((BasicStroke)s).getDashArray(), dash));
} else {
DashMenuItem.this.setSelected(false);
}
}
}
}
private class ArrowMenuItem extends JCheckBoxMenuItem implements PaintContextListener {
private static final long serialVersionUID = 1L;
private Arrowhead arrow;
private boolean right;
private ArrowMenuItem(Arrowhead arrow, boolean right) {
this.arrow = arrow;
this.right = right;
BufferedImage bi = new BufferedImage(ROW_WIDTH, ROW_HEIGHT, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bi.createGraphics();
g.setPaint(Color.black);
if (right) {
g.setStroke(PowerStroke.DEFAULT.deriveArrowOnEnd(arrow));
g.drawLine(0, bi.getHeight()/2, bi.getWidth()-1-ARROW_OFFSET, bi.getHeight()/2);
} else {
g.setStroke(PowerStroke.DEFAULT.deriveArrowOnStart(arrow));
g.drawLine(ARROW_OFFSET, bi.getHeight()/2, bi.getWidth()-1, bi.getHeight()/2);
}
g.dispose();
setIcon(new ImageIcon(bi));
setText(null);
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Stroke s = StrokePresetPanel.this.pc.getStroke();
if (s instanceof PowerStroke || s instanceof BasicStroke) {
PowerStroke ds = (s instanceof BasicStroke) ? PowerStroke.DEFAULT.deriveBasicStroke((BasicStroke)s) : (PowerStroke)s;
if (ArrowMenuItem.this.right) {
StrokePresetPanel.this.pc.setStroke(ds.deriveArrowOnEnd(ArrowMenuItem.this.arrow));
} else {
StrokePresetPanel.this.pc.setStroke(ds.deriveArrowOnStart(ArrowMenuItem.this.arrow));
}
}
}
});
StrokePresetPanel.this.pc.addPaintContextListener(ArrowMenuItem.this);
paintSettingsChanged(StrokePresetPanel.this.pc, StrokePresetPanel.this.pc.getPaintSettings(), -1);
}
public void editingChanged(PaintContext src, boolean editingStroke, boolean editingBkgnd) {}
public void paintSettingsChanged(PaintContext src, PaintSettings ps, int delta) {
if ((delta & CHANGED_STROKE) != 0) {
Stroke s = ps.drawStroke;
if (s instanceof PowerStroke || s instanceof BasicStroke) {
PowerStroke ds = (s instanceof BasicStroke) ? PowerStroke.DEFAULT.deriveBasicStroke((BasicStroke)s) : (PowerStroke)s;
Arrowhead psa = right ? ds.arrowOnEnd : ds.arrowOnStart;
ArrowMenuItem.this.setSelected(arrow == null ? psa == null : psa == null ? arrow == null : arrow.equals(psa));
} else {
ArrowMenuItem.this.setSelected(false);
}
}
}
}
private class ShowStrokeMenuItem extends JMenuItem {
private static final long serialVersionUID = 1L;
public ShowStrokeMenuItem(final JPopupMenu parent) {
super(PaletteUtilities.messages.getString("stroke.show"));
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Container c = StrokePresetPanel.this.getParent();
while (true) {
if (c == null) {
return;
} else if (c instanceof Window) {
Point p = MouseInfo.getPointerInfo().getLocation();
c.setLocation(p.x-64, p.y-8);
c.setVisible(true);
return;
} else {
c = c.getParent();
}
}
}
});
}
}
private class StrokePopup extends JPopupMenu {
private static final long serialVersionUID = 1L;
public StrokePopup() {
add(new ShowStrokeMenuItem(this));
addSeparator();
for (Float width : widths) {
add(new WidthMenuItem(width));
}
addSeparator();
for (float[] dash : dashes) {
add(new DashMenuItem(dash));
}
}
}
private class ArrowPopup extends JPopupMenu {
private static final long serialVersionUID = 1L;
public ArrowPopup(boolean right) {
add(new ShowStrokeMenuItem(this));
addSeparator();
for (Arrowhead arrow : arrows) {
add(new ArrowMenuItem(arrow, right));
}
}
}
}