/**
* MainPanel
*
* @author pquiring
*
* Date : Feb 8, 2012
*
*/
import javax.swing.*;
import javax.swing.filechooser.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.font.*;
import java.io.*;
import java.util.*;
import javaforce.*;
import javaforce.gl.*;
public class MainPanel extends javax.swing.JPanel implements MouseListener, MouseMotionListener, KeyListener, KeyEventDispatcher, ActionListener {
public static String version = "0.21";
/**
* Creates new form PaintPanel
*/
public MainPanel(JFrame frame, JApplet applet) {
try {
this.frame = frame;
PaintCanvas.mainPanel = this;
Border.panel = this;
initComponents();
setLayout(new PanelLayout()); //can't make netbeans work properly
addTab("untitled");
updateClr(foreColor, foreClr);
updateClr(backColor, backClr);
selBox.setSelected(true);
javax.swing.Timer timer = new javax.swing.Timer(250, this);
timer.start();
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(this);
selBox.doClick();
currentPath = JF.getUserPath() + "/Pictures";
thresholdSliderStateChanged(null);
alphaSliderStateChanged(null);
paintMode.setMaximumRowCount(paintMode.getItemCount()); //default is 8
rotateImg = new JFImage();
rotateImg.load(this.getClass().getResourceAsStream("rotate.png"));
pixel = new JFImage(1,1);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
group = new javax.swing.ButtonGroup();
toolbar1 = new javax.swing.JToolBar();
selBox = new javax.swing.JToggleButton();
fill = new javax.swing.JToggleButton();
pickColor = new javax.swing.JToggleButton();
pencil = new javax.swing.JToggleButton();
text = new javax.swing.JToggleButton();
curve = new javax.swing.JToggleButton();
line = new javax.swing.JToggleButton();
box = new javax.swing.JToggleButton();
circle = new javax.swing.JToggleButton();
sub = new javax.swing.JToggleButton();
jLabel3 = new javax.swing.JLabel();
rotateCW = new javax.swing.JButton();
rotateCCW = new javax.swing.JButton();
flipVert = new javax.swing.JButton();
flipHorz = new javax.swing.JButton();
scaleSize = new javax.swing.JButton();
jLabel4 = new javax.swing.JLabel();
fillMode = new javax.swing.JToggleButton();
fillAlpha = new javax.swing.JToggleButton();
fillEdge = new javax.swing.JToggleButton();
round = new javax.swing.JToggleButton();
selkeyclr = new javax.swing.JToggleButton();
jLabel5 = new javax.swing.JLabel();
selectFont = new javax.swing.JButton();
changeSize = new javax.swing.JButton();
backswap = new javax.swing.JButton();
toolbar2 = new javax.swing.JToolBar();
foreColor = new javax.swing.JButton();
swap = new javax.swing.JButton();
backColor = new javax.swing.JButton();
width = new javax.swing.JComboBox();
paintMode = new javax.swing.JComboBox();
colorLayer = new javax.swing.JComboBox();
layersButton = new javax.swing.JButton();
toolbar3 = new javax.swing.JToolBar();
jLabel1 = new javax.swing.JLabel();
threshold = new javax.swing.JLabel();
thresholdSlider = new javax.swing.JSlider();
jLabel2 = new javax.swing.JLabel();
alpha = new javax.swing.JLabel();
alphaSlider = new javax.swing.JSlider();
jLabel6 = new javax.swing.JLabel();
zoom = new javax.swing.JSlider();
zoomText = new javax.swing.JLabel();
tabs = new javax.swing.JTabbedPane();
status = new javax.swing.JTextField();
toolbar1.setFloatable(false);
toolbar1.setRollover(true);
group.add(selBox);
selBox.setIcon(new javax.swing.ImageIcon(getClass().getResource("/selbox.png"))); // NOI18N
selBox.setToolTipText("Selection Box");
selBox.setFocusable(false);
selBox.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
selBox.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
selBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
selBoxActionPerformed(evt);
}
});
toolbar1.add(selBox);
group.add(fill);
fill.setIcon(new javax.swing.ImageIcon(getClass().getResource("/fill.png"))); // NOI18N
fill.setToolTipText("Fill (uses threshold)");
fill.setFocusable(false);
fill.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
fill.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
fill.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
fillActionPerformed(evt);
}
});
toolbar1.add(fill);
group.add(pickColor);
pickColor.setIcon(new javax.swing.ImageIcon(getClass().getResource("/pickcolor.png"))); // NOI18N
pickColor.setToolTipText("Pick Color");
pickColor.setFocusable(false);
pickColor.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
pickColor.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
pickColor.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
pickColorActionPerformed(evt);
}
});
toolbar1.add(pickColor);
group.add(pencil);
pencil.setIcon(new javax.swing.ImageIcon(getClass().getResource("/pencil.png"))); // NOI18N
pencil.setToolTipText("Pencil");
pencil.setFocusable(false);
pencil.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
pencil.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
pencil.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
pencilActionPerformed(evt);
}
});
toolbar1.add(pencil);
group.add(text);
text.setIcon(new javax.swing.ImageIcon(getClass().getResource("/text.png"))); // NOI18N
text.setToolTipText("Text");
text.setFocusable(false);
text.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
text.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
text.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
textActionPerformed(evt);
}
});
toolbar1.add(text);
group.add(curve);
curve.setIcon(new javax.swing.ImageIcon(getClass().getResource("/curve.png"))); // NOI18N
curve.setToolTipText("Curve");
curve.setFocusable(false);
curve.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
curve.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
curve.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
curveActionPerformed(evt);
}
});
toolbar1.add(curve);
group.add(line);
line.setIcon(new javax.swing.ImageIcon(getClass().getResource("/line.png"))); // NOI18N
line.setToolTipText("Line");
line.setFocusable(false);
line.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
line.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
line.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
lineActionPerformed(evt);
}
});
toolbar1.add(line);
group.add(box);
box.setIcon(new javax.swing.ImageIcon(getClass().getResource("/box.png"))); // NOI18N
box.setToolTipText("Box");
box.setFocusable(false);
box.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
box.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
box.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
boxActionPerformed(evt);
}
});
toolbar1.add(box);
group.add(circle);
circle.setIcon(new javax.swing.ImageIcon(getClass().getResource("/circle.png"))); // NOI18N
circle.setToolTipText("Circle");
circle.setFocusable(false);
circle.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
circle.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
circle.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
circleActionPerformed(evt);
}
});
toolbar1.add(circle);
group.add(sub);
sub.setIcon(new javax.swing.ImageIcon(getClass().getResource("/sub.png"))); // NOI18N
sub.setToolTipText("Substitute Box - Changes backColor to foreColor within drawn Box (uses threshold)");
sub.setFocusable(false);
sub.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
sub.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
sub.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
subActionPerformed(evt);
}
});
toolbar1.add(sub);
jLabel3.setText(":");
toolbar1.add(jLabel3);
rotateCW.setIcon(new javax.swing.ImageIcon(getClass().getResource("/rotatecw.png"))); // NOI18N
rotateCW.setToolTipText("Rotate CW");
rotateCW.setFocusable(false);
rotateCW.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
rotateCW.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
rotateCW.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
rotateCWActionPerformed(evt);
}
});
toolbar1.add(rotateCW);
rotateCCW.setIcon(new javax.swing.ImageIcon(getClass().getResource("/rotateccw.png"))); // NOI18N
rotateCCW.setToolTipText("Rotate CCW");
rotateCCW.setFocusable(false);
rotateCCW.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
rotateCCW.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
rotateCCW.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
rotateCCWActionPerformed(evt);
}
});
toolbar1.add(rotateCCW);
flipVert.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flipvert.png"))); // NOI18N
flipVert.setToolTipText("Flip Vertical");
flipVert.setFocusable(false);
flipVert.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
flipVert.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
flipVert.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
flipVertActionPerformed(evt);
}
});
toolbar1.add(flipVert);
flipHorz.setIcon(new javax.swing.ImageIcon(getClass().getResource("/fliphorz.png"))); // NOI18N
flipHorz.setToolTipText("Fill Horizontal");
flipHorz.setFocusable(false);
flipHorz.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
flipHorz.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
flipHorz.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
flipHorzActionPerformed(evt);
}
});
toolbar1.add(flipHorz);
scaleSize.setIcon(new javax.swing.ImageIcon(getClass().getResource("/scale.png"))); // NOI18N
scaleSize.setToolTipText("Scale Image");
scaleSize.setFocusable(false);
scaleSize.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
scaleSize.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
scaleSize.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
scaleSizeActionPerformed(evt);
}
});
toolbar1.add(scaleSize);
jLabel4.setText(":");
toolbar1.add(jLabel4);
fillMode.setIcon(new javax.swing.ImageIcon(getClass().getResource("/fillmode.png"))); // NOI18N
fillMode.setToolTipText("Fill Mode");
fillMode.setFocusable(false);
fillMode.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
fillMode.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
toolbar1.add(fillMode);
fillAlpha.setIcon(new javax.swing.ImageIcon(getClass().getResource("/fillAlpha.png"))); // NOI18N
fillAlpha.setToolTipText("Fill setting Transparent Level (Alpha)");
fillAlpha.setFocusable(false);
fillAlpha.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
fillAlpha.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
fillAlpha.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
fillAlphaActionPerformed(evt);
}
});
toolbar1.add(fillAlpha);
fillEdge.setIcon(new javax.swing.ImageIcon(getClass().getResource("/fillEdge.png"))); // NOI18N
fillEdge.setToolTipText("Fill edges only");
fillEdge.setFocusable(false);
fillEdge.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
fillEdge.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
toolbar1.add(fillEdge);
round.setIcon(new javax.swing.ImageIcon(getClass().getResource("/round.png"))); // NOI18N
round.setToolTipText("Rounded Box");
round.setFocusable(false);
round.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
round.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
round.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
roundActionPerformed(evt);
}
});
toolbar1.add(round);
selkeyclr.setIcon(new javax.swing.ImageIcon(getClass().getResource("/keyclr.png"))); // NOI18N
selkeyclr.setToolTipText("Place selection box except for background color pixels.");
selkeyclr.setFocusable(false);
selkeyclr.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
selkeyclr.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
toolbar1.add(selkeyclr);
jLabel5.setText(":");
toolbar1.add(jLabel5);
selectFont.setIcon(new javax.swing.ImageIcon(getClass().getResource("/font.png"))); // NOI18N
selectFont.setToolTipText("Select Font");
selectFont.setFocusable(false);
selectFont.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
selectFont.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
selectFont.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
selectFontActionPerformed(evt);
}
});
toolbar1.add(selectFont);
changeSize.setIcon(new javax.swing.ImageIcon(getClass().getResource("/size.png"))); // NOI18N
changeSize.setToolTipText("Change Image Size");
changeSize.setFocusable(false);
changeSize.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
changeSize.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
changeSize.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
changeSizeActionPerformed(evt);
}
});
toolbar1.add(changeSize);
backswap.setIcon(new javax.swing.ImageIcon(getClass().getResource("/backswap.png"))); // NOI18N
backswap.setToolTipText("Alternate background checker pattern.");
backswap.setFocusable(false);
backswap.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
backswap.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
backswap.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
backswapActionPerformed(evt);
}
});
toolbar1.add(backswap);
toolbar2.setFloatable(false);
toolbar2.setRollover(true);
foreColor.setText("ForeColor");
foreColor.setToolTipText("Fore Color");
foreColor.setFocusable(false);
foreColor.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
foreColor.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
foreColor.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
foreColorActionPerformed(evt);
}
});
toolbar2.add(foreColor);
swap.setIcon(new javax.swing.ImageIcon(getClass().getResource("/swap.png"))); // NOI18N
swap.setToolTipText("Swap Colors");
swap.setFocusable(false);
swap.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
swap.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
swap.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
swapActionPerformed(evt);
}
});
toolbar2.add(swap);
backColor.setText("BackColor");
backColor.setToolTipText("Back Color");
backColor.setFocusable(false);
backColor.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
backColor.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
backColor.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
backColorActionPerformed(evt);
}
});
toolbar2.add(backColor);
width.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "1px", "2px", "3px", "4px" }));
width.setToolTipText("Line Width");
width.setMaximumSize(new java.awt.Dimension(50, 28));
toolbar2.add(width);
paintMode.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Normal", "Transparent", "Gradient (cyclic)", "Gradient (acyclic)", "Gradient (radial - no cycle)", "Gradient (radial - reflect)", "Gradient (radial - repeat)", "Gaussian Blur", "Pixelate", "Chrome" }));
paintMode.setToolTipText("Paint Mode");
paintMode.setMaximumSize(new java.awt.Dimension(180, 28));
paintMode.setMinimumSize(new java.awt.Dimension(1, 1));
paintMode.setName(""); // NOI18N
paintMode.setPreferredSize(new java.awt.Dimension(180, 20));
paintMode.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
paintModeActionPerformed(evt);
}
});
toolbar2.add(paintMode);
colorLayer.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "ARGB", "A---", "-R--", "--G-", "---B" }));
colorLayer.setToolTipText("Color Layer");
colorLayer.setLightWeightPopupEnabled(false);
colorLayer.setMaximumSize(new java.awt.Dimension(70, 28));
colorLayer.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
colorLayerActionPerformed(evt);
}
});
toolbar2.add(colorLayer);
layersButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/layers.png"))); // NOI18N
layersButton.setToolTipText("Show Image Layers Window");
layersButton.setFocusable(false);
layersButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
layersButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
layersButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
layersButtonActionPerformed(evt);
}
});
toolbar2.add(layersButton);
toolbar3.setFloatable(false);
toolbar3.setRollover(true);
jLabel1.setText("Threshold:");
jLabel1.setToolTipText("0=match exact : 100=match all");
toolbar3.add(jLabel1);
threshold.setText("0%");
threshold.setToolTipText("0=match exact : 100=match all");
threshold.setMaximumSize(new java.awt.Dimension(30, 14));
threshold.setMinimumSize(new java.awt.Dimension(25, 14));
threshold.setPreferredSize(new java.awt.Dimension(25, 14));
toolbar3.add(threshold);
thresholdSlider.setMaximum(255);
thresholdSlider.setToolTipText("0=match exact : 100=match all");
thresholdSlider.setValue(0);
thresholdSlider.setEnabled(false);
thresholdSlider.setMaximumSize(new java.awt.Dimension(120, 23));
thresholdSlider.setMinimumSize(new java.awt.Dimension(100, 23));
thresholdSlider.setPreferredSize(new java.awt.Dimension(100, 23));
thresholdSlider.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
thresholdSliderStateChanged(evt);
}
});
toolbar3.add(thresholdSlider);
jLabel2.setText("Transparent:");
jLabel2.setToolTipText("0=opaque : 100=transparent");
toolbar3.add(jLabel2);
alpha.setText("0%");
alpha.setToolTipText("0=transparent : 100=opaque");
alpha.setMaximumSize(new java.awt.Dimension(30, 14));
alpha.setMinimumSize(new java.awt.Dimension(25, 14));
alpha.setPreferredSize(new java.awt.Dimension(25, 14));
toolbar3.add(alpha);
alphaSlider.setMaximum(255);
alphaSlider.setToolTipText("0=transparent : 100=opaque");
alphaSlider.setValue(0);
alphaSlider.setEnabled(false);
alphaSlider.setMaximumSize(new java.awt.Dimension(120, 23));
alphaSlider.setMinimumSize(new java.awt.Dimension(100, 23));
alphaSlider.setPreferredSize(new java.awt.Dimension(100, 23));
alphaSlider.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
alphaSliderStateChanged(evt);
}
});
toolbar3.add(alphaSlider);
jLabel6.setText("Zoom:");
toolbar3.add(jLabel6);
zoom.setMaximum(5);
zoom.setPaintLabels(true);
zoom.setValue(2);
zoom.setMaximumSize(new java.awt.Dimension(120, 23));
zoom.setMinimumSize(new java.awt.Dimension(100, 23));
zoom.setPreferredSize(new java.awt.Dimension(100, 23));
zoom.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
zoomStateChanged(evt);
}
});
toolbar3.add(zoom);
zoomText.setText("100%");
toolbar3.add(zoomText);
tabs.setTabLayoutPolicy(javax.swing.JTabbedPane.SCROLL_TAB_LAYOUT);
tabs.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
tabsStateChanged(evt);
}
});
status.setText("status");
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(toolbar2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(toolbar1, javax.swing.GroupLayout.DEFAULT_SIZE, 639, Short.MAX_VALUE)
.addComponent(status)
.addComponent(tabs)
.addComponent(toolbar3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(toolbar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(toolbar2, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(toolbar3, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(tabs, javax.swing.GroupLayout.PREFERRED_SIZE, 423, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(status, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
);
}// </editor-fold>//GEN-END:initComponents
private void tabsStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_tabsStateChanged
if (curIdx != -1) {
unselectTool(curIdx);
updateStatus();
}
int idx = getidx();
curIdx = idx;
if (idx == -1) return;
PaintCanvas pc = imageTabs.get(idx).pc;
int scale = (int)pc.scale;
switch (scale) {
case 25: zoom.setValue(0); break;
case 50: zoom.setValue(1); break;
case 100: zoom.setValue(2); break;
case 200: zoom.setValue(3); break;
case 400: zoom.setValue(4); break;
case 800: zoom.setValue(5); break;
}
colorLayer.setSelectedIndex(pc.getColorLayer());
if (layers != null) {
layers.setup(pc);
}
}//GEN-LAST:event_tabsStateChanged
private void selBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selBoxActionPerformed
if (selectedTool == tools.selBox) return;
unselectTool(getidx());
selectTool(tools.selBox);
}//GEN-LAST:event_selBoxActionPerformed
private void fillActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fillActionPerformed
if (selectedTool == tools.fill) return;
unselectTool(getidx());
selectTool(tools.fill);
}//GEN-LAST:event_fillActionPerformed
private void pickColorActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pickColorActionPerformed
if (selectedTool == tools.pickColor) return;
unselectTool(getidx());
selectTool(tools.pickColor);
}//GEN-LAST:event_pickColorActionPerformed
private void pencilActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pencilActionPerformed
if (selectedTool == tools.pencil) return;
unselectTool(getidx());
selectTool(tools.pencil);
}//GEN-LAST:event_pencilActionPerformed
private void textActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_textActionPerformed
if (selectedTool == tools.text) return;
unselectTool(getidx());
selectTool(tools.text);
}//GEN-LAST:event_textActionPerformed
private void curveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_curveActionPerformed
if (selectedTool == tools.curve) return;
unselectTool(getidx());
selectTool(tools.curve);
}//GEN-LAST:event_curveActionPerformed
private void lineActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_lineActionPerformed
if (selectedTool == tools.line) return;
unselectTool(getidx());
selectTool(tools.line);
}//GEN-LAST:event_lineActionPerformed
private void boxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_boxActionPerformed
if (selectedTool == tools.box) return;
unselectTool(getidx());
selectTool(tools.box);
}//GEN-LAST:event_boxActionPerformed
private void circleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_circleActionPerformed
if (selectedTool == tools.circle) return;
unselectTool(getidx());
selectTool(tools.circle);
}//GEN-LAST:event_circleActionPerformed
private void foreColorActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_foreColorActionPerformed
foreClr = selectClr(foreClr, "Select foreground colour");
updateClr(foreColor, foreClr);
}//GEN-LAST:event_foreColorActionPerformed
private void backColorActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_backColorActionPerformed
backClr = selectClr(backClr, "Select background colour");
updateClr(backColor, backClr);
}//GEN-LAST:event_backColorActionPerformed
private void subActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_subActionPerformed
if (selectedTool == tools.sub) return;
unselectTool(getidx());
selectTool(tools.sub);
}//GEN-LAST:event_subActionPerformed
private void swapActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_swapActionPerformed
swapColors();
}//GEN-LAST:event_swapActionPerformed
private void rotateCWActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rotateCWActionPerformed
PaintCanvas pc = imageTabs.get(getidx()).pc;
pc.rotateCW();
pc.resizeBorder();
pc.parentPanel.revalidate();
pc.repaint();
}//GEN-LAST:event_rotateCWActionPerformed
private void rotateCCWActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rotateCCWActionPerformed
PaintCanvas pc = imageTabs.get(getidx()).pc;
pc.rotateCCW();
pc.resizeBorder();
pc.parentPanel.revalidate();
pc.repaint();
}//GEN-LAST:event_rotateCCWActionPerformed
private void flipVertActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_flipVertActionPerformed
PaintCanvas pc = imageTabs.get(getidx()).pc;
pc.flipVert();
pc.repaint();
}//GEN-LAST:event_flipVertActionPerformed
private void flipHorzActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_flipHorzActionPerformed
PaintCanvas pc = imageTabs.get(getidx()).pc;
pc.flipHorz();
pc.repaint();
}//GEN-LAST:event_flipHorzActionPerformed
private void scaleSizeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_scaleSizeActionPerformed
GetXY dialog = new GetXY(frame, true, "Scale Image (percentage)", 100, 100);
dialog.setVisible(true);
if (dialog.w <= 0) return;
PaintCanvas pc = imageTabs.get(getidx()).pc;
int orgLayer = pc.getColorLayer();
if (orgLayer != 0) {
pc.changeColorLayer(0);
}
pc.scaleImage(dialog.w, dialog.h);
pc.resizeBorder();
if (orgLayer != 0) {
pc.changeColorLayer(orgLayer);
}
pc.parentPanel.revalidate();
pc.repaint();
}//GEN-LAST:event_scaleSizeActionPerformed
private void selectFontActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectFontActionPerformed
JFontChooser fc = new JFontChooser(null);
fc.showDialog(textFont);
Font newFont = fc.getFont();
if (newFont == null) return;
textFont = newFont;
}//GEN-LAST:event_selectFontActionPerformed
private void changeSizeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_changeSizeActionPerformed
PaintCanvas pc = imageTabs.get(getidx()).pc;
int ox = pc.getUnscaledWidth();
int oy = pc.getUnscaledHeight();
GetXY dialog = new GetXY(frame, true, "Set Image Size (pixels)", ox, oy);
dialog.setVisible(true);
if ((dialog.w <= 0) || (dialog.h <= 0)) return;
changeSize(pc, dialog.w - ox, dialog.h - oy, false);
}//GEN-LAST:event_changeSizeActionPerformed
private void roundActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_roundActionPerformed
if (round.isSelected()) {
GetXY getarcs = new GetXY(null, true, "Get Arc X/Y", arcX, arcY);
getarcs.setVisible(true);
if (getarcs.w == -1) {
round.setSelected(false);
return;
}
arcX = getarcs.w;
arcY = getarcs.h;
}
}//GEN-LAST:event_roundActionPerformed
private void colorLayerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_colorLayerActionPerformed
layerChanged();
}//GEN-LAST:event_colorLayerActionPerformed
private void paintModeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_paintModeActionPerformed
paintModeChanged();
}//GEN-LAST:event_paintModeActionPerformed
private void backswapActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_backswapActionPerformed
int idx = getidx();
if (idx == -1) return;
PaintCanvas pc = imageTabs.get(idx).pc;
if (pc == null) return;
pc.swap = !pc.swap;
pc.backClear();
pc.repaint();
}//GEN-LAST:event_backswapActionPerformed
private void layersButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_layersButtonActionPerformed
if (layers != null) {
layers.dispose();
} else {
int idx = getidx();
if (idx == -1) return;
PaintCanvas pc = imageTabs.get(idx).pc;
if (pc == null) return;
layers = new LayersWindow(this);
layers.setup(pc);
layers.setVisible(true);
Point pt = layersButton.getLocationOnScreen();
pt.y += layersButton.getHeight();
layers.setLocation(pt);
}
}//GEN-LAST:event_layersButtonActionPerformed
private void thresholdSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_thresholdSliderStateChanged
threshold.setText("" + getThresholdPercent() + "%");
}//GEN-LAST:event_thresholdSliderStateChanged
private void alphaSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_alphaSliderStateChanged
alpha.setText("" + getAlphaPercent() + "%");
}//GEN-LAST:event_alphaSliderStateChanged
private void zoomStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_zoomStateChanged
changeScale();
}//GEN-LAST:event_zoomStateChanged
private void fillAlphaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fillAlphaActionPerformed
if (selectedTool == tools.fill) {
alphaSlider.setEnabled(fillAlpha.isSelected());
}
}//GEN-LAST:event_fillAlphaActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel alpha;
private javax.swing.JSlider alphaSlider;
private javax.swing.JButton backColor;
private javax.swing.JButton backswap;
private javax.swing.JToggleButton box;
private javax.swing.JButton changeSize;
private javax.swing.JToggleButton circle;
private javax.swing.JComboBox colorLayer;
private javax.swing.JToggleButton curve;
private javax.swing.JToggleButton fill;
private javax.swing.JToggleButton fillAlpha;
private javax.swing.JToggleButton fillEdge;
private javax.swing.JToggleButton fillMode;
private javax.swing.JButton flipHorz;
private javax.swing.JButton flipVert;
private javax.swing.JButton foreColor;
private javax.swing.ButtonGroup group;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JLabel jLabel5;
private javax.swing.JLabel jLabel6;
private javax.swing.JButton layersButton;
private javax.swing.JToggleButton line;
private javax.swing.JComboBox paintMode;
private javax.swing.JToggleButton pencil;
private javax.swing.JToggleButton pickColor;
private javax.swing.JButton rotateCCW;
private javax.swing.JButton rotateCW;
private javax.swing.JToggleButton round;
private javax.swing.JButton scaleSize;
private javax.swing.JToggleButton selBox;
private javax.swing.JButton selectFont;
private javax.swing.JToggleButton selkeyclr;
private javax.swing.JTextField status;
private javax.swing.JToggleButton sub;
private javax.swing.JButton swap;
private javax.swing.JTabbedPane tabs;
private javax.swing.JToggleButton text;
private javax.swing.JLabel threshold;
private javax.swing.JSlider thresholdSlider;
private javax.swing.JToolBar toolbar1;
private javax.swing.JToolBar toolbar2;
private javax.swing.JToolBar toolbar3;
private javax.swing.JComboBox width;
private javax.swing.JSlider zoom;
private javax.swing.JLabel zoomText;
// End of variables declaration//GEN-END:variables
//global data
private JFrame frame;
public boolean active = true;
public enum tools { selBox, fill, pickColor, pencil, text, curve, line, box, circle, sub };
/* public enum modes {
Normal, Transparent, Gradient_cyclic, Gradient_acyclic, Gradient_radial_no_cycle
,Gradient_radial_reflect, Gradient_radial_repeat
};*/
public tools selectedTool = tools.selBox;
public int foreClr = 0x000000;
public int backClr = 0xffffff;
public int selClr = 0x000000;
public int init_x = 256, init_y = 256;
public boolean haveSel;
public int selX1, selY1, selX2, selY2;
public int clipBoard[], cbX, cbY;
public int cx[] = new int[4], cy[] = new int[4]; //curve points
public int cpt = -1; //current curve point (0-3)
public int gx[] = new int[2], gy[] = new int[2]; //grad points
public int gfx, gfy; //grad focus point (radial)
public boolean getGradPoints = false;
public boolean getGradFocus = false;
public String textText = "";
public Font textFont = new Font("Default", Font.PLAIN, 12);
public int curIdx = -1;
public int arcX = 25, arcY = 25;
public Config config;
public LayersWindow layers;
public JFImage rotateImg;
public JFImage pixel;
private String configFolder = JF.getUserPath();
private String configFile = "/.jfpaint.xml";
private String currentPath;
private int filter_radius;
private int filter_pixelSize; //pixelation
private float filter_amount, filter_exposure;
private float rotate;
private int scretchDir;
public static class Config {
public String code;
}
private void loadConfig() {
defaultConfig();
try {
XML xml = new XML();
FileInputStream fis = new FileInputStream(configFolder + configFile);
xml.read(fis);
xml.writeClass(config);
} catch (FileNotFoundException e1) {
defaultConfig();
} catch (Exception e2) {
JFLog.log(e2);
defaultConfig();
}
}
private void defaultConfig() {
config = new Config();
}
private void saveConfig() {
try {
XML xml = new XML();
FileOutputStream fos = new FileOutputStream(configFolder + configFile);
xml.readClass("jfpaint", config);
xml.write(fos);
fos.close();
} catch (Exception e) {
JFLog.log(e);
}
}
private class PanelLayout implements LayoutManager {
// private Vector<Component> list = new Vector<Component>();
public void addLayoutComponent(String string, Component cmp) {
// list.add(cmp);
}
public void removeLayoutComponent(Component cmp) {
// list.remove(cmp);
}
public Dimension preferredLayoutSize(Container c) {
return new Dimension(1, 1);
}
public Dimension minimumLayoutSize(Container c) {
return new Dimension(1, 1);
}
public void layoutContainer(Container c) {
//assumes images are added Center,East,South
try {
Dimension d1, d2, d3, ds;
int cnt = c.getComponentCount();
int x = c.getWidth();
int y = c.getHeight();
d1 = toolbar1.getPreferredSize();
toolbar1.setBounds(0, 0, x, d1.height);
d2 = toolbar2.getPreferredSize();
toolbar2.setBounds(0, d1.height, x, d2.height);
d3 = toolbar3.getPreferredSize();
toolbar3.setBounds(0, d1.height + d2.height, x, d3.height);
ds = status.getPreferredSize();
tabs.setBounds(0, d1.height + d2.height + d3.height, x, y - (d1.height + d2.height + d3.height + ds.height));
status.setBounds(0, y - ds.height, x, ds.height);
} catch (Exception e) {
e.printStackTrace();
}
}
}
private class ImageLayout implements LayoutManager {
// private Vector<Component> list = new Vector<Component>();
public void addLayoutComponent(String string, Component cmp) {
// list.add(cmp);
}
public void removeLayoutComponent(Component cmp) {
// list.remove(cmp);
}
public Dimension preferredLayoutSize(Container c) {
int cnt = c.getComponentCount();
if (cnt != 4) return new Dimension(1, 1);
PaintCanvas pc = (PaintCanvas)c.getComponent(0);
return new Dimension(pc.getScaledWidth() + 10, pc.getScaledHeight() + 10);
}
public Dimension minimumLayoutSize(Container c) {
return preferredLayoutSize(c);
}
public void layoutContainer(Container c) {
//assumes images are added Center,East,South,Corner
int cnt = c.getComponentCount();
if (cnt != 4) return;
PaintCanvas pc = (PaintCanvas)c.getComponent(0);
int x = pc.getScaledWidth();
int y = pc.getScaledHeight();
//System.out.println("layout:" + x + "," + y);
pc.setBounds(0, 0, x, y);
Component img1 = c.getComponent(1);
img1.setBounds(x, 0, 10, y);
Component img2 = c.getComponent(2);
img2.setBounds(0, y, x, 10);
Component img3 = c.getComponent(3);
img3.setBounds(x, y, 10, 10);
}
}
private class ImageTab {
PaintCanvas pc;
JPanel panel;
JScrollPane scroll;
File filename;
};
private Vector<ImageTab> imageTabs = new Vector<ImageTab>();
public void openTab() {
JFileChooser chooser = new JFileChooser();
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
chooser.addChoosableFileFilter(new FileNameExtensionFilter("JFPAINT", "jfpaint"));
chooser.addChoosableFileFilter(new FileNameExtensionFilter("JPEG", "jpg", "jpeg"));
chooser.addChoosableFileFilter(new FileNameExtensionFilter("PNG", "png"));
chooser.addChoosableFileFilter(new FileNameExtensionFilter("BMP", "bmp"));
chooser.addChoosableFileFilter(new FileNameExtensionFilter("XPM", "xpm"));
chooser.setMultiSelectionEnabled(false);
chooser.setCurrentDirectory(new File(currentPath));
if (chooser.showOpenDialog(this) != JFileChooser.APPROVE_OPTION) return;
loadTab(chooser.getSelectedFile().toString());
}
private void loadTab(String filename) {
if (filename.length() == 0) return;
int idx = getidx();
ImageTab tab = imageTabs.get(idx);
boolean emptyFile;
//check if current page is "untitled" and !dirty
if (tab.filename.toString().equals("untitled") && imageTabs.get(idx).pc.dirty == false) {
//load on current page
tab.filename = new File(filename);
emptyFile = tab.filename.length() == 0;
} else {
addTab("newfile");
idx = tabs.getTabCount() - 1;
tab = imageTabs.get(idx);
tab.filename = new File(filename);
emptyFile = tab.filename.length() == 0;
}
currentPath = tab.filename.getAbsoluteFile().getParent();
if (currentPath == null) currentPath = JF.getUserPath() + "/Pictures";
String name = tab.filename.toString();
int fidx = name.lastIndexOf("/");
if (fidx != -1) name = name.substring(fidx+1);
tabs.setTitleAt(idx, name);
PaintCanvas pc = tab.pc;
if (!emptyFile && !loadImage(pc, filename)) {
closeTab(false);
if (tabs.getTabCount() == 0) addTab("untitled");
JF.showError("Error", "Failed to load file");
return;
}
pc.grabFocus();
pc.resizeBorder();
pc.parentPanel.revalidate();
updateStatus();
}
public void loadFiles(String files[]) {
if (files == null) return;
for(int a=0;a<files.length;a++) {
loadTab(files[a]);
}
}
private ImageTab addTab(String title) {
ImageTab tab = new ImageTab();
tab.panel = new JPanel(new ImageLayout());
tab.scroll = new JScrollPane(tab.panel);
tab.pc = new PaintCanvas(tab.panel, tab.scroll);
tab.pc.setImageSize(init_x, init_y);
tab.pc.img[0].fill(0,0,init_x,init_y,backClr);
tab.pc.createBorders();
tab.panel.add(tab.pc, "CENTER");
tab.panel.add(tab.pc.border_east, "EAST");
tab.panel.add(tab.pc.border_south, "SOUTH");
tab.panel.add(tab.pc.border_corner, "CORNER");
tab.pc.resizeBorder();
tab.filename = new File(title);
tab.pc.dirty = false;
imageTabs.add(tab);
tabs.addTab(title, tab.scroll);
tabs.setSelectedComponent(tab.scroll);
tab.pc.requestFocus();
if (layers != null) {
layers.setup(tab.pc);
}
return tab;
}
private int getidx() { return tabs.getSelectedIndex(); }
private boolean loadImage(PaintCanvas pc, String filename) {
pc.disableScale = true;
JFImage img = new JFImage();
String format = getFormat(filename);
if (format == null) return false;
boolean result, multi = false;
if (format.equals("jfpaint")) {
multi = true;
try {
JFPaint imgs;
FileInputStream fis = new FileInputStream(filename);
ObjectInputStream ois = new ObjectInputStream(fis);
imgs = (JFPaint)ois.readObject();
ois.close();
fis.close();
int w = 0,h = 0;
for(int a=0;a<imgs.images.length;a++) {
img = new JFImage();
ByteArrayInputStream bais = new ByteArrayInputStream(imgs.images[a].png);
if (!img.loadPNG(bais)) throw new Exception("jfpaint sub-png load failed");
if (a == 0) {
w = img.getWidth();
h = img.getHeight();
pc.setImageSize(w, h);
} else {
pc.addImageLayer();
}
pc.setImageLayer(a);
int px[] = img.getPixels();
pc.img[a].putPixels(px, 0, 0, w, h, 0);
pc.name[a] = imgs.images[a].name;
}
pc.setImageLayer(0);
result = true;
} catch (Exception e) {
JF.showError("Error", e.toString());
result = false;
}
}
else if (format.equals("bmp"))
result = img.loadBMP(filename);
else if (format.equals("svg"))
result = img.loadSVG(filename);
else if (format.equals("jpg"))
result = img.loadJPG(filename);
else if (format.equals("xpm"))
result = img.loadXPM(filename);
else
result = img.load(filename);
if (result && !multi) {
int w = img.getWidth();
int h = img.getHeight();
pc.setImageSize(w, h);
int px[] = img.getPixels();
pc.img[pc.getImageLayer()].putPixels(px, 0, 0, w, h, 0);
}
pc.disableScale = false;
return result;
}
private void updateStatus() {
int idx = getidx();
if (idx == -1) {status.setText("?"); return;}
if (getGradPoints) {
status.setText("Draw a line to define Gradient start and end points.");
return;
}
if (getGradFocus) {
status.setText("Click a point to define Gradient focal point.");
return;
}
ImageTab tab = imageTabs.get(idx);
String str = "size:" + tab.pc.getUnscaledWidth() + "x" + tab.pc.getUnscaledHeight();
str += " mouse: " + tab.pc.mx + "," + tab.pc.my;
if (tab.pc.button == MouseEvent.BUTTON1) str += " box: " + Math.abs(tab.pc.mx - tab.pc.sx + 1) + "x" + Math.abs(tab.pc.my - tab.pc.sy + 1);
status.setText(str);
}
private int selectClr(int oldClr, String name) {
Color newClr = JColorChooser.showDialog(this, name, new Color(oldClr));
if (newClr == null) return oldClr;
return newClr.getRGB() & JFImage.RGB_MASK;
}
private void updateClr(JButton button, int clr) {
JFImage blk = new JFImage(16,16);
blk.fill(0,0,16,16,clr);
button.setIcon(blk);
button.setText("");
}
public void newTab() {
GetXY dialog = new GetXY(frame, true, "New Image (pixels)", init_x, init_y);
dialog.setVisible(true);
if (dialog.w == -1) return;
int idx = getidx();
ImageTab tab = imageTabs.get(idx);
if (!(tab.filename.toString().equals("untitled") && imageTabs.get(idx).pc.dirty == false)) {
addTab("untitled");
idx = tabs.getTabCount() - 1;
tab = imageTabs.get(idx);
}
tab.pc.setImageSize(dialog.w, dialog.h);
tab.pc.img[tab.pc.getImageLayer()].fill(0,0,dialog.w,dialog.h,backClr);
repaint();
}
public boolean closeTab(boolean exiting) {
int idx = getidx();
if (tabs.getTabCount() == 0) return true;
if (imageTabs.get(idx).pc.dirty) {
switch (JF.showConfirm3("Save?", "Save first?")) {
case JF.YES:
if (!saveTab()) return false;
case JF.CANCEL:
return false;
case JF.NO:
break;
}
}
curIdx = -1;
imageTabs.remove(idx);
tabs.remove(idx);
if (exiting) return true;
if (tabs.getTabCount() == 0) addTab("untitled");
return true;
}
public boolean saveTab() {
int idx = getidx();
if (imageTabs.get(idx).filename.toString().equals("untitled")) {
return saveAs();
}
PaintCanvas pc = imageTabs.get(idx).pc;
String filename = imageTabs.get(idx).filename.toString();
String format = getFormat(filename);
if (format == null) return false;
boolean saved = false;
pc.disableScale = true;
pc.clearUndo();
pc.applyColorLayer();
if (format.equals("jfpaint")) {
int cnt = pc.getImageLayers();
JFPaint imgs = new JFPaint();
imgs.images = new JFPaintImage[cnt];
try {
for(int a=0;a<cnt;a++) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
if (!pc.img[a].savePNG(baos)) throw new Exception("jfpaint sub-png save failed");
imgs.images[a] = new JFPaintImage();
imgs.images[a].png = baos.toByteArray();
imgs.images[a].name = pc.name[a];
}
FileOutputStream fos = new FileOutputStream(filename);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(imgs);
oos.close();
fos.close();
return true;
} catch (Exception e) {
JF.showError("Error", e.toString());
return false;
}
} else {
if (pc.getImageLayers() > 1) {
if (!JF.showConfirm("Combine Layers?", "Saving in this format will combine all layers, are you sure?")) return false;
}
JFImage img = pc.combineImageLayers();
if (format.equals("bmp"))
saved = img.saveBMP(filename);
else if (format.equals("svg"))
saved = img.saveSVG(filename);
else if (format.equals("jpg"))
saved = img.saveJPG(filename);
else
saved = img.save(filename, format);
}
pc.disableScale = false;
if (saved) pc.dirty = false;
return saved;
}
public boolean saveAs() {
int idx = getidx();
JFileChooser chooser = new JFileChooser();
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
chooser.addChoosableFileFilter(new FileNameExtensionFilter("JFPAINT", "jfpaint"));
chooser.addChoosableFileFilter(new FileNameExtensionFilter("JPEG", "jpg", "jpeg"));
chooser.addChoosableFileFilter(new FileNameExtensionFilter("PNG", "png"));
chooser.addChoosableFileFilter(new FileNameExtensionFilter("BMP", "bmp"));
chooser.addChoosableFileFilter(new FileNameExtensionFilter("SVG", "svg"));
chooser.setMultiSelectionEnabled(false);
chooser.setCurrentDirectory(new File(currentPath));
if (chooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
ImageTab tab = imageTabs.get(idx);
tab.pc.setDirty();
tab.filename = chooser.getSelectedFile();
String format = getFormat(tab.filename.toString());
if (format == null) {
String ext = chooser.getFileFilter().getDescription().toLowerCase();
if (ext.equals("all files")) {
if (tab.pc.getImageLayers() == 1)
ext = "png"; //default if one image layer
else
ext = "jfpaint"; //default if > 1 image layer
}
if (ext.equals("jpeg")) ext = "jpg";
tab.filename = new File(tab.filename.toString() + "." + ext);
}
currentPath = tab.filename.getAbsoluteFile().getParent();
if (currentPath == null) currentPath = JF.getUserPath() + "/Pictures";
String name = tab.filename.toString();
int fidx = name.lastIndexOf("/");
if (fidx != -1) name = name.substring(fidx+1);
tabs.setTitleAt(idx, name);
return saveTab();
}
return false;
}
private void selectAll() {
int idx = getidx();
unselectTool(idx);
selBox.setSelected(true);
selectTool(tools.selBox);
PaintCanvas pc = imageTabs.get(idx).pc;
selX1 = selY1 = 0;
selX2 = pc.img[pc.getImageLayer()].getWidth()-1;
selY2 = pc.img[pc.getImageLayer()].getHeight()-1;
haveSel = true;
cutSel();
pasteSel(selX1, selY1, false);
pc.drag = true;
}
private String getFormat(String filename) {
int idx = filename.lastIndexOf(".");
if (idx == -1) return null;
String format = filename.substring(idx+1).toLowerCase();
if (format.equals("jfpaint")) return "jfpaint";
if (format.equals("png")) return "png";
if (format.equals("bmp")) return "bmp";
if (format.equals("jpg")) return "jpg";
if (format.equals("jpeg")) return "jpg";
if (format.equals("svg")) return "svg";
if (format.equals("xpm")) return "xpm";
System.out.println("Unsupported format:" + format);
return null;
}
private void selectTool(tools tool) {
selectedTool = tool;
switch (tool) {
case fill:
thresholdSlider.setEnabled(true);
alphaSlider.setEnabled(fillAlpha.isSelected() || paintMode.getSelectedIndex() == 1);
break;
case sub:
thresholdSlider.setEnabled(true);
alphaSlider.setEnabled(paintMode.getSelectedIndex() == 1);
break;
default:
thresholdSlider.setEnabled(false);
alphaSlider.setEnabled(paintMode.getSelectedIndex() == 1);
break;
}
}
private void unselectTool(int idx) {
if (idx == -1) return;
PaintCanvas pc = imageTabs.get(idx).pc;
pc.disableScale = true;
switch (selectedTool) {
case selBox:
if (pc.drag) { drawSel(pc); clearSel(pc); pc.drag = false; }
pc.foreClear();
break;
case text:
if (pc.drag) { drawText(pc); clearSel(pc); pc.drag = false; }
pc.foreClear();
break;
case curve:
cpt = -1;
break;
}
pc.disableScale = false;
}
private void print() {
//TODO
}
public void delSel() {
if (selectedTool != tools.selBox) return;
if (!haveSel) return;
int tmp;
if (selX1 > selX2) {tmp=selX1; selX1=selX2; selX2=tmp;}
if (selY1 > selY2) {tmp=selY1; selY1=selY2; selY2=tmp;}
int idx = getidx();
int w = selX2-selX1+1;
int h = selY2-selY1+1;
PaintCanvas pc = imageTabs.get(idx).pc;
pc.img[pc.getImageLayer()].fill(selX1,selY1,w,h,backClr);
clearSel(pc);
pc.drag = false;
}
public void cutSel() {
if (selectedTool != tools.selBox) return;
if (!haveSel) return;
int tmp;
if (selX1 > selX2) {tmp=selX1; selX1=selX2; selX2=tmp;}
if (selY1 > selY2) {tmp=selY1; selY1=selY2; selY2=tmp;}
int idx = getidx();
cbX = selX2-selX1+1;
cbY = selY2-selY1+1;
PaintCanvas pc = imageTabs.get(idx).pc;
pc.disableScale = true;
JFImage clip = new JFImage(cbX,cbY);
clipBoard = pc.img[pc.getImageLayer()].getPixels(selX1,selY1,cbX,cbY);
clip.putPixels(clipBoard,0,0,cbX,cbY,0);
JFClipboard.writeImage(clip.getImage());
int layer = pc.getImageLayer();
if (layer == 0) {
pc.img[layer].fill(selX1,selY1,cbX,cbY,backClr);
} else {
pc.img[layer].fill(selX1,selY1,cbX,cbY,backClr,true); //alpha = transparent
}
pc.disableScale = false;
}
public void copySel() {
if (selectedTool != tools.selBox) return;
if (!haveSel) return;
int tmp;
if (selX1 > selX2) {tmp=selX1; selX1=selX2; selX2=tmp;}
if (selY1 > selY2) {tmp=selY1; selY1=selY2; selY2=tmp;}
int idx = getidx();
cbX = selX2-selX1+1;
cbY = selY2-selY1+1;
PaintCanvas pc = imageTabs.get(idx).pc;
JFImage clip = new JFImage(cbX,cbY);
clipBoard = pc.img[pc.getImageLayer()].getPixels(selX1,selY1,cbX,cbY);
clip.putPixels(clipBoard,0,0,cbX,cbY,0);
JFClipboard.writeImage(clip.getImage());
}
public void pasteSel(int x, int y, boolean sysClipBoard) {
if (colorLayer.getSelectedIndex() != 0) return;
rotate = 0f;
if (clipBoard == null || sysClipBoard) {
java.awt.Image img = JFClipboard.readImage();
if (img == null) return;
JFImage image = JFClipboard.convertImage(img);
cbX = image.getWidth();
cbY = image.getHeight();
clipBoard = image.getPixels();
}
int idx = getidx();
PaintCanvas pc = imageTabs.get(idx).pc;
if (selectedTool != tools.selBox) {
unselectTool(idx);
selBox.setSelected(true);
selectTool(tools.selBox);
}
pc.disableScale = true;
minSize(pc, x + cbX, y + cbY);
selX1 = x;
selY1 = y;
selX2 = x+cbX;
selY2 = y+cbY;
haveSel = true;
foreDrawSel(pc);
pc.drag = true;
pc.disableScale = false;
}
private void clearSel(PaintCanvas pc) {
pc.foreClear();
haveSel = false;
}
private void drawSel(PaintCanvas pc) {
if (cbX == 0 || cbY == 0) return; //shouldn't happen ???
int px[];
if (selkeyclr.isSelected()) {
int cnt = cbX * cbY;
px = new int[cnt];
System.arraycopy(clipBoard, 0, px, 0, cnt);
for(int a=0;a<cnt;a++) {
if ((px[a] & JFImage.RGB_MASK) == backClr) {
px[a] = 0;
}
}
} else {
px = clipBoard;
}
pc.putPixels(px, selX1, selY1, selX2 - selX1, selY2 - selY1, cbX, cbY, rotate);
pc.img[pc.getImageLayer()].repaint();
}
private void foreDrawSel(PaintCanvas pc) {
int px[];
if (selkeyclr.isSelected()) {
int cnt = cbX * cbY;
px = new int[cnt];
System.arraycopy(clipBoard, 0, px, 0, cnt);
for(int a=0;a<cnt;a++) {
if ((px[a] & JFImage.RGB_MASK) == backClr) {
px[a] = 0;
}
}
} else {
px = clipBoard;
}
pc.forePutPixels(px, selX1, selY1, selX2 - selX1, selY2 - selY1, cbX, cbY, rotate);
pc.foreDrawSelBox(selX1,selY1,selX2,selY2,rotate);
}
private void drawText(PaintCanvas pc) {
assignPaint(pc.cimg, true);
pc.setFont(textFont);
int x=selX1;
int y=selY1;
Rectangle2D rect = textFont.getMaxCharBounds(pc.img[pc.getImageLayer()].getGraphics2D().getFontRenderContext());
int fy = (int)rect.getHeight();
pc.drawText(textText.split("\n"), x, y, fy, 1, 1, rotate);
textText = "";
}
private void foreDrawText(PaintCanvas pc) {
FontRenderContext frc = pc.img[pc.getImageLayer()].getGraphics2D().getFontRenderContext();
Rectangle2D rect = textFont.getMaxCharBounds(pc.img[pc.getImageLayer()].getGraphics2D().getFontRenderContext());
int fx = (int)rect.getWidth();
int fy = (int)rect.getHeight();
int mx = 1;
int my;
int lx = 0;
assignPaint(pc.fimg, true);
pc.foreClear();
pc.foreDrawSelBox(selX1, selY1, selX2, selY2, rotate);
pc.foreSetFont(textFont);
String text;
if (pc.textCursor) {
pc.textCursor = false;
text = textText + "\u2588";
} else {
pc.textCursor = true;
text = textText;
}
String lns[] = text.split("\n", -1);
my = lns.length * fy;
int x=selX1;
int y=selY1;
for(int a=0;a<lns.length;a++) {
lx = (int)textFont.getStringBounds(lns[a], frc).getWidth() + 6;
if (lx > mx) mx = lx;
}
pc.foreDrawText(lns, x, y, fy, 1, 1, rotate);
if ((selX2 - selX1) < mx) selX2 = selX1 + mx;
if ((selY2 - selY1) < my) selY2 = selY1 + my;
}
private void repaintTool(PaintCanvas pc) {
if (!pc.drag) return;
assignPaint(pc.fimg, pc.button == MouseEvent.BUTTON1);
pc.disableScale = true;
pc.foreClear();
switch (selectedTool) {
case selBox:
foreDrawSel(pc);
break;
case text:
foreDrawText(pc);
break;
}
pc.repaint();
pc.disableScale = false;
}
private void undo() {
unselectTool(getidx());
PaintCanvas pc = imageTabs.get(getidx()).pc;
pc.disableScale = true;
pc.undo();
pc.disableScale = false;
}
private void redo() {
unselectTool(getidx());
PaintCanvas pc = imageTabs.get(getidx()).pc;
pc.disableScale = true;
pc.redo();
pc.disableScale = false;
}
private void repaintImage() {
int idx = getidx();
imageTabs.get(idx).pc.repaint();
}
private void minSize(PaintCanvas pc, int w, int h) {
//scaling on pc is already disabled
int pw = pc.getUnscaledWidth();
int ph = pc.getUnscaledHeight();
int dx = 0;
int dy = 0;
if (w > pw) dx = w - pw;
if (h > ph) dy = h - ph;
if (dx == 0 && dy == 0) return;
changeSize(pc, dx, dy, false);
}
private void changeSize(PaintCanvas pc, int dx, int dy, boolean scaled) {
float orgScale = pc.scale;
int orgLayer = pc.getColorLayer();
int x = pc.getUnscaledWidth();
int y = pc.getUnscaledHeight();
if (x + dx < 1) {
dx = -x + 1;
}
if (y + dy < 1) {
dy = -y + 1;
}
if (scaled) {
dx /= (pc.scale / 100f);
dy /= (pc.scale / 100f);
}
if (orgLayer != 0) {
pc.changeColorLayer(0);
}
if (orgScale != 100) pc.setScale(100);
int cnt = pc.getImageLayers();
int px[][] = new int[cnt][];
for (int a=0;a<cnt;a++) {
px[a] = pc.img[a].getPixels();
}
pc.setImageSize(x + dx,y + dy);
for(int a=0;a<cnt;a++) {
pc.img[a].putPixels(px[a], 0,0, x,y, 0);
if (dx > 0) {
if (a == 0)
pc.img[a].fill(x,0,dx,y + dy,backClr);
else
pc.img[a].fill(x,0,dx,y + dy,backClr, true);
}
if (dy > 0) {
if (a == 0)
pc.img[a].fill(0,y,x + dx,dy,backClr);
else
pc.img[a].fill(0,y,x + dx,dy,backClr, true);
}
if ((dx > 0) && (dy > 0)) {
if (a == 0)
pc.img[a].fill(x,y,dx,dy,backClr);
else
pc.img[a].fill(x,y,dx,dy,backClr, true);
}
}
if (orgScale != 100) pc.setScale(orgScale);
if (orgLayer != 0) {
pc.changeColorLayer(orgLayer);
}
pc.resizeBorder();
repaintTool(pc);
updateStatus();
}
private void paintModeChanged() {
getGradPoints = false;
getGradFocus = false;
updateStatus();
int mode = paintMode.getSelectedIndex();
if (mode == 0) {
fillAlpha.setEnabled(true);
fillEdge.setEnabled(true);
} else {
fillAlpha.setEnabled(false);
fillAlpha.setSelected(false);
fillEdge.setEnabled(false);
fillEdge.setSelected(false);
}
alphaSlider.setEnabled(false);
GetValue dialog;
GetValue2 dialog2;
switch (mode) {
case 0: //normal
break;
case 1: //transparent
alphaSlider.setEnabled(true);
break;
case 2:
case 3:
case 4:
case 5:
case 6:
getGradPoints = true;
updateStatus();
break;
case 7:
dialog = new GetValue(null, true, "Enter Gaussian Blur parameters", "radius", 2, 64, 5);
dialog.setVisible(true);
filter_radius = dialog.value;
if (filter_radius == -1) filter_radius = 2;
break;
case 8:
dialog = new GetValue(null, true, "Enter Pixelate parameters", "pixel size", 2, 64, 5);
dialog.setVisible(true);
filter_pixelSize = dialog.value;
if (filter_pixelSize == -1) filter_pixelSize = 2;
break;
case 9:
dialog2 = new GetValue2(null, true, "Enter Chrome parameters"
, "amount", 0, 100, 50
, "exposure", 0, 100, 100
);
dialog2.setVisible(true);
filter_amount = dialog2.value1;
if (filter_amount == -1) filter_pixelSize = 50;
filter_amount /= 100f;
filter_exposure = dialog2.value2;
if (filter_exposure == -1) filter_exposure = 100;
filter_exposure /= 100f;
break;
}
if (mode >= 7 ) {
switch (selectedTool) {
case box:
break;
default:
unselectTool(getidx());
box.doClick();
break;
}
pencil.setEnabled(false);
fill.setEnabled(false);
fillMode.setEnabled(false);
text.setEnabled(false);
curve.setEnabled(false);
line.setEnabled(false);
circle.setEnabled(false);
round.setEnabled(false);
selectFont.setEnabled(false);
sub.setEnabled(false);
thresholdSlider.setEnabled(false);
rotateCW.setEnabled(false);
rotateCCW.setEnabled(false);
flipVert.setEnabled(false);
flipHorz.setEnabled(false);
selkeyclr.setEnabled(false);
fillMode.setSelected(false);
} else {
pencil.setEnabled(true);
fill.setEnabled(true);
fillMode.setEnabled(true);
text.setEnabled(true);
curve.setEnabled(true);
line.setEnabled(true);
circle.setEnabled(true);
round.setEnabled(true);
selectFont.setEnabled(true);
sub.setEnabled(true);
thresholdSlider.setEnabled(true);
rotateCW.setEnabled(true);
rotateCCW.setEnabled(true);
flipVert.setEnabled(true);
flipHorz.setEnabled(true);
selkeyclr.setEnabled(true);
}
}
private int getAlphaLevel() {
int al = alphaSlider.getValue();
return 255 - al;
}
private int getAlphaPercent() {
int al = alphaSlider.getValue();
return al * 100 / 255;
}
private int getThresholdLevel() {
int al = thresholdSlider.getValue();
if (al < 0) al = 0;
if (al > 255) al = 255;
return al;
}
private int getThresholdPercent() {
int al = thresholdSlider.getValue();
if (al < 0) al = 0;
if (al > 255) al = 255;
return al * 100 / 255;
}
private float gradRadius() {
float rise = Math.abs(gy[0] - gy[1]);
float run = Math.abs(gx[0] - gx[1]);
return (float)Math.sqrt(rise*rise + run*run);
}
private void assignPaint(JFImage img, boolean button1) {
Paint paint = null;
int clr;
switch (paintMode.getSelectedIndex()) {
case 0: //normal
if (button1) clr = foreClr; else clr = backClr;
switch (colorLayer.getSelectedIndex()) {
case 0: //ARGB
paint = new Color(clr);
break;
case 1: //A
//find avg of color components and assign to rgb
int r = (clr & 0xff0000) >> 16;
int g = (clr & 0x00ff00) >> 8;
int b = (clr & 0x0000ff);
clr = (r + g + b) / 3;
paint = new Color((clr << 16) | (clr << 8) | (clr));
break;
case 2: //R
paint = new Color(clr & 0xff0000);
break;
case 3: //G
paint = new Color(clr & 0x00ff00);
break;
case 4: //B
paint = new Color(clr & 0x0000ff);
break;
}
break;
case 1: //transparent
if (button1) clr = foreClr; else clr = backClr;
paint = new Color(clr | (getAlphaLevel() << 24), true);
break;
case 2: //grad (cyclic)
paint = new GradientPaint(gx[0], gy[0], new Color(foreClr), gx[1], gy[1], new Color(backClr), true);
break;
case 3: //grad (acyclic)
paint = new GradientPaint(gx[0], gy[0], new Color(foreClr), gx[1], gy[1], new Color(backClr), false);
break;
case 4: //grad (radial - no cycle)
paint = new RadialGradientPaint(gx[0], gy[0], gradRadius(), gfx, gfy, new float[] {0.0f, 1.0f}, new Color[] {new Color(foreClr), new Color(backClr)}, MultipleGradientPaint.CycleMethod.NO_CYCLE);
break;
case 5: //grad (radial - reflect)
paint = new RadialGradientPaint(gx[0], gy[0], gradRadius(), gfx, gfy, new float[] {0.0f, 1.0f}, new Color[] {new Color(foreClr), new Color(backClr)}, MultipleGradientPaint.CycleMethod.REFLECT);
break;
case 6: //grad (radial - repeat)
paint = new RadialGradientPaint(gx[0], gy[0], gradRadius(), gfx, gfy, new float[] {0.0f, 1.0f}, new Color[] {new Color(foreClr), new Color(backClr)}, MultipleGradientPaint.CycleMethod.REPEAT);
break;
}
img.getGraphics2D().setPaint(paint);
}
public void swapColors() {
int tmp = foreClr;
foreClr = backClr;
backClr = tmp;
updateClr(foreColor, foreClr);
updateClr(backColor, backClr);
}
public void changeScale() {
PaintCanvas pc = imageTabs.get(getidx()).pc;
int newScale = -1;
switch (zoom.getValue()) {
case 0: newScale = 25; break;
case 1: newScale = 50; break;
case 2: newScale = 100; break;
case 3: newScale = 200; break;
case 4: newScale = 400; break;
case 5: newScale = 800; break;
}
zoomText.setText(Integer.toString(newScale) + "%");
pc.setScale(newScale);
pc.parentPanel.revalidate();
pc.resizeBorder();
pc.repaint();
}
public void actionPerformed(ActionEvent e) {
//Swing Timer
repaintTool(imageTabs.get(getidx()).pc);
}
public void doPaste(boolean sysClipBoard) {
int idx = getidx();
if (idx == -1) return;
unselectTool(idx);
selBox.setSelected(true);
selectTool(tools.selBox);
Point pt = imageTabs.get(idx).scroll.getViewport().getViewPosition();
//scale point
float scale = imageTabs.get(idx).pc.scale / 100f;
pt.x = (int)(pt.x / scale);
pt.y = (int)(pt.y / scale);
pasteSel(pt.x, pt.y, sysClipBoard);
}
public boolean dispatchKeyEvent(KeyEvent evt) {
int id = evt.getID();
switch (id) {
case KeyEvent.KEY_TYPED:
keyTyped(evt);
break;
case KeyEvent.KEY_PRESSED:
keyPressed(evt);
break;
case KeyEvent.KEY_RELEASED:
keyReleased(evt);
break;
}
return false; //pass on as normal
}
public static final int NONE = 0;
public static final int N = 1;
public static final int E = 2;
public static final int S = 3;
public static final int W = 4;
public static final int NE = 5;
public static final int NW = 6;
public static final int SE = 7;
public static final int SW = 8;
public static final int R = 9;
public static final int INSIDE = 10;
public static final int OUTSIDE = 11;
public float rad2deg(float rad) {
return rad * 180f / (float)Math.PI;
}
/** Get selection box point.
* Adjusts for rotation.
*/
public int getSelBoxPt(int x,int y) {
if (!haveSel) return OUTSIDE;
if (rotate != 0f) {
GLMatrix mat = new GLMatrix();
mat.addRotate(rad2deg(rotate), 0, 0, 1);
GLVector3 vec = new GLVector3();
vec.v[0] = x - selX1;
vec.v[1] = y - selY1;
vec.v[2] = 0; //z
mat.mult(vec);
x = (int)vec.v[0] + selX1;
y = (int)vec.v[1] + selY1;
}
int ox = x - selX1;
int oy = y - selY1;
int width = selX2 - selX1 + 1;
int height = selY2 - selY1 + 1;
if (x >= selX1 && x <= selX2 && y >= selY1 && y <= selY2) {
return INSIDE;
} else {
if (ox >= width+5 && ox <= width+15 && oy >= height+5 && oy <= height+15) return R;
if (ox < -5 || ox > width+5) return OUTSIDE;
if (oy < -5 || oy > height+5) return OUTSIDE;
int x1 = 0;
int y1 = 0;
int x2 = width;
int y2 = height;
if (ox >= x2 && oy >= y2) return SE;
if (ox <= x1 && oy >= y2) return SW;
if (ox >= x2 && oy <= y1) return NE;
if (ox <= x1 && oy <= y1) return NW;
if (oy <= y1) return N;
if (oy >= y2) return S;
if (ox <= x1) return W;
if (ox >= x2) return E;
return INSIDE; //should not happen
}
}
public void keyPressed(KeyEvent evt) {
//Key Pressed
int f1 = evt.getKeyCode();
int f2 = evt.getModifiers();
int idx = getidx();
if ((f1 == KeyEvent.VK_F1) && (f2 == 0)) {
JOptionPane.showMessageDialog(this,
"jfpaint/" + version + "\n\n" +
"F1 = Help\n" +
"CTRL-O = Open\n" +
"CTRL-W = Close\n" +
"CTRL-S = Save\n" +
"CTRL-Q = Save As\n" +
"CTRL-P = Print\n" +
"CTRL-X = Cut\n" +
"CTRL-C = Copy\n" +
"CTRL-V = Paste\n" +
"CTRL-Z = Undo\n" +
"CTRL-Y = Redo\n" +
"ALT-# = Switch to document\n\n"
, "Help", JOptionPane.INFORMATION_MESSAGE);
return;
}
if ((f1 == KeyEvent.VK_ESCAPE) && (f2 == 0)) { unselectTool(getidx()); return; }
if ((f1 == KeyEvent.VK_N) && (f2 == KeyEvent.CTRL_MASK)) { addTab("untitled"); return; }
if ((f1 == KeyEvent.VK_S) && (f2 == KeyEvent.CTRL_MASK)) { saveTab(); return; }
if ((f1 == KeyEvent.VK_Q) && (f2 == KeyEvent.CTRL_MASK)) { saveAs(); return; }
if ((f1 == KeyEvent.VK_W) && (f2 == KeyEvent.CTRL_MASK)) { closeTab(false); return; }
if ((f1 == KeyEvent.VK_O) && (f2 == KeyEvent.CTRL_MASK)) { openTab(); return; }
if ((f1 == KeyEvent.VK_P) && (f2 == KeyEvent.CTRL_MASK)) { print(); return; }
if ((f1 == KeyEvent.VK_A) && (f2 == KeyEvent.CTRL_MASK)) { selectAll(); return; }
if ((f1 == KeyEvent.VK_DELETE) && (f2 == 0)) { delSel(); return; }
if ((f1 == KeyEvent.VK_Z) && (f2 == KeyEvent.CTRL_MASK)) { undo(); return; }
if ((f1 == KeyEvent.VK_Y) && (f2 == KeyEvent.CTRL_MASK)) { redo(); return; }
if ((f2 == KeyEvent.ALT_MASK) && (f1 >= KeyEvent.VK_0) && (f1 <= KeyEvent.VK_9)) {
idx = f1 - KeyEvent.VK_0;
if (idx == 0) idx = 9; else idx--;
if (idx >= imageTabs.size()) return;
unselectTool(getidx());
tabs.setSelectedIndex(idx);
return;
}
if ((f2 == KeyEvent.ALT_MASK) && (f1 == KeyEvent.VK_MINUS)) {unselectTool(getidx()); tabs.setSelectedIndex(10);}
if ((f2 == KeyEvent.ALT_MASK) && (f1 == KeyEvent.VK_EQUALS)) {unselectTool(getidx()); tabs.setSelectedIndex(11);}
}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}
//the following mouse events are from PaintCanvas, not this Panel
public void mouseClicked(MouseEvent e) {
JComponent c = (JComponent)e.getComponent();
if (c instanceof Border) return;
PaintCanvas pc = (PaintCanvas)c;
int x = (int)(e.getX() / (pc.scale / 100f));
int y = (int)(e.getY() / (pc.scale / 100f));
if (getGradFocus) {
gfx = x;
gfy = y;
getGradFocus = false;
updateStatus();
return;
}
pc.disableScale = true;
pc.setLineWidth(width.getSelectedIndex()+1);
assignPaint(pc.cimg, e.getButton() == MouseEvent.BUTTON1);
switch (selectedTool) {
default:
pc.disableScale = false;
return;
case pencil:
pc.drawLine(x, y, x, y);
break;
}
pc.disableScale = false;
pc.setDirty();
pc.repaint();
}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e) {
JComponent c = (JComponent)e.getComponent();
PaintCanvas pc;
boolean border = false;
if (c instanceof Border) {
Border b = (Border)c;
pc = b.pc;
border = true;
} else {
pc = (PaintCanvas)c;
}
pc.grabFocus();
pc.button = e.getButton();
int x = (int)(e.getX() / (pc.scale / 100f));
int y = (int)(e.getY() / (pc.scale / 100f));
if (border) {
//start to drag size
pc.sx = x;
pc.sy = y;
pc.createUndo();
return;
}
if (getGradPoints) {
gx[0] = x;
gy[0] = y;
return;
}
if (getGradFocus) return;
pc.disableScale = true;
pc.setLineWidth(width.getSelectedIndex()+1);
assignPaint(pc.cimg, e.getButton() == MouseEvent.BUTTON1);
switch (selectedTool) {
default:
pc.disableScale = false;
return;
case pencil:
pc.createUndo();
pc.sx = x;
pc.sy = y;
pc.disableScale = false;
return;
case selBox:
case text:
int pt = getSelBoxPt(x,y);
switch (pt) {
default:
scretchDir = pt;
pc.sx = x;
pc.sy = y;
break;
case INSIDE:
scretchDir = NONE;
pc.drag = true;
pc.sx = x;
pc.sy = y;
break;
case OUTSIDE:
scretchDir = NONE;
if (pc.drag) {
if (selectedTool == tools.selBox) drawSel(pc); else drawText(pc);
pc.drag = false;
clearSel(pc);
}
rotate = 0f;
selX1 = x;
selY1 = y;
haveSel = true;
if (selectedTool == tools.text) textText = "";
break;
}
//no break
case line:
case box:
case circle:
case sub:
pc.createUndo();
pc.sx = x;
pc.sy = y;
pc.disableScale = false;
return;
case curve:
if (cpt == -1) {
pc.createUndo();
cpt++;
cx[cpt] = x;
cy[cpt] = y;
cpt++;
} else {
mouseDragged(e);
}
pc.disableScale = false;
return;
case fill:
int clr = foreClr;
if (e.getButton() == MouseEvent.BUTTON3) clr = backClr;
switch (colorLayer.getSelectedIndex()) {
case 0: //ARGB
break;
case 1: //A
//find avg of color components and assign to rgb
int r = (clr & 0xff0000) >> 16;
int g = (clr & 0x00ff00) >> 8;
int b = (clr & 0x0000ff);
clr = (r + g + b) / 3;
clr = (clr << 16) | (clr << 8) | (clr);
break;
case 2: //R
clr &= 0xff0000;
break;
case 3: //G
clr &= 0x00ff00;
break;
case 4: //B
clr &= 0x0000ff;
break;
}
pc.createUndo();
switch (paintMode.getSelectedIndex()) {
case 0:
if (fillAlpha.isSelected())
pc.fillFast(x, y, clr | getAlphaLevel() << 24, true, fillEdge.isSelected(), getThresholdLevel());
else
pc.fillFast(x, y, clr, false, fillEdge.isSelected(), getThresholdLevel());
break;
default:
pc.fillSlow(x, y, fillEdge.isSelected(), getThresholdLevel());
break;
}
break;
case pickColor:
if (e.getButton() == MouseEvent.BUTTON1) {
foreClr = pc.img[pc.getImageLayer()].getPixel(x, y);
updateClr(foreColor, foreClr);
}
if (e.getButton() == MouseEvent.BUTTON3) {
backClr = pc.img[pc.getImageLayer()].getPixel(x, y);
updateClr(backColor, backClr);
}
pc.disableScale = false;
return;
}
pc.disableScale = false;
pc.setDirty();
pc.repaint();
}
public void mouseReleased(MouseEvent e) {
JComponent c = (JComponent)e.getComponent();
if (c instanceof Border) return;
PaintCanvas pc = (PaintCanvas)c;
pc.button = -1;
int tmp;
int x = (int)(e.getX() / (pc.scale / 100f));
int y = (int)(e.getY() / (pc.scale / 100f));
if (getGradPoints) {
gx[1] = x;
gy[1] = y;
pc.foreClear();
getGradPoints = false;
if (paintMode.getSelectedIndex() > 3) getGradFocus = true;
updateStatus();
pc.repaint();
return;
}
if (getGradFocus) return;
pc.disableScale = true;
pc.setLineWidth(width.getSelectedIndex()+1);
assignPaint(pc.cimg, e.getButton() == MouseEvent.BUTTON1);
switch (selectedTool) {
default:
pc.disableScale = false;
return;
case line:
pc.drawLine(pc.sx, pc.sy, x, y);
pc.foreClear();
break;
case box:
switch (paintMode.getSelectedIndex()) {
default:
if (fillMode.isSelected()) {
if (round.isSelected())
pc.fillRoundBox(pc.sx, pc.sy, x, y, arcX, arcY);
else
pc.fillBox(pc.sx, pc.sy, x, y);
} else {
if (round.isSelected())
pc.drawRoundBox(pc.sx, pc.sy, x, y, arcX, arcY);
else
pc.drawBox(pc.sx, pc.sy, x, y);
}
break;
case 7:
pc.blur(pc.sx, pc.sy, x, y, filter_radius);
break;
case 8:
pc.pixelate(pc.sx, pc.sy, x, y, filter_pixelSize);
break;
case 9:
pc.chrome(pc.sx, pc.sy, x, y, filter_amount, filter_exposure);
break;
}
pc.foreClear();
break;
case circle:
if (fillMode.isSelected()) {
pc.fillCircle(pc.sx, pc.sy, x, y);
} else {
pc.drawCircle(pc.sx, pc.sy, x, y);
}
pc.foreClear();
break;
case selBox:
if (pc.drag) {
pc.disableScale = false;
return;
}
selX2 = x;
selY2 = y;
if ((selX1 == selX2) && (selY1 == selY2)) {haveSel = false; pc.foreClear(); pc.repaint(); return;}
if (selX1 > selX2) {tmp=selX1; selX1=selX2; selX2=tmp;}
if (selY1 > selY2) {tmp=selY1; selY1=selY2; selY2=tmp;}
//copySel();
cutSel();
pasteSel(selX1, selY1, false);
pc.drag = true;
scretchDir = NONE;
break;
case curve:
cx[cpt] = x;
cy[cpt] = y;
cpt++;
if (cpt != 4) return;
//draw final curve
pc.drawCurve(cx, cy);
cpt = -1;
break;
case pencil:
break;
case sub:
switch (paintMode.getSelectedIndex()) {
case 0:
pc.subBoxFast(pc.sx, pc.sy, x, y, backClr, foreClr, getThresholdLevel());
break;
default:
pc.subBoxSlow(pc.sx, pc.sy, x, y, backClr, getThresholdLevel());
break;
}
pc.foreClear();
break;
case text:
if (pc.drag) return;
selX2 = x;
selY2 = y;
if ((selX1 == selX2) && (selY1 == selY2)) {haveSel = false; pc.foreClear(); pc.repaint(); return;}
if (selX1 > selX2) {tmp=selX1; selX1=selX2; selX2=tmp;}
if (selY1 > selY2) {tmp=selY1; selY1=selY2; selY2=tmp;}
pc.drag = true;
break;
}
pc.disableScale = false;
pc.setDirty();
pc.repaint();
}
public void mouseDragged(MouseEvent e) {
JComponent c = (JComponent)e.getComponent();
if (c instanceof Border) {
Border b = (Border)c;
int x = (int)(e.getX() / (b.pc.scale / 100f));
int y = (int)(e.getY() / (b.pc.scale / 100f));
//changing size
if (b.borderType == Border.Types.east) {
changeSize(b.pc, x - b.pc.sx, 0, true);
}
if (b.borderType == Border.Types.south) {
changeSize(b.pc, 0, y - b.pc.sy, true);
}
if (b.borderType == Border.Types.corner) {
changeSize(b.pc, x - b.pc.sx, y - b.pc.sy, true);
}
imageTabs.get(getidx()).scroll.doLayout();
doLayout();
return;
}
PaintCanvas pc = (PaintCanvas)c;
int x = (int)(e.getX() / (pc.scale / 100f));
int y = (int)(e.getY() / (pc.scale / 100f));
if (scretchDir != NONE) {
float width = selX2 - selX1;
float height = selY2 - selY1;
switch(scretchDir) {
case NW:
selX1 = x;
selY1 = y;
break;
case N:
selY1 = y;
break;
case NE:
selY1 = y;
selX2 = x;
break;
case E:
selX2 = x;
break;
case SE:
selX2 = x;
selY2 = y;
break;
case S:
selY2 = y;
break;
case SW:
selX1 = x;
selY2 = y;
break;
case W:
selX1 = x;
break;
case R:
rotate = (y - selY2) / height;
break;
}
return;
}
pc.disableScale = true;
if (getGradPoints) {
pc.foreClear();
pc.fimg.getGraphics2D().setPaint(new Color(foreClr));
pc.foreDrawLine(gx[0], gy[0], x, y);
pc.repaint();
pc.disableScale = false;
return;
}
if (getGradFocus) {
pc.disableScale = false;
return; //shouldn't happen unless user can't read
}
assignPaint(pc.cimg, pc.button == MouseEvent.BUTTON1);
assignPaint(pc.fimg, pc.button == MouseEvent.BUTTON1);
switch (selectedTool) {
case pencil:
pc.drawLine(pc.sx, pc.sy, x, y);
pc.sx = x;
pc.sy = y;
break;
case line:
pc.foreClear();
pc.foreDrawLine(pc.sx, pc.sy, x, y);
break;
case box:
pc.foreClear();
if (fillMode.isSelected()) {
if (round.isSelected())
pc.foreFillRoundBox(pc.sx, pc.sy, x, y, arcX, arcY);
else
pc.foreFillBox(pc.sx, pc.sy, x, y);
} else {
if (round.isSelected())
pc.foreDrawRoundBox(pc.sx, pc.sy, x, y, arcX, arcY);
else
pc.foreDrawBox(pc.sx, pc.sy, x, y);
}
break;
case circle:
pc.foreClear();
if (fillMode.isSelected()) {
pc.foreFillCircle(pc.sx, pc.sy, x, y);
} else {
pc.foreDrawCircle(pc.sx, pc.sy, x, y);
}
break;
case selBox:
if (!haveSel) break;
if (pc.drag) {
pc.foreClear();
int dx = (x - pc.sx);
int dy = (y - pc.sy);
selX1 += dx;
selY1 += dy;
selX2 += dx;
selY2 += dy;
foreDrawSel(pc);
pc.sx = x;
pc.sy = y;
} else {
selX2 = x;
selY2 = y;
pc.foreClear();
pc.foreDrawSelBox(selX1, selY1, selX2, selY2, rotate);
}
break;
case curve:
cx[cpt] = x;
cy[cpt] = y;
pc.foreClear();
switch (cpt) {
case 1:
pc.foreDrawLine(cx[0], cy[0], cx[1], cy[1]);
break;
case 2:
cx[3] = cx[1];
cy[3] = cy[1];
//no break
case 3:
pc.foreDrawCurve(cx, cy);
break;
}
break;
case sub:
pc.foreClear();
pc.foreDrawBox(pc.sx, pc.sy, x, y);
break;
case text:
if (!haveSel) break;
if (pc.drag) {
pc.foreClear();
int dx = (x - pc.sx);
int dy = (y - pc.sy);
selX1 += dx;
selY1 += dy;
selX2 += dx;
selY2 += dy;
pc.sx = x;
pc.sy = y;
} else {
selX2 = x;
selY2 = y;
}
foreDrawText(pc);
break;
}
pc.disableScale = false;
updateStatus();
pc.setDirty();
pc.repaint();
}
public void mouseMoved(MouseEvent e) {
updateStatus();
}
public void keyTypedOnImage(char key) {
if (selectedTool != tools.text) return;
PaintCanvas pc = imageTabs.get(getidx()).pc;
if (key == 8) {
if (textText.length() > 0) textText = textText.substring(0,textText.length()-1);
} else if (key == 10) {
textText += "\n";
} else {
textText += key;
}
foreDrawText(pc);
pc.repaint();
}
public int getLayer() {
return colorLayer.getSelectedIndex();
}
public void layerChanged() {
int idx = getidx();
unselectTool(idx);
switch (selectedTool) {
case selBox:
case sub:
pencil.doClick();
}
PaintCanvas pc = imageTabs.get(idx).pc;
pc.changeColorLayer(colorLayer.getSelectedIndex());
if (colorLayer.getSelectedIndex() > 0) {
paintMode.setSelectedIndex(0);
paintMode.setEnabled(false);
selBox.setEnabled(false);
sub.setEnabled(false);
thresholdSlider.setEnabled(false);
rotateCW.setEnabled(false);
rotateCCW.setEnabled(false);
flipVert.setEnabled(false);
flipHorz.setEnabled(false);
selkeyclr.setEnabled(false);
fillAlpha.setSelected(false);
fillAlpha.setEnabled(false);
fillEdge.setSelected(false);
fillEdge.setEnabled(false);
} else {
int mode = paintMode.getSelectedIndex();
paintMode.setEnabled(true);
selBox.setEnabled(true);
sub.setEnabled(true);
thresholdSlider.setEnabled(true);
rotateCW.setEnabled(true);
rotateCCW.setEnabled(true);
flipVert.setEnabled(true);
flipHorz.setEnabled(true);
selkeyclr.setEnabled(true);
fillAlpha.setEnabled(mode == 0);
fillEdge.setEnabled(mode == 0);
}
repaint();
pc.repaint();
}
public boolean closeAll() {
while (tabs.getTabCount() > 0) {
if (!closeTab(true)) return false;
}
return true;
}
public void addLayer() {
int idx = getidx();
if (idx == -1) return;
PaintCanvas pc = imageTabs.get(idx).pc;
if (pc == null) return;
pc.addImageLayer();
pc.repaint();
}
public void delLayer() {
int idx = getidx();
if (idx == -1) return;
PaintCanvas pc = imageTabs.get(idx).pc;
if (pc == null) return;
pc.removeImageLayer(pc.getImageLayer());
pc.repaint();
}
public void editLayer() {
int idx = getidx();
if (idx == -1) return;
PaintCanvas pc = imageTabs.get(idx).pc;
if (pc == null) return;
int layer = pc.getImageLayer();
String newName = JF.getString("Edit layer name", pc.name[layer]);
if (newName == null) return;
pc.name[layer] = newName;
}
public void dupLayer() {
int idx = getidx();
if (idx == -1) return;
PaintCanvas pc = imageTabs.get(idx).pc;
if (pc == null) return;
int layer = pc.getImageLayer();
int px[] = pc.img[layer].getPixels();
pc.addImageLayer();
pc.swapLayers(layer+1, pc.getImageLayers()-1);
pc.img[layer+1].putPixels(px, 0, 0, pc.getUnscaledWidth(), pc.getUnscaledHeight(), 0);
pc.repaint();
}
public void mergeLayer() {
int idx = getidx();
if (idx == -1) return;
PaintCanvas pc = imageTabs.get(idx).pc;
if (pc == null) return;
int layer = pc.getImageLayer();
if (layer == 0) return;
pc.img[layer-1].getGraphics().drawImage(pc.img[layer].getImage(), 0, 0, null);
pc.removeImageLayer(layer);
pc.setImageLayer(layer-1);
pc.repaint();
}
public void moveLayerUp() {
int idx = getidx();
if (idx == -1) return;
PaintCanvas pc = imageTabs.get(idx).pc;
if (pc == null) return;
int layer = pc.getImageLayer();
if (layer == 0) return;
pc.swapLayers(layer, layer-1);
pc.setImageLayer(layer-1);
pc.repaint();
}
public void moveLayerDown() {
int idx = getidx();
if (idx == -1) return;
PaintCanvas pc = imageTabs.get(idx).pc;
if (pc == null) return;
int layer = pc.getImageLayer();
if (layer == pc.getImageLayers()-1) return;
pc.swapLayers(layer, layer+1);
pc.setImageLayer(layer+1);
pc.repaint();
}
}