You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1723 lines
66 KiB
1723 lines
66 KiB
package com.jotuntech.sketcher.client;
|
|
|
|
import info.clearthought.layout.TableLayout;
|
|
|
|
import java.applet.Applet;
|
|
import java.applet.AudioClip;
|
|
import java.awt.AlphaComposite;
|
|
import java.awt.BorderLayout;
|
|
import java.awt.Color;
|
|
import java.awt.Component;
|
|
import java.awt.Container;
|
|
import java.awt.Cursor;
|
|
import java.awt.Dimension;
|
|
import java.awt.Graphics;
|
|
import java.awt.Insets;
|
|
import java.awt.Rectangle;
|
|
import java.awt.Toolkit;
|
|
import java.awt.event.ActionEvent;
|
|
import java.awt.event.ActionListener;
|
|
import java.awt.event.AdjustmentEvent;
|
|
import java.awt.event.AdjustmentListener;
|
|
import java.awt.event.ComponentEvent;
|
|
import java.awt.event.ComponentListener;
|
|
import java.awt.event.MouseEvent;
|
|
import java.awt.event.MouseListener;
|
|
import java.awt.image.BufferedImage;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.DataOutputStream;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.OutputStream;
|
|
import java.io.RandomAccessFile;
|
|
import java.net.HttpURLConnection;
|
|
import java.net.URI;
|
|
import java.net.URL;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
import javax.imageio.ImageIO;
|
|
import javax.swing.AbstractListModel;
|
|
import javax.swing.BorderFactory;
|
|
import javax.swing.BoundedRangeModel;
|
|
import javax.swing.Box;
|
|
import javax.swing.BoxLayout;
|
|
import javax.swing.ButtonGroup;
|
|
import javax.swing.Icon;
|
|
import javax.swing.ImageIcon;
|
|
import javax.swing.JButton;
|
|
import javax.swing.JCheckBox;
|
|
import javax.swing.JCheckBoxMenuItem;
|
|
import javax.swing.JDialog;
|
|
import javax.swing.JFileChooser;
|
|
import javax.swing.JLabel;
|
|
import javax.swing.JList;
|
|
import javax.swing.JMenu;
|
|
import javax.swing.JMenuBar;
|
|
import javax.swing.JMenuItem;
|
|
import javax.swing.JOptionPane;
|
|
import javax.swing.JPanel;
|
|
import javax.swing.JProgressBar;
|
|
import javax.swing.JRadioButton;
|
|
import javax.swing.JScrollBar;
|
|
import javax.swing.JScrollPane;
|
|
import javax.swing.JSlider;
|
|
import javax.swing.JSpinner;
|
|
import javax.swing.JSplitPane;
|
|
import javax.swing.JTabbedPane;
|
|
import javax.swing.JTextArea;
|
|
import javax.swing.JTextField;
|
|
import javax.swing.JToggleButton;
|
|
import javax.swing.ListModel;
|
|
import javax.swing.SpinnerNumberModel;
|
|
import javax.swing.SwingConstants;
|
|
import javax.swing.SwingUtilities;
|
|
import javax.swing.event.ChangeEvent;
|
|
import javax.swing.event.ChangeListener;
|
|
import javax.swing.event.ListSelectionEvent;
|
|
import javax.swing.event.ListSelectionListener;
|
|
|
|
import com.jotuntech.sketcher.client.command.CreateLayerCommand;
|
|
import com.jotuntech.sketcher.client.command.DeleteLayerCommand;
|
|
import com.jotuntech.sketcher.client.command.FilterCommand;
|
|
import com.jotuntech.sketcher.client.command.KickCommand;
|
|
import com.jotuntech.sketcher.client.command.MergeCommand;
|
|
import com.jotuntech.sketcher.client.command.SayCommand;
|
|
import com.jotuntech.sketcher.client.command.SetBrushCommand;
|
|
import com.jotuntech.sketcher.client.command.SetColorCommand;
|
|
import com.jotuntech.sketcher.client.command.SetLayerCommand;
|
|
import com.jotuntech.sketcher.client.command.VoiceCommand;
|
|
import com.jotuntech.sketcher.common.Brush;
|
|
import com.jotuntech.sketcher.common.Canvas;
|
|
import com.jotuntech.sketcher.common.Layer;
|
|
import com.jotuntech.sketcher.common.LayerType;
|
|
import com.jotuntech.sketcher.common.Log;
|
|
import com.jotuntech.sketcher.common.Pixels;
|
|
import com.jotuntech.sketcher.common.TwoWayHashMap;
|
|
import com.jotuntech.sketcher.common.User;
|
|
import com.jotuntech.sketcher.common.filter.AutoContrastFilter;
|
|
import com.jotuntech.sketcher.common.filter.BlurFilter;
|
|
|
|
public class UserInterface extends JPanel {
|
|
public final static Insets NO_INSETS = new Insets(0, 0, 0, 0);
|
|
|
|
protected Client client;
|
|
|
|
private JSplitPane splitPane;
|
|
|
|
private JScrollPane editorPane;
|
|
private Editor editor;
|
|
|
|
private JPanel rightPanel;
|
|
|
|
private JMenuBar menuBar;
|
|
private JMenu filterMenu;
|
|
|
|
private JCheckBoxMenuItem soundItem, tagsItem;
|
|
|
|
JCollapsiblePanelGroup mainGroup;
|
|
|
|
private JScrollPane chatPane;
|
|
private JTextArea chatLog;
|
|
private JTextField chatField;
|
|
|
|
private BrushButton[] brushButtons;
|
|
|
|
private JLabel zoomLabel;
|
|
private JSpinner zoomSpin;
|
|
JCheckBox smoothBox;
|
|
|
|
private JCheckBox opacityBox, flowBox, radiusBox, lockTransBox;
|
|
|
|
private JUserList userList;
|
|
|
|
private JList layerList;
|
|
|
|
private JSlider hardnessSlider, sizeSlider, opacitySlider, flowSlider, spacingSlider, jitterSlider, noiseSlider, waterSlider, waterAreaSlider;
|
|
|
|
private JSlider redSlider, greenSlider, blueSlider;
|
|
private JPanel rgbColor;
|
|
|
|
private JSlider hueSlider, satSlider, brightSlider;
|
|
private JPanel hsbColor;
|
|
|
|
private JSlider cyanSlider, magentaSlider, yellowSlider;
|
|
private JPanel cmyColor;
|
|
|
|
private JCollapsiblePanel brushPanel, brushSettingsPanel, colorPanel, inputPanel;
|
|
|
|
private JToggleButton selectButton, moveButton, freehandButton, lineButton, bezierButton, rectangleButton, ovalButton;
|
|
|
|
private boolean smoothZoom = true;
|
|
private boolean colorAdjusting = false;
|
|
protected boolean brushAdjusting = false;
|
|
private boolean layerAdjusting = false;
|
|
|
|
public static AudioClip
|
|
AUDIO_INTRO = Applet.newAudioClip(UserInterface.class.getResource("audio/intro.wav")),
|
|
AUDIO_SIGN_IN = Applet.newAudioClip(UserInterface.class.getResource("audio/signin.wav")),
|
|
AUDIO_SIGN_OUT = Applet.newAudioClip(UserInterface.class.getResource("audio/signout.wav")),
|
|
AUDIO_KICK = Applet.newAudioClip(UserInterface.class.getResource("audio/kick.wav")),
|
|
AUDIO_CHAT = Applet.newAudioClip(UserInterface.class.getResource("audio/chat.wav")),
|
|
AUDIO_OUTTRO = Applet.newAudioClip(UserInterface.class.getResource("audio/outtro.wav"));
|
|
|
|
private static Icon[] brushIcons = new Icon[] {
|
|
new ImageIcon(UserInterface.class.getResource("images/pen.png")),
|
|
new ImageIcon(UserInterface.class.getResource("images/pencil.png")),
|
|
new ImageIcon(UserInterface.class.getResource("images/water2.png")),
|
|
new ImageIcon(UserInterface.class.getResource("images/eraser.png")),
|
|
new ImageIcon(UserInterface.class.getResource("images/ink.png")),
|
|
new ImageIcon(UserInterface.class.getResource("images/wipe.png"))
|
|
};
|
|
|
|
private void saveFileToDisk(final boolean selectionOnly) {
|
|
try {
|
|
final JFileChooser fileChooser = new JFileChooser();
|
|
if(fileChooser.showSaveDialog(null) != JFileChooser.APPROVE_OPTION) {
|
|
return;
|
|
}
|
|
|
|
final File file = fileChooser.getSelectedFile();
|
|
|
|
if(file.exists()) {
|
|
if(JOptionPane.showConfirmDialog(null, "Overwrite existing file?", "Confirm", JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
Thread saveThread = new Thread("SaveThread") {
|
|
public void run() {
|
|
BufferedImage image;
|
|
if(selectionOnly) {
|
|
Rectangle s = editor.getSelect();
|
|
if(s == null) {
|
|
JOptionPane.showMessageDialog(UserInterface.this, "Cannot save empty selection!", "Error", JOptionPane.ERROR_MESSAGE);
|
|
return;
|
|
}
|
|
image = editor.getImage().getSubimage(s.x, s.y, s.width, s.height);
|
|
} else {
|
|
image = editor.getImage();
|
|
}
|
|
|
|
if(file.getName().toUpperCase().endsWith(".PNG")) {
|
|
println("Saving PNG file. Please wait...");
|
|
try {
|
|
ImageIO.write(image, "PNG", file);
|
|
} catch (Throwable e) {
|
|
JOptionPane.showMessageDialog(UserInterface.this, "Unable to save file! (" + e.getMessage() + ")", "Error", JOptionPane.ERROR_MESSAGE);
|
|
return;
|
|
}
|
|
println("Completed!");
|
|
} else if(file.getName().toUpperCase().endsWith(".PSD")) {
|
|
if(selectionOnly) {
|
|
JOptionPane.showMessageDialog(UserInterface.this, "Cannot save partial canvases in PSD format!", "Error", JOptionPane.ERROR_MESSAGE);
|
|
return;
|
|
}
|
|
println("Saving PSD file. Please wait...");
|
|
Canvas canvas = client.getCanvas();
|
|
TwoWayHashMap<Integer, Layer> lm = canvas.getLayerMap();
|
|
try {
|
|
RandomAccessFile raf = new RandomAccessFile(fileChooser.getSelectedFile(), "rw");
|
|
|
|
PSDEncoder psde = new PSDEncoder(raf, image, lm);
|
|
psde.encode();
|
|
raf.close();
|
|
System.gc();
|
|
} catch (Throwable e) {
|
|
JOptionPane.showMessageDialog(UserInterface.this, "Unable to save file! (" + e.getMessage() + ")", "Error", JOptionPane.ERROR_MESSAGE);
|
|
return;
|
|
}
|
|
println("Completed!");
|
|
} else {
|
|
JOptionPane.showMessageDialog(UserInterface.this, "You need to add an extension like .png or .psd to save a file!", "Error", JOptionPane.ERROR_MESSAGE);
|
|
}
|
|
}
|
|
};
|
|
saveThread.setPriority(Thread.MIN_PRIORITY);
|
|
saveThread.start();
|
|
} catch(SecurityException e) {
|
|
JOptionPane.showMessageDialog(UserInterface.this, "You cannot use the save feature without accepting the security certificate!", "Error", JOptionPane.ERROR_MESSAGE);
|
|
}
|
|
}
|
|
|
|
public UserInterface(final Client client) {
|
|
super(new BorderLayout());
|
|
|
|
this.client = client;
|
|
|
|
editor = new Editor(client);
|
|
editor.setSmoothZoom(true);
|
|
|
|
if(client.isAds()) {
|
|
try {
|
|
BufferedImage bi = ImageIO.read(UserInterface.class.getResource("images/ad1.png"));
|
|
editor.setAd(bi);
|
|
editor.setAdPosition(-468, -60);
|
|
} catch (IOException e1) {
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
|
|
if(!LookAndFeel.NIMBUS.activate()) {
|
|
LookAndFeel.SYSTEM.activate();
|
|
}
|
|
|
|
editorPane = new JScrollPane(editor);
|
|
|
|
AdjustmentListener canvasScroller = new AdjustmentListener() {
|
|
public void adjustmentValueChanged(AdjustmentEvent arg0) {
|
|
boolean adjusting = arg0.getValueIsAdjusting();
|
|
editor.setAdPosition(editorPane.getHorizontalScrollBar().getValue() + editorPane.getViewport().getWidth() - 478, editorPane.getVerticalScrollBar().getValue() + 10);
|
|
if(smoothZoom) {
|
|
if(adjusting) {
|
|
editor.setSmoothZoom(false);
|
|
} else {
|
|
editor.setSmoothZoom(true);
|
|
editor.repaint();
|
|
}
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
editorPane.getVerticalScrollBar().addAdjustmentListener(canvasScroller);
|
|
editorPane.getHorizontalScrollBar().addAdjustmentListener(canvasScroller);
|
|
|
|
/** Create panel for tools */
|
|
rightPanel = new JPanel();
|
|
rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS));
|
|
|
|
/** Make split pane with canvas on left, tools on right */
|
|
splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, editorPane, rightPanel);
|
|
splitPane.setResizeWeight(1.0);
|
|
splitPane.setOneTouchExpandable(true);
|
|
add(splitPane, BorderLayout.CENTER);
|
|
|
|
menuBar = new JMenuBar();
|
|
menuBar.setAlignmentX(Component.LEFT_ALIGNMENT);
|
|
menuBar.setMinimumSize(new Dimension(0, 24));
|
|
menuBar.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
|
|
rightPanel.add(menuBar);
|
|
|
|
JMenu fileMenu = new JMenu("File");
|
|
menuBar.add(fileMenu);
|
|
|
|
JMenuItem saveItem = new JMenuItem("Save Canvas As...");
|
|
saveItem.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent arg0) {
|
|
saveFileToDisk(false);
|
|
}
|
|
});
|
|
fileMenu.add(saveItem);
|
|
|
|
JMenuItem saveSelectItem = new JMenuItem("Save Selection As...");
|
|
saveSelectItem.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent arg0) {
|
|
saveFileToDisk(true);
|
|
}
|
|
});
|
|
fileMenu.add(saveSelectItem);
|
|
|
|
JMenuItem uploadSelectItem = new JMenuItem("Upload Selection...");
|
|
uploadSelectItem.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent arg0) {
|
|
final Rectangle s = editor.getSelect();
|
|
if(s == null) {
|
|
JOptionPane.showMessageDialog(UserInterface.this, "Cannot upload empty selection!", "Error", JOptionPane.ERROR_MESSAGE);
|
|
return;
|
|
}
|
|
|
|
final JDialog uploadDialog = new JDialog();
|
|
uploadDialog.setTitle("Upload Selection to ArtGrounds.com");
|
|
uploadDialog.setResizable(false);
|
|
uploadDialog.setModal(true);
|
|
Container contentPane = uploadDialog.getContentPane();
|
|
contentPane.setLayout(new BorderLayout());
|
|
JPanel northPanel = new JPanel();
|
|
northPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 0, 8));
|
|
northPanel.setLayout(new BoxLayout(northPanel, BoxLayout.Y_AXIS));
|
|
northPanel.add(new JLabel("Format:"));
|
|
JPanel formatPanel = new JPanel();
|
|
formatPanel.setLayout(new BoxLayout(formatPanel, BoxLayout.X_AXIS));
|
|
ButtonGroup formatGroup = new ButtonGroup();
|
|
final JRadioButton jpegButton = new JRadioButton("JPEG (realism, paintings, soft shading)");
|
|
jpegButton.setSelected(true);
|
|
formatGroup.add(jpegButton);
|
|
formatPanel.add(jpegButton);
|
|
formatPanel.add(Box.createRigidArea(new Dimension(8, 0)));
|
|
final JRadioButton pngButton = new JRadioButton("PNG (cartoons, drawings, hard shading)");
|
|
formatGroup.add(pngButton);
|
|
formatPanel.add(pngButton);
|
|
northPanel.add(formatPanel);
|
|
formatPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
|
northPanel.add(new JLabel("Title:"));
|
|
final JTextField titleField = new JTextField();
|
|
titleField.setAlignmentX(Component.LEFT_ALIGNMENT);
|
|
northPanel.add(titleField);
|
|
northPanel.add(Box.createRigidArea(new Dimension(0, 8)));
|
|
northPanel.add(new JLabel("Description:"));
|
|
contentPane.add(northPanel, BorderLayout.NORTH);
|
|
contentPane.add(Box.createRigidArea(new Dimension(8, 0)), BorderLayout.WEST);
|
|
final JTextArea descArea = new JTextArea();
|
|
contentPane.add(descArea, BorderLayout.CENTER);
|
|
contentPane.add(Box.createRigidArea(new Dimension(8, 0)), BorderLayout.EAST);
|
|
JPanel southPanel = new JPanel();
|
|
southPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
|
|
southPanel.setLayout(new BoxLayout(southPanel, BoxLayout.X_AXIS));
|
|
final JProgressBar progressBar = new JProgressBar();
|
|
southPanel.add(progressBar);
|
|
southPanel.add(Box.createRigidArea(new Dimension(8, 0)));
|
|
final JCheckBox matureBox = new JCheckBox("Mature Content");
|
|
southPanel.add(matureBox);
|
|
southPanel.add(Box.createRigidArea(new Dimension(8, 0)));
|
|
final JButton cancelButton = new JButton("Cancel");
|
|
cancelButton.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
uploadDialog.setVisible(false);
|
|
}
|
|
});
|
|
final JButton uploadButton = new JButton("Upload");
|
|
uploadButton.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
Thread saveThread = new Thread("SaveThread") {
|
|
public void run() {
|
|
try {
|
|
String title = titleField.getText().trim();
|
|
if(title.isEmpty()) {
|
|
JOptionPane.showMessageDialog(uploadDialog, "Title cannot be empty!", "Error", JOptionPane.ERROR_MESSAGE);
|
|
return;
|
|
}
|
|
String description = descArea.getText().trim();
|
|
if(description.isEmpty()) {
|
|
JOptionPane.showMessageDialog(uploadDialog, "Description cannot be empty!", "Error", JOptionPane.ERROR_MESSAGE);
|
|
return;
|
|
}
|
|
|
|
uploadButton.setEnabled(false);
|
|
jpegButton.setEnabled(false);
|
|
pngButton.setEnabled(false);
|
|
titleField.setEnabled(false);
|
|
descArea.setEnabled(false);
|
|
matureBox.setEnabled(false);
|
|
|
|
BufferedImage argbImage = editor.getImage().getSubimage(s.x, s.y, s.width, s.height);
|
|
BufferedImage rgbImage = new BufferedImage(s.width, s.height, BufferedImage.TYPE_INT_RGB);
|
|
Graphics g = rgbImage.getGraphics();
|
|
g.drawImage(argbImage, 0, 0, editor.getCanvasBackground(), null);
|
|
|
|
BufferedImage madeImage = ImageIO.read(UserInterface.class.getResource("images/madeinsketcher.png"));
|
|
g.drawImage(madeImage, s.width - madeImage.getWidth() - 2, 2, null);
|
|
|
|
ByteArrayOutputStream imgbaos = new ByteArrayOutputStream();
|
|
ImageIO.write(rgbImage, jpegButton.isSelected() ? "JPG" : "PNG", imgbaos);
|
|
byte[] imgarr = imgbaos.toByteArray();
|
|
progressBar.setMaximum(imgarr.length);
|
|
|
|
ByteArrayOutputStream hdrbaos = new ByteArrayOutputStream();
|
|
DataOutputStream hdrdos = new DataOutputStream(hdrbaos);
|
|
hdrdos.writeUTF(client.getLogin());
|
|
hdrdos.writeUTF(client.getPassword());
|
|
hdrdos.writeUTF(title);
|
|
hdrdos.writeUTF(description);
|
|
hdrdos.writeBoolean(matureBox.isSelected());
|
|
hdrdos.writeInt(imgarr.length);
|
|
byte[] hdrarr = hdrbaos.toByteArray();
|
|
|
|
int contentLength = hdrarr.length + imgarr.length;
|
|
|
|
URL url = new URL("http://www.artgrounds.com/sketcher-upload/");
|
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
|
conn.setFixedLengthStreamingMode(contentLength);
|
|
conn.setDoOutput(true);
|
|
|
|
OutputStream httpos = conn.getOutputStream();
|
|
|
|
httpos.write(hdrarr);
|
|
|
|
for(int ofs = 0; ofs < imgarr.length; ofs += 1458) {
|
|
progressBar.setValue(ofs);
|
|
httpos.write(imgarr, ofs, Math.min(1458, imgarr.length - ofs));
|
|
httpos.flush();
|
|
}
|
|
progressBar.setValue(imgarr.length);
|
|
httpos.flush();
|
|
httpos.close();
|
|
|
|
if(conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
|
|
progressBar.setValue(0);
|
|
uploadButton.setEnabled(true);
|
|
jpegButton.setEnabled(true);
|
|
pngButton.setEnabled(true);
|
|
titleField.setEnabled(true);
|
|
descArea.setEnabled(true);
|
|
matureBox.setEnabled(true);
|
|
JOptionPane.showMessageDialog(uploadDialog, "Unable to upload image! (" + conn.getResponseCode() + " " + conn.getResponseMessage() + ")", "Error", JOptionPane.ERROR_MESSAGE);
|
|
return;
|
|
}
|
|
|
|
cancelButton.setText("Close");
|
|
|
|
JOptionPane.showMessageDialog(uploadDialog, "Upload completed!", "Information", JOptionPane.INFORMATION_MESSAGE);
|
|
} catch (Throwable t) {
|
|
progressBar.setValue(0);
|
|
uploadButton.setEnabled(true);
|
|
jpegButton.setEnabled(true);
|
|
pngButton.setEnabled(true);
|
|
titleField.setEnabled(true);
|
|
descArea.setEnabled(true);
|
|
matureBox.setEnabled(true);
|
|
JOptionPane.showMessageDialog(uploadDialog, "Unable to upload image! (" + t.getClass().getSimpleName() + " " + t.getMessage() + ")", "Error", JOptionPane.ERROR_MESSAGE);
|
|
Log.error(t);
|
|
}
|
|
}
|
|
};
|
|
saveThread.setPriority(Thread.MIN_PRIORITY);
|
|
saveThread.start();
|
|
}
|
|
});
|
|
southPanel.add(uploadButton);
|
|
southPanel.add(cancelButton);
|
|
contentPane.add(southPanel, BorderLayout.SOUTH);
|
|
uploadDialog.setPreferredSize(new Dimension(512, 512));
|
|
uploadDialog.pack();
|
|
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
|
uploadDialog.setLocation((screenSize.width - uploadDialog.getWidth()) / 2, (screenSize.height - uploadDialog.getHeight()) / 2);
|
|
uploadDialog.setVisible(true);
|
|
}
|
|
});
|
|
fileMenu.add(uploadSelectItem);
|
|
|
|
JMenu optMenu = new JMenu("Options");
|
|
menuBar.add(optMenu);
|
|
|
|
soundItem = new JCheckBoxMenuItem("Sounds", client.isSoundEnabled());
|
|
soundItem.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
client.setSoundEnabled(((JCheckBoxMenuItem) e.getSource()).isSelected());
|
|
}
|
|
});
|
|
|
|
optMenu.add(soundItem);
|
|
|
|
tagsItem = new JCheckBoxMenuItem("Tags", editor.isTagsEnabled());
|
|
tagsItem.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
editor.setTagsEnabled(((JCheckBoxMenuItem) e.getSource()).isSelected());
|
|
editor.repaint();
|
|
}
|
|
});
|
|
|
|
optMenu.add(tagsItem);
|
|
|
|
JCheckBoxMenuItem voiceItem = new JCheckBoxMenuItem("Voice", client.isVoiceEnabled());
|
|
voiceItem.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
client.getCommandQueue().offer(new CommandEntry(0, new VoiceCommand(((JCheckBoxMenuItem) e.getSource()).isSelected())));
|
|
}
|
|
});
|
|
|
|
optMenu.add(voiceItem);
|
|
|
|
JCheckBoxMenuItem swCursorItem = new JCheckBoxMenuItem("Software Cursor", editor.isSoftwareCursorEnabled());
|
|
swCursorItem.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
editor.setSoftwareCursorEnabled(((JCheckBoxMenuItem) e.getSource()).isSelected());
|
|
editor.setCursorType(Editor.CursorType.SOFTWARE);
|
|
}
|
|
});
|
|
|
|
optMenu.add(swCursorItem);
|
|
|
|
|
|
JMenuItem resetItem = new JMenuItem("Reset");
|
|
resetItem.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
int confirm = JOptionPane.showConfirmDialog(UserInterface.this, "This will erase all your settings permanently. Continue?", "Confirm", JOptionPane.YES_NO_OPTION);
|
|
if(confirm != JOptionPane.OK_OPTION) {
|
|
return;
|
|
}
|
|
client.resetProps();
|
|
}
|
|
});
|
|
|
|
optMenu.add(resetItem);
|
|
|
|
filterMenu = new JMenu("Filters");
|
|
filterMenu.setEnabled(false);
|
|
menuBar.add(filterMenu);
|
|
|
|
JMenuItem blurItem = new JMenuItem("Blur");
|
|
blurItem.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
final Rectangle select = editor.getSelect();
|
|
if(select == null) {
|
|
JOptionPane.showMessageDialog(UserInterface.this, "You must select an area before you can blur anything!", "Error", JOptionPane.ERROR_MESSAGE);
|
|
return;
|
|
}
|
|
|
|
final JDialog blurDialog = new JDialog();
|
|
blurDialog.setTitle("Blur");
|
|
blurDialog.setModal(true);
|
|
|
|
Container contentPane = blurDialog.getContentPane();
|
|
contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.X_AXIS));
|
|
|
|
contentPane.add(new JLabel("Size: "));
|
|
final SpinnerNumberModel sizeModel = new SpinnerNumberModel(5, 0.5, 50, 0.5);
|
|
JSpinner sizeSpin = new JSpinner(sizeModel);
|
|
contentPane.add(sizeSpin);
|
|
JButton okButton = new JButton("OK");
|
|
okButton.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
blurDialog.setVisible(false);
|
|
editor.requestFocusInWindow();
|
|
client.getCommandQueue().offer(new CommandEntry(0, new FilterCommand(new BlurFilter(), select.x, select.y, select.width, select.height, ((Double) sizeModel.getValue()).floatValue(), 0f, 0f)));
|
|
client.getCommandQueue().offer(new CommandEntry(0, new MergeCommand()));
|
|
}
|
|
});
|
|
contentPane.add(okButton);
|
|
JButton cancelButton = new JButton("Cancel");
|
|
cancelButton.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
editor.requestFocusInWindow();
|
|
blurDialog.setVisible(false);
|
|
}
|
|
});
|
|
contentPane.add(cancelButton);
|
|
blurDialog.pack();
|
|
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
|
blurDialog.setLocation((screenSize.width - blurDialog.getWidth()) / 2, (screenSize.height - blurDialog.getHeight()) / 2);
|
|
blurDialog.setVisible(true);
|
|
}
|
|
});
|
|
filterMenu.add(blurItem);
|
|
|
|
JMenuItem autoContrastItem = new JMenuItem("Auto Contrast");
|
|
autoContrastItem.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
final Rectangle select = editor.getSelect();
|
|
if(select == null) {
|
|
JOptionPane.showMessageDialog(UserInterface.this, "You must select an area before you can correct its contrast!", "Error", JOptionPane.ERROR_MESSAGE);
|
|
return;
|
|
}
|
|
|
|
client.getCommandQueue().offer(new CommandEntry(0, new FilterCommand(new AutoContrastFilter(), select.x, select.y, select.width, select.height, 0.05f, 0.05f, 0.05f)));
|
|
client.getCommandQueue().offer(new CommandEntry(0, new MergeCommand()));
|
|
}
|
|
});
|
|
filterMenu.add(autoContrastItem);
|
|
|
|
menuBar.add(Box.createHorizontalGlue());
|
|
|
|
JMenu helpMenu = new JMenu("Help");
|
|
menuBar.add(helpMenu);
|
|
|
|
JMenuItem aboutItem = new JMenuItem("About");
|
|
aboutItem.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
final JDialog aboutDialog = new JDialog();
|
|
aboutDialog.setTitle("About Sketcher\u2122");
|
|
aboutDialog.setResizable(false);
|
|
aboutDialog.setModal(true);
|
|
Container contentPane = aboutDialog.getContentPane();
|
|
contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
|
|
JLabel label = new JLabel(new ImageIcon(getClass().getResource("images/about.png")));
|
|
label.addMouseListener(new MouseListener() {
|
|
public void mouseClicked(MouseEvent e) {
|
|
aboutDialog.setVisible(false);
|
|
}
|
|
|
|
public void mouseEntered(MouseEvent e) { }
|
|
public void mouseExited(MouseEvent e) { }
|
|
public void mousePressed(MouseEvent e) { }
|
|
public void mouseReleased(MouseEvent e) { }
|
|
});
|
|
contentPane.add(label);
|
|
aboutDialog.pack();
|
|
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
|
aboutDialog.setLocation((screenSize.width - aboutDialog.getWidth()) / 2, (screenSize.height - aboutDialog.getHeight()) / 2);
|
|
aboutDialog.setVisible(true);
|
|
}
|
|
});
|
|
helpMenu.add(aboutItem);
|
|
|
|
JLabel copyright = new JLabel(new ImageIcon(UserInterface.class.getResource("images/sketcherlogo.png")));
|
|
copyright.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
|
copyright.setAlignmentX(Component.LEFT_ALIGNMENT);
|
|
copyright.setHorizontalAlignment(SwingConstants.CENTER);
|
|
copyright.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
|
|
copyright.addMouseListener(new MouseListener() {
|
|
public void mouseClicked(MouseEvent e) {
|
|
try {
|
|
Class<?> desktopClass = Class.forName("java.awt.Desktop");
|
|
if((Boolean) desktopClass.getMethod("isDesktopSupported").invoke(null)) { // Desktop.isDesktopSupported()
|
|
Object desktop = desktopClass.getMethod("getDesktop").invoke(null); // Desktop.getDesktop()
|
|
Class<?> actionClass = Class.forName("java.awt.Desktop$Action");
|
|
if((Boolean) desktopClass.getMethod("isSupported", actionClass).invoke(desktop, actionClass.getField("BROWSE").get(null))) { // desktop.isSupported(java.awt.Desktop.Action.BROWSE)
|
|
desktopClass.getMethod("browse", URI.class).invoke(desktop, new URI("http://sketcher.artgrounds.com/")); // desktop.browse(uri);
|
|
return;
|
|
}
|
|
}
|
|
} catch(Throwable t) { }
|
|
|
|
JOptionPane.showMessageDialog(UserInterface.this, "Visit sketcher.artgrounds.com for more information about Sketcher!");
|
|
}
|
|
|
|
public void mouseEntered(MouseEvent e) { }
|
|
public void mouseExited(MouseEvent e) { }
|
|
public void mousePressed(MouseEvent e) { }
|
|
public void mouseReleased(MouseEvent e) { }
|
|
});
|
|
rightPanel.add(copyright);
|
|
|
|
mainGroup = new JCollapsiblePanelGroup();
|
|
|
|
/** Set up view panel */
|
|
JCollapsiblePanel viewPanel = new JCollapsiblePanel(100, "Canvas", false, false);
|
|
viewPanel.setGroup(mainGroup);
|
|
JPanel viewPanelContent = viewPanel.getContentPane();
|
|
viewPanelContent.setLayout(new BoxLayout(viewPanelContent, BoxLayout.Y_AXIS));
|
|
|
|
/* Set up zoom panel */
|
|
JPanel zoomPanel = new JPanel();
|
|
zoomPanel.setLayout(new BoxLayout(zoomPanel, BoxLayout.X_AXIS));
|
|
viewPanelContent.add(zoomPanel);
|
|
|
|
zoomPanel.add(Box.createHorizontalGlue());
|
|
|
|
zoomLabel = new JLabel(new ImageIcon(UserInterface.class.getResource("images/zoom.png")));
|
|
zoomLabel.setAlignmentY(Component.CENTER_ALIGNMENT);
|
|
zoomPanel.add(zoomLabel);
|
|
|
|
zoomSpin = new JSpinner(new SpinnerNumberModel(100, 10, 800, 25));
|
|
zoomSpin.setToolTipText("Zoom - grow or shrink the displayed canvas.");
|
|
zoomSpin.setAlignmentY(Component.CENTER_ALIGNMENT);
|
|
zoomPanel.add(zoomSpin);
|
|
|
|
zoomSpin.getModel().addChangeListener(new ChangeListener() {
|
|
|
|
public void stateChanged(ChangeEvent arg0) {
|
|
if(client.getCanvas() != null) {
|
|
try {
|
|
int newZoom = (Integer)zoomSpin.getValue();
|
|
|
|
if(newZoom > 0 && newZoom <= 800) {
|
|
/* Fetch scrollbars */
|
|
JScrollBar v = editorPane.getHorizontalScrollBar();
|
|
JScrollBar h = editorPane.getVerticalScrollBar();
|
|
|
|
/* Fetch fractions */
|
|
float hf = (float)h.getValue() / (float)h.getMaximum();
|
|
float vf = (float)v.getValue() / (float)v.getMaximum();
|
|
float hvis = (float)h.getVisibleAmount() / (float)h.getMaximum();
|
|
float vvis = (float)v.getVisibleAmount() / (float)v.getMaximum();
|
|
|
|
/* Change zoom */
|
|
editor.setZoom(newZoom / 100f);
|
|
editor.repaint();
|
|
|
|
/* Apply old fractions to new viewport */
|
|
float nhvis = (float)h.getVisibleAmount() / (float)h.getMaximum();
|
|
float nvvis = (float)v.getVisibleAmount() / (float)v.getMaximum();
|
|
h.setValue((int)((hf + (hvis - nhvis) / 2) * h.getMaximum()));
|
|
v.setValue((int)((vf + (vvis - nvvis) / 2) * v.getMaximum()));
|
|
}
|
|
} catch(NumberFormatException e) {
|
|
/** Ignore bad numbers */
|
|
}
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
/** Smooth zoom box */
|
|
smoothBox = new JCheckBox("Smoothly");
|
|
smoothBox.setToolTipText("Display the canvas smoothly for zoom settings not divisble by 100. Somewhat computing intensive.");
|
|
smoothBox.setAlignmentY(Component.CENTER_ALIGNMENT);
|
|
smoothBox.setHorizontalAlignment(JCheckBox.CENTER);
|
|
smoothBox.setSelected(smoothZoom);
|
|
zoomPanel.add(smoothBox);
|
|
|
|
smoothBox.addActionListener(new ActionListener() {
|
|
|
|
public void actionPerformed(ActionEvent arg0) {
|
|
smoothZoom = smoothBox.isSelected();
|
|
editor.setSmoothZoom(smoothZoom);
|
|
editor.repaint();
|
|
}
|
|
|
|
});
|
|
|
|
zoomPanel.add(Box.createHorizontalGlue());
|
|
|
|
/* Background brightness */
|
|
final JSlider backgroundSlider = new JSlider(0, 255, 255);
|
|
backgroundSlider.setToolTipText("Background brightness - adjust the background brightness to see layer transparency.");
|
|
backgroundSlider.addChangeListener(new ChangeListener() {
|
|
public void stateChanged(ChangeEvent arg0) {
|
|
if(!backgroundSlider.getModel().getValueIsAdjusting()) {
|
|
int brightness = backgroundSlider.getValue();
|
|
editor.setCanvasBackground(new Color(brightness, brightness, brightness));
|
|
editor.repaint();
|
|
}
|
|
}
|
|
});
|
|
viewPanelContent.add(backgroundSlider);
|
|
|
|
rightPanel.add(viewPanel);
|
|
|
|
|
|
/** Create Tools panel, add to right panel */
|
|
JCollapsiblePanel toolsPanel = new JCollapsiblePanel(150, "Tools", true, true);
|
|
toolsPanel.setGroup(mainGroup);
|
|
rightPanel.add(toolsPanel);
|
|
JPanel toolsPane = toolsPanel.getContentPane();
|
|
toolsPane.setLayout(new BoxLayout(toolsPane, BoxLayout.X_AXIS));
|
|
|
|
/** Make group for buttons */
|
|
ButtonGroup toolButtonGroup = new ButtonGroup();
|
|
|
|
toolsPane.add(Box.createHorizontalGlue());
|
|
|
|
selectButton = new JToggleButton(loadImageIcon("select.png"));
|
|
selectButton.setToolTipText("Select");
|
|
selectButton.setMargin(UserInterface.NO_INSETS);
|
|
selectButton.setMinimumSize(new Dimension(32, 32));
|
|
selectButton.setPreferredSize(new Dimension(32, 32));
|
|
selectButton.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
editor.setState(Editor.State.SELECT_HOVER);
|
|
updatePanels();
|
|
}
|
|
});
|
|
toolsPane.add(selectButton);
|
|
toolButtonGroup.add(selectButton);
|
|
|
|
moveButton = new JToggleButton(loadImageIcon("move.png"));
|
|
moveButton.setToolTipText("Duplicate");
|
|
moveButton.setMargin(UserInterface.NO_INSETS);
|
|
moveButton.setMinimumSize(new Dimension(32, 32));
|
|
moveButton.setPreferredSize(new Dimension(32, 32));
|
|
moveButton.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
editor.setState(Editor.State.MOVE_HOVER);
|
|
updatePanels();
|
|
}
|
|
});
|
|
toolsPane.add(moveButton);
|
|
toolButtonGroup.add(moveButton);
|
|
|
|
freehandButton = new JToggleButton(loadImageIcon("freehand.png"));
|
|
freehandButton.setSelected(true);
|
|
freehandButton.setToolTipText("Freehand");
|
|
freehandButton.setMargin(UserInterface.NO_INSETS);
|
|
freehandButton.setMinimumSize(new Dimension(32, 32));
|
|
freehandButton.setPreferredSize(new Dimension(32, 32));
|
|
freehandButton.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
editor.setState(Editor.State.DRAW_HOVER);
|
|
updatePanels();
|
|
}
|
|
});
|
|
toolsPane.add(freehandButton);
|
|
toolButtonGroup.add(freehandButton);
|
|
|
|
lineButton = new JToggleButton(loadImageIcon("line.png"));
|
|
lineButton.setToolTipText("Line");
|
|
lineButton.setMargin(UserInterface.NO_INSETS);
|
|
lineButton.setMinimumSize(new Dimension(32, 32));
|
|
lineButton.setPreferredSize(new Dimension(32, 32));
|
|
lineButton.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
editor.setState(Editor.State.LINE_HOVER);
|
|
updatePanels();
|
|
}
|
|
});
|
|
toolsPane.add(lineButton);
|
|
toolButtonGroup.add(lineButton);
|
|
|
|
bezierButton = new JToggleButton(loadImageIcon("bezier.png"));
|
|
bezierButton.setToolTipText("Bezier");
|
|
bezierButton.setMargin(UserInterface.NO_INSETS);
|
|
bezierButton.setMinimumSize(new Dimension(32, 32));
|
|
bezierButton.setPreferredSize(new Dimension(32, 32));
|
|
bezierButton.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
editor.setState(Editor.State.BEZIER_HOVER);
|
|
updatePanels();
|
|
}
|
|
});
|
|
toolsPane.add(bezierButton);
|
|
toolButtonGroup.add(bezierButton);
|
|
|
|
rectangleButton = new JToggleButton(loadImageIcon("rectangle.png"));
|
|
rectangleButton.setToolTipText("Rectangle");
|
|
rectangleButton.setMargin(UserInterface.NO_INSETS);
|
|
rectangleButton.setMinimumSize(new Dimension(32, 32));
|
|
rectangleButton.setPreferredSize(new Dimension(32, 32));
|
|
rectangleButton.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
editor.setState(Editor.State.RECT_HOVER);
|
|
updatePanels();
|
|
}
|
|
});
|
|
toolsPane.add(rectangleButton);
|
|
toolButtonGroup.add(rectangleButton);
|
|
|
|
ovalButton = new JToggleButton(loadImageIcon("oval.png"));
|
|
ovalButton.setToolTipText("Oval");
|
|
ovalButton.setMargin(UserInterface.NO_INSETS);
|
|
ovalButton.setMinimumSize(new Dimension(32, 32));
|
|
ovalButton.setPreferredSize(new Dimension(32, 32));
|
|
ovalButton.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent e) {
|
|
editor.setState(Editor.State.OVAL_HOVER);
|
|
updatePanels();
|
|
}
|
|
});
|
|
toolsPane.add(ovalButton);
|
|
toolButtonGroup.add(ovalButton);
|
|
|
|
toolsPane.add(Box.createHorizontalGlue());
|
|
|
|
/** Create Brushes panel, add to right panel */
|
|
brushPanel = new JCollapsiblePanel(200, "Brushes", true, true);
|
|
brushPanel.setGroup(mainGroup);
|
|
rightPanel.add(brushPanel);
|
|
JPanel brushesPane = brushPanel.getContentPane();
|
|
brushesPane.setLayout(new BoxLayout(brushesPane, BoxLayout.X_AXIS));
|
|
|
|
/** Make group for buttons */
|
|
ButtonGroup brushButtonGroup = new ButtonGroup();
|
|
|
|
/** Make, add and group brush buttons */
|
|
brushButtons = new BrushButton[client.brushes.length];
|
|
|
|
brushesPane.add(Box.createHorizontalGlue());
|
|
|
|
for(int i = 0; i < brushButtons.length; i++) {
|
|
BrushButton b = new BrushButton(this, client.brushes, brushIcons, i);
|
|
brushesPane.add(b);
|
|
brushButtonGroup.add(b);
|
|
brushButtons[i] = b;
|
|
}
|
|
|
|
brushesPane.add(Box.createHorizontalGlue());
|
|
|
|
/** BRUSH panel */
|
|
TableLayout brushTabLayout = new TableLayout(new double[][] {{0, -2, -1, -2, 0}, {-2, -2, -2, -2, -2, -2, -2, -2, -2}});
|
|
brushSettingsPanel = new JCollapsiblePanel(300, "Brush settings", false, false);
|
|
brushSettingsPanel.setGroup(mainGroup);
|
|
JPanel brushTab = brushSettingsPanel.getContentPane();
|
|
brushTab.setLayout(brushTabLayout);
|
|
brushTab.setAlignmentX(Component.LEFT_ALIGNMENT);
|
|
rightPanel.add(brushSettingsPanel);
|
|
|
|
/** HARDNESS */
|
|
brushTab.add(new JLabel(loadImageIcon("hardness.png")), "1 0 r c");
|
|
hardnessSlider = new JSlider(1, 12, 1);
|
|
hardnessSlider.setToolTipText("Hardness - controls the crispness of the brush.");
|
|
hardnessSlider.setSnapToTicks(true);
|
|
brushTab.add(hardnessSlider, "2 0 2 0");
|
|
hardnessSlider.addChangeListener(new ChangeListener() {
|
|
public void stateChanged(ChangeEvent arg0) {
|
|
if(!hardnessSlider.getModel().getValueIsAdjusting() && !brushAdjusting && client.getConnection().getUser() != null && client.getConnection().getUser().getBrush() != null) {
|
|
client.getConnection().getUser().getBrush().setHardness(hardnessSlider.getValue());
|
|
client.getConnection().getSendQueue().offer(new CommandEntry(0, new SetBrushCommand(client.getConnection().getUser().getBrush())));
|
|
}
|
|
}
|
|
});
|
|
|
|
/** SIZE */
|
|
brushTab.add(new JLabel(loadImageIcon("size.png")), "1 1 r c");
|
|
sizeSlider = new JSlider(1, 1008, 1);
|
|
sizeSlider.setToolTipText("Size - controls the diameter of the brush.");
|
|
brushTab.add(sizeSlider, "2 1 2 1");
|
|
sizeSlider.addChangeListener(new ChangeListener() {
|
|
|
|
public void stateChanged(ChangeEvent arg0) {
|
|
if(!sizeSlider.getModel().getValueIsAdjusting() && !brushAdjusting && client.getConnection().getUser() != null && client.getConnection().getUser().getBrush() != null) {
|
|
client.getConnection().getUser().getBrush().setRadius(sizeSlider.getValue() / 8f);
|
|
client.getConnection().getSendQueue().offer(new CommandEntry(0, new SetBrushCommand(client.getConnection().getUser().getBrush())));
|
|
}
|
|
}
|
|
});
|
|
|
|
/** OPACITY */
|
|
brushTab.add(new JLabel(loadImageIcon("opacity.png")), "1 2 r c");
|
|
opacitySlider = new JSlider(-255, 255, 0);
|
|
opacitySlider.setMajorTickSpacing(255);
|
|
opacitySlider.setPaintTicks(true);
|
|
opacitySlider.setToolTipText("Opacity - controls the opacity of the brush.");
|
|
brushTab.add(opacitySlider, "2 2 2 2");
|
|
opacitySlider.addChangeListener(new ChangeListener() {
|
|
public void stateChanged(ChangeEvent arg0) {
|
|
if(!opacitySlider.getModel().getValueIsAdjusting() && !brushAdjusting && client.getConnection().getUser() != null && client.getConnection().getUser().getBrush() != null) {
|
|
Brush b = client.getConnection().getUser().getBrush();
|
|
b.setOpacity(opacitySlider.getValue());
|
|
client.getConnection().getSendQueue().offer(new CommandEntry(0, new SetBrushCommand(client.getConnection().getUser().getBrush())));
|
|
}
|
|
}
|
|
});
|
|
|
|
/** FLOW */
|
|
brushTab.add(new JLabel(loadImageIcon("flow.png")), "1 3 r c");
|
|
flowSlider = new JSlider(0, 255, 0);
|
|
flowSlider.setToolTipText("Flow - controls the flow of the brush.");
|
|
brushTab.add(flowSlider, "2 3 2 3");
|
|
flowSlider.addChangeListener(new ChangeListener() {
|
|
public void stateChanged(ChangeEvent arg0) {
|
|
if(!flowSlider.getModel().getValueIsAdjusting() && !brushAdjusting && client.getConnection().getUser() != null && client.getConnection().getUser().getBrush() != null) {
|
|
client.getConnection().getUser().getBrush().setFlow(flowSlider.getValue());
|
|
client.getConnection().getSendQueue().offer(new CommandEntry(0, new SetBrushCommand(client.getConnection().getUser().getBrush())));
|
|
}
|
|
}
|
|
});
|
|
|
|
/** SPACING */
|
|
brushTab.add(new JLabel(loadImageIcon("spacing.png")), "1 4 r c");
|
|
spacingSlider = new JSlider(4, 100, 4);
|
|
spacingSlider.setToolTipText("Spacing - controls the density of the brush.");
|
|
brushTab.add(spacingSlider, "2 4 2 4");
|
|
spacingSlider.addChangeListener(new ChangeListener() {
|
|
|
|
public void stateChanged(ChangeEvent arg0) {
|
|
if(!spacingSlider.getModel().getValueIsAdjusting() && !brushAdjusting && client.getConnection().getUser() != null && client.getConnection().getUser().getBrush() != null) {
|
|
client.getConnection().getUser().getBrush().setSpacing(spacingSlider.getValue() / 100f);
|
|
client.getConnection().getSendQueue().offer(new CommandEntry(0, new SetBrushCommand(client.getConnection().getUser().getBrush())));
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
/** JITTER */
|
|
brushTab.add(new JLabel(loadImageIcon("jitter.png")), "1 5 r c");
|
|
jitterSlider = new JSlider(0, 400, 0);
|
|
jitterSlider.setToolTipText("Jitter - adds unpredictability to the position of the brush.");
|
|
brushTab.add(jitterSlider, "2 5 2 5");
|
|
jitterSlider.addChangeListener(new ChangeListener() {
|
|
|
|
public void stateChanged(ChangeEvent arg0) {
|
|
if(!jitterSlider.getModel().getValueIsAdjusting() && !brushAdjusting && client.getConnection().getUser() != null && client.getConnection().getUser().getBrush() != null) {
|
|
client.getConnection().getUser().getBrush().setJitter(jitterSlider.getValue() / 100f);
|
|
client.getConnection().getSendQueue().offer(new CommandEntry(0, new SetBrushCommand(client.getConnection().getUser().getBrush())));
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
/** NOISE */
|
|
brushTab.add(new JLabel(loadImageIcon("noise.png")), "1 6 r c");
|
|
noiseSlider = new JSlider(0, 255, 0);
|
|
noiseSlider.setToolTipText("Noise - adds grains to the brush.");
|
|
brushTab.add(noiseSlider, "2 6 2 6");
|
|
noiseSlider.addChangeListener(new ChangeListener() {
|
|
|
|
public void stateChanged(ChangeEvent arg0) {
|
|
if(!noiseSlider.getModel().getValueIsAdjusting() && !brushAdjusting && client.getConnection().getUser() != null && client.getConnection().getUser().getBrush() != null) {
|
|
client.getConnection().getUser().getBrush().setNoise(noiseSlider.getValue());
|
|
client.getConnection().getSendQueue().offer(new CommandEntry(0, new SetBrushCommand(client.getConnection().getUser().getBrush())));
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
/** WATER */
|
|
brushTab.add(new JLabel(loadImageIcon("water.png")), "1 7 r c");
|
|
waterSlider = new JSlider(0, 255, 0);
|
|
waterSlider.setToolTipText("Watercolor - amount of color that is sampled and mixed with the current color.");
|
|
brushTab.add(waterSlider, "2 7 2 7");
|
|
waterSlider.addChangeListener(new ChangeListener() {
|
|
|
|
public void stateChanged(ChangeEvent arg0) {
|
|
if(!waterSlider.getModel().getValueIsAdjusting() && !brushAdjusting && client.getConnection().getUser() != null && client.getConnection().getUser().getBrush() != null) {
|
|
client.getConnection().getUser().getBrush().setWater(waterSlider.getValue());
|
|
client.getConnection().getSendQueue().offer(new CommandEntry(0, new SetBrushCommand(client.getConnection().getUser().getBrush())));
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
/** WATER AREA */
|
|
brushTab.add(new JLabel(loadImageIcon("waterarea.png")), "1 8 r c");
|
|
waterAreaSlider = new JSlider(1, 100, 75);
|
|
waterAreaSlider.setToolTipText("Watercolor Pickup Area - size of color sampling area compared to the brush size.");
|
|
brushTab.add(waterAreaSlider, "2 8 2 8");
|
|
waterAreaSlider.addChangeListener(new ChangeListener() {
|
|
public void stateChanged(ChangeEvent arg0) {
|
|
if(!waterSlider.getModel().getValueIsAdjusting() && !brushAdjusting && client.getConnection().getUser() != null && client.getConnection().getUser().getBrush() != null) {
|
|
client.getConnection().getUser().getBrush().setWaterArea(waterAreaSlider.getValue() / 100f);
|
|
client.getConnection().getSendQueue().offer(new CommandEntry(0, new SetBrushCommand(client.getConnection().getUser().getBrush())));
|
|
}
|
|
}
|
|
});
|
|
|
|
/** Pressure-to-Radius box */
|
|
radiusBox = new JCheckBox();
|
|
radiusBox.setToolTipText("Pressure to Size - vary brush size with pen pressure");
|
|
radiusBox.setEnabled(false);
|
|
brushTab.add(radiusBox, "3 1 c c");
|
|
|
|
radiusBox.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent arg0) {
|
|
if(!brushAdjusting && client.getConnection().getUser() != null && client.getConnection().getUser().getBrush() != null) {
|
|
client.getConnection().getUser().getBrush().setPressureToRadius(radiusBox.isSelected());
|
|
client.getConnection().getSendQueue().offer(new CommandEntry(0, new SetBrushCommand(client.getConnection().getUser().getBrush())));
|
|
}
|
|
}
|
|
});
|
|
|
|
/** Pressure-to-Opacity box */
|
|
opacityBox = new JCheckBox();
|
|
opacityBox.setToolTipText("Pressure to Opacity - vary brush opacity with pen pressure");
|
|
opacityBox.setEnabled(false);
|
|
brushTab.add(opacityBox, "3 2 c c");
|
|
|
|
opacityBox.addActionListener(new ActionListener() {
|
|
|
|
public void actionPerformed(ActionEvent arg0) {
|
|
if(!brushAdjusting && client.getConnection().getUser() != null && client.getConnection().getUser().getBrush() != null) {
|
|
client.getConnection().getUser().getBrush().setPressureToOpacity(opacityBox.isSelected());
|
|
client.getConnection().getSendQueue().offer(new CommandEntry(0, new SetBrushCommand(client.getConnection().getUser().getBrush())));
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
/** Pressure-to-Flow box */
|
|
flowBox = new JCheckBox();
|
|
flowBox.setToolTipText("Pressure to Flow - vary brush flow with pen pressure");
|
|
opacityBox.setEnabled(false);
|
|
flowBox.setEnabled(false);
|
|
brushTab.add(flowBox, "3 3 c c");
|
|
|
|
flowBox.addActionListener(new ActionListener() {
|
|
|
|
public void actionPerformed(ActionEvent arg0) {
|
|
if(!brushAdjusting && client.getConnection().getUser() != null && client.getConnection().getUser().getBrush() != null) {
|
|
client.getConnection().getUser().getBrush().setPressureToFlow(flowBox.isSelected());
|
|
client.getConnection().getSendQueue().offer(new CommandEntry(0, new SetBrushCommand(client.getConnection().getUser().getBrush())));
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
/** Lock Transparency box */
|
|
lockTransBox = new JCheckBox();
|
|
lockTransBox.setToolTipText("Lock Transparency - alter colors while simultaneously preserving underlying shapes");
|
|
brushTab.add(lockTransBox, "3 0 c c");
|
|
|
|
lockTransBox.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent arg0) {
|
|
if(!brushAdjusting && client.getConnection().getUser() != null && client.getConnection().getUser().getBrush() != null) {
|
|
Brush b = client.getConnection().getUser().getBrush();
|
|
b.setLockTransparency(lockTransBox.isSelected());
|
|
Layer l = client.getConnection().getUser().getPhantomLayer();
|
|
if(lockTransBox.isSelected()) {
|
|
l.setAlphaRule(AlphaComposite.SRC_ATOP);
|
|
} else if(b.getOpacity() >= 0) {
|
|
l.setAlphaRule(AlphaComposite.SRC_OVER);
|
|
} else {
|
|
l.setAlphaRule(AlphaComposite.DST_OUT);
|
|
}
|
|
client.getConnection().getSendQueue().offer(new CommandEntry(0, new SetBrushCommand(client.getConnection().getUser().getBrush())));
|
|
}
|
|
}
|
|
});
|
|
|
|
/* Layers tab */
|
|
final JCollapsiblePanel layersPanel = new JCollapsiblePanel(400, "Layers", true, true);
|
|
layersPanel.setGroup(mainGroup);
|
|
JPanel layersTab = layersPanel.getContentPane();
|
|
|
|
TableLayout layersTabLayout = new TableLayout(new double[][] {{-1, -2}, {-2, -2, -1}});
|
|
layersTabLayout.setHGap(4);
|
|
layersTabLayout.setVGap(4);
|
|
layersTab.setLayout(layersTabLayout);
|
|
rightPanel.add(layersPanel);
|
|
|
|
layerList = new JList();
|
|
|
|
layersTab.add(layerList, "0 0 0 2");
|
|
|
|
JButton addLayerButton = new JButton("Add");
|
|
addLayerButton.setToolTipText("Adds a new layer to the canvas. Prompts you for a name first. Layers are visible to all users.");
|
|
addLayerButton.setMargin(NO_INSETS);
|
|
layersTab.add(addLayerButton, "1 0");
|
|
addLayerButton.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent arg0) {
|
|
String layerName = JOptionPane.showInputDialog("Name of new layer:");
|
|
if(layerName == null) {
|
|
return;
|
|
}
|
|
|
|
layerName = layerName.trim();
|
|
|
|
if(layerName.length() == 0) {
|
|
return;
|
|
}
|
|
|
|
client.getConnection().getSendQueue().offer(new CommandEntry(0, new CreateLayerCommand(0, LayerType.BITMAP, layerName)));
|
|
}
|
|
|
|
});
|
|
|
|
JButton remLayerButton = new JButton("Remove");
|
|
remLayerButton.setToolTipText("Removes the currently selected layer from the canvas. Prompts you for confirmation first.");
|
|
remLayerButton.setMargin(NO_INSETS);
|
|
layersTab.add(remLayerButton, "1 1");
|
|
remLayerButton.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent arg0) {
|
|
if(client.getConnection().getUser() == null || client.getConnection().getUser().getLayer() == null) {
|
|
return;
|
|
}
|
|
|
|
Layer layer = client.getConnection().getUser().getLayer();
|
|
|
|
int confirm = JOptionPane.showConfirmDialog(UserInterface.this, "Really remove layer " + layer.getName() + "?", "Confirm", JOptionPane.YES_NO_OPTION);
|
|
if(confirm != JOptionPane.OK_OPTION) {
|
|
return;
|
|
}
|
|
|
|
if(!layer.isEmpty()) {
|
|
confirm = JOptionPane.showConfirmDialog(UserInterface.this, "Layer " + layer.getName() + " is not empty! Are you absolutely sure?", "Confirm", JOptionPane.YES_NO_OPTION);
|
|
if(confirm != JOptionPane.OK_OPTION) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
client.getConnection().getSendQueue().offer(new CommandEntry(0, new DeleteLayerCommand(client.getCanvas().getLayerMap().getKeyForValue(layer))));
|
|
}
|
|
});
|
|
|
|
/** Color tab */
|
|
colorPanel = new JCollapsiblePanel(500, "Color", false, false);
|
|
colorPanel.setGroup(mainGroup);
|
|
JPanel colorTab = colorPanel.getContentPane();
|
|
colorTab.setLayout(new BorderLayout());
|
|
rightPanel.add(colorPanel);
|
|
|
|
/** Color space tabs */
|
|
JTabbedPane colorSpaceTabs = new JTabbedPane(JTabbedPane.TOP);
|
|
colorTab.add(colorSpaceTabs, BorderLayout.CENTER);
|
|
|
|
/** RGB tab */
|
|
JPanel rgbTab = new JPanel();
|
|
colorSpaceTabs.addTab(null, loadImageIcon("rgb.png"), rgbTab, "RGB - picks colors with red, green, and blue sliders.");
|
|
rgbTab.setLayout(new TableLayout(new double[][] {{TableLayout.PREFERRED, TableLayout.FILL}, {TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.FILL}}));
|
|
|
|
ChangeListener rgbChangeListener = new ChangeListener() {
|
|
public void stateChanged(ChangeEvent arg0) {
|
|
if(!colorAdjusting) {
|
|
int color = Pixels.pack(redSlider.getValue(), greenSlider.getValue(), blueSlider.getValue()) & 0xFFFFFF;
|
|
if(!((JSlider) arg0.getSource()).getModel().getValueIsAdjusting()) {
|
|
client.getCommandQueue().offer(new CommandEntry(0, new SetColorCommand(color)));
|
|
setCMYSliders(color);
|
|
setHSBSliders(color);
|
|
}
|
|
rgbColor.setBackground(new Color(color));
|
|
}
|
|
}
|
|
};
|
|
|
|
rgbTab.add(new JLabel(loadImageIcon("red.png")), "0 0 r c");
|
|
redSlider = new JSlider(0, 255, 0);
|
|
redSlider.setToolTipText("Red");
|
|
rgbTab.add(redSlider, "1 0 1 0");
|
|
redSlider.addChangeListener(rgbChangeListener);
|
|
|
|
rgbTab.add(new JLabel(loadImageIcon("green.png")), "0 1 r c");
|
|
greenSlider = new JSlider(0, 255, 0);
|
|
greenSlider.setToolTipText("Green");
|
|
rgbTab.add(greenSlider, "1 1 1 1");
|
|
greenSlider.addChangeListener(rgbChangeListener);
|
|
|
|
rgbTab.add(new JLabel(loadImageIcon("blue.png")), "0 2 r c");
|
|
blueSlider = new JSlider(0, 255, 0);
|
|
blueSlider.setToolTipText("Blue");
|
|
rgbTab.add(blueSlider, "1 2 1 2");
|
|
blueSlider.addChangeListener(rgbChangeListener);
|
|
|
|
rgbColor = new JPanel();
|
|
rgbColor.setBackground(Color.BLACK);
|
|
rgbTab.add(rgbColor, "0 3 1 3");
|
|
|
|
/** CMY tab */
|
|
JPanel cmyTab = new JPanel();
|
|
cmyTab.setLayout(new TableLayout(new double[][] {{TableLayout.PREFERRED, TableLayout.FILL}, {TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.FILL}}));
|
|
colorSpaceTabs.addTab(null, loadImageIcon("cmy.png"), cmyTab, "CMY - picks colors with cyan, magenta and yellow sliders.");
|
|
|
|
ChangeListener cmyChangeListener = new ChangeListener() {
|
|
public void stateChanged(ChangeEvent arg0) {
|
|
if(!colorAdjusting) {
|
|
int color = Pixels.pack(255 - cyanSlider.getValue(), 255 - magentaSlider.getValue(), 255 - yellowSlider.getValue()) & 0xFFFFFF;
|
|
if(!((JSlider) arg0.getSource()).getModel().getValueIsAdjusting()) {
|
|
client.getCommandQueue().offer(new CommandEntry(0, new SetColorCommand(color)));
|
|
setRGBSliders(color);
|
|
setHSBSliders(color);
|
|
}
|
|
cmyColor.setBackground(new Color(color));
|
|
}
|
|
}
|
|
};
|
|
|
|
cmyTab.add(new JLabel(loadImageIcon("cyan.png")), "0 0 r c");
|
|
cyanSlider = new JSlider(0, 255, 255);
|
|
cyanSlider.setToolTipText("Cyan");
|
|
cmyTab.add(cyanSlider, "1 0 1 0");
|
|
cyanSlider.addChangeListener(cmyChangeListener);
|
|
|
|
cmyTab.add(new JLabel(loadImageIcon("magenta.png")), "0 1 r c");
|
|
magentaSlider = new JSlider(0, 255, 255);
|
|
magentaSlider.setToolTipText("Magenta");
|
|
cmyTab.add(magentaSlider, "1 1 1 1");
|
|
magentaSlider.addChangeListener(cmyChangeListener);
|
|
|
|
cmyTab.add(new JLabel(loadImageIcon("yellow.png")), "0 2 r c");
|
|
yellowSlider = new JSlider(0, 255, 255);
|
|
yellowSlider.setToolTipText("Yellow");
|
|
cmyTab.add(yellowSlider, "1 2 1 2");
|
|
yellowSlider.addChangeListener(cmyChangeListener);
|
|
|
|
cmyColor = new JPanel();
|
|
cmyColor.setBackground(Color.BLACK);
|
|
cmyTab.add(cmyColor, "0 3 1 3");
|
|
|
|
/** HSB tab */
|
|
JPanel hsbTab = new JPanel();
|
|
hsbTab.setLayout(new TableLayout(new double[][] {{TableLayout.PREFERRED, TableLayout.FILL}, {TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.FILL}}));
|
|
colorSpaceTabs.addTab(null, loadImageIcon("hsb.png"), hsbTab, "HSB - picks colors with hue, saturation, and brightness sliders.");
|
|
|
|
/** HSB change listener */
|
|
ChangeListener hsbChangeListener = new ChangeListener() {
|
|
public void stateChanged(ChangeEvent arg0) {
|
|
if(!colorAdjusting) {
|
|
int color = Color.HSBtoRGB(hueSlider.getValue() / 256f, satSlider.getValue() / 256f, brightSlider.getValue() / 256f) & 0xFFFFFF;
|
|
if(!((JSlider) arg0.getSource()).getModel().getValueIsAdjusting()) {
|
|
client.getCommandQueue().offer(new CommandEntry(0, new SetColorCommand(color)));
|
|
setRGBSliders(color);
|
|
setCMYSliders(color);
|
|
}
|
|
hsbColor.setBackground(new Color(color));
|
|
}
|
|
}
|
|
};
|
|
|
|
hsbTab.add(new JLabel(new ImageIcon(getClass().getResource("images/hue.png"))), "0 0 r c");
|
|
hueSlider = new JSlider(0, 256, 0);
|
|
hueSlider.setToolTipText("Hue - basic color");
|
|
hsbTab.add(hueSlider, "1 0 1 0");
|
|
hueSlider.addChangeListener(hsbChangeListener);
|
|
|
|
hsbTab.add(new JLabel(new ImageIcon(getClass().getResource(
|
|
"images/saturation.png"))), "0 1 r c");
|
|
satSlider = new JSlider(0, 256, 0);
|
|
satSlider.setToolTipText("Saturation - color amount");
|
|
hsbTab.add(satSlider, "1 1 1 1");
|
|
satSlider.addChangeListener(hsbChangeListener);
|
|
|
|
hsbTab.add(new JLabel(new ImageIcon(getClass().getResource(
|
|
"images/brightness.png"))), "0 2 r c");
|
|
brightSlider = new JSlider(0, 256, 0);
|
|
brightSlider.setToolTipText("Brightness");
|
|
hsbTab.add(brightSlider, "1 2 1 2");
|
|
brightSlider.addChangeListener(hsbChangeListener);
|
|
|
|
hsbColor = new JPanel();
|
|
hsbColor.setBackground(Color.BLACK);
|
|
hsbTab.add(hsbColor, "0 3 1 3");
|
|
|
|
inputPanel = new JCollapsiblePanel(600, "Input", false, false);
|
|
inputPanel.setGroup(mainGroup);
|
|
rightPanel.add(inputPanel);
|
|
JPanel smoothPanelContent = inputPanel.getContentPane();
|
|
smoothPanelContent.setLayout(new TableLayout(new double[][] {{TableLayout.PREFERRED, TableLayout.FILL}, {TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED}}));
|
|
|
|
JLabel jtabletLabel = new JLabel();
|
|
jtabletLabel.setBackground(Color.BLUE);
|
|
jtabletLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
|
if(editor.hasJTablet()) {
|
|
jtabletLabel.setText("JTablet detected!");
|
|
jtabletLabel.setForeground(new Color(0, 160, 0));
|
|
} else {
|
|
jtabletLabel.setText("JTablet NOT detected!");
|
|
jtabletLabel.setForeground(Color.RED);
|
|
}
|
|
smoothPanelContent.add(jtabletLabel, "0 0 1 0");
|
|
|
|
smoothPanelContent.add(new JLabel(loadImageIcon("trailing.png")), "0 1 r c");
|
|
final JSlider smoothSlider = new JSlider(0, 100, 15);
|
|
smoothSlider.setToolTipText("Cursor Trailing - aids the unsteady hand in drawing sweeping curves.");
|
|
smoothPanelContent.add(smoothSlider, "1 1");
|
|
smoothSlider.addChangeListener(new ChangeListener() {
|
|
public void stateChanged(ChangeEvent arg0) {
|
|
if(!smoothSlider.getModel().getValueIsAdjusting()) {
|
|
Smoother.setSmoothness(smoothSlider.getValue() / 10f);
|
|
}
|
|
}
|
|
});
|
|
|
|
final JCheckBox curveSmoothBox = new JCheckBox("Curve Interpolation");
|
|
curveSmoothBox.setToolTipText("Analyzes cursor motion and smooths segmented lines into curves.");
|
|
curveSmoothBox.setSelected(true);
|
|
smoothPanelContent.add(curveSmoothBox, "0 2 1 2");
|
|
|
|
curveSmoothBox.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent arg0) {
|
|
Smoother.setEnabled(curveSmoothBox.isSelected());
|
|
}
|
|
});
|
|
|
|
/** Create user list panel */
|
|
JCollapsiblePanel userListPanel = new JCollapsiblePanel(700, "Users", true, true);
|
|
userListPanel.setGroup(mainGroup);
|
|
final JPanel userListContent = userListPanel.getContentPane();
|
|
userListContent.setLayout(new BorderLayout());
|
|
rightPanel.add(userListPanel);
|
|
|
|
userList = new JUserList(client.getUserMap());
|
|
userListContent.add(userList, BorderLayout.CENTER);
|
|
|
|
/** Create chat panel */
|
|
JCollapsiblePanel chatPanel = new JCollapsiblePanel(800, "Chat", true, true);
|
|
chatPanel.setGroup(mainGroup);
|
|
JPanel chatContent = chatPanel.getContentPane();
|
|
chatContent.setLayout(new BorderLayout());
|
|
rightPanel.add(chatPanel);
|
|
|
|
/** Create chat scroll pane, add to chat panel */
|
|
chatPane = new JScrollPane();
|
|
ComponentListener chatPaneListener = new ComponentListener() {
|
|
public void componentHidden(ComponentEvent arg0) {
|
|
}
|
|
|
|
public void componentMoved(ComponentEvent arg0) {
|
|
}
|
|
|
|
public void componentResized(ComponentEvent arg0) {
|
|
scroll();
|
|
}
|
|
|
|
public void componentShown(ComponentEvent arg0) {
|
|
}
|
|
};
|
|
chatPane.addComponentListener(chatPaneListener);
|
|
chatContent.add(chatPane, BorderLayout.CENTER);
|
|
|
|
/** Create chat log, add to chat pane */
|
|
chatLog = new JTextArea();
|
|
chatPane.setViewportView(chatLog);
|
|
|
|
chatLog.setCursor(new Cursor(Cursor.TEXT_CURSOR));
|
|
chatLog.setEditable(false);
|
|
chatLog.setLineWrap(true);
|
|
chatLog.setWrapStyleWord(true);
|
|
chatLog.getCaret().setVisible(false);
|
|
chatLog.setText("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
|
|
|
|
/** Create chat field, add to chat panel */
|
|
chatField = new JTextField();
|
|
chatContent.add(chatField, BorderLayout.SOUTH);
|
|
chatField.addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent arg0) {
|
|
String input = chatField.getText();
|
|
|
|
if(client.getConnection().getUser() == null) {
|
|
return;
|
|
}
|
|
|
|
String username = client.getConnection().getUser() == null ? null : client.getConnection().getUser().getName();
|
|
if(input.startsWith("*") && input.endsWith("*")) {
|
|
client.getConnection().getSendQueue().offer(new CommandEntry(0, new SayCommand(" " + input.substring(1, input.length() - 1), true)));
|
|
} else if(input.startsWith(username)) {
|
|
client.getConnection().getSendQueue().offer(new CommandEntry(0, new SayCommand(input.substring(username.length()), true)));
|
|
} else if(input.startsWith("/me")) {
|
|
client.getConnection().getSendQueue().offer(new CommandEntry(0, new SayCommand(input.substring(3), true)));
|
|
} else if(input.startsWith("/kick ")) {
|
|
String kickUsername = input.substring(6);
|
|
boolean kicked = false;
|
|
for(Map.Entry<Integer, User> e: client.getUserMap().entrySet()) {
|
|
if(kickUsername.equalsIgnoreCase(e.getValue().getName())) {
|
|
client.getConnection().getSendQueue().offer(new CommandEntry(0, new KickCommand(e.getKey(), "Kicked by " + username)));
|
|
kicked = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!kicked) {
|
|
println("The user you are trying to kick doesn't exist.");
|
|
}
|
|
} else if("/brush".equals(input)) {
|
|
Brush brush = client.getConnection().getUser().getBrush();
|
|
if(brush != null) {
|
|
println("/*");
|
|
println(" Hardness: " + brush.getHardness());
|
|
println(" Size: " + brush.getRadius());
|
|
println(" Opacity: " + brush.getFlow());
|
|
println(" Spacing: " + brush.getSpacing());
|
|
println(" Jitter: " + brush.getJitter());
|
|
println(" Noise: " + brush.getNoise());
|
|
println(" Water: " + brush.getWater());
|
|
println(" WaterArea: " + brush.getWaterArea());
|
|
println(" PressuteToOpacity: " + brush.isPressureToOpacity());
|
|
println(" PressureToFlow: " + brush.isPressureToFlow());
|
|
println(" PressureToSize: " + brush.isPressureToRadius());
|
|
println("*/");
|
|
}
|
|
} else if(!input.trim().isEmpty()) {
|
|
client.getConnection().getSendQueue().offer(new CommandEntry(0, new SayCommand(input, false)));
|
|
}
|
|
|
|
chatField.setText(null);
|
|
}
|
|
|
|
});
|
|
|
|
/** Adjust size of editor */
|
|
editor.adjust();
|
|
|
|
if(editor.hasJTablet()) {
|
|
opacityBox.setEnabled(true);
|
|
flowBox.setEnabled(true);
|
|
radiusBox.setEnabled(true);
|
|
}
|
|
|
|
validate();
|
|
|
|
scroll();
|
|
}
|
|
|
|
ImageIcon loadImageIcon(String filename) {
|
|
return new ImageIcon(getClass().getResource("images/" + filename));
|
|
}
|
|
|
|
private void updatePanels() {
|
|
boolean hasBrush = freehandButton.isSelected() || lineButton.isSelected() || bezierButton.isSelected() || rectangleButton.isSelected() || ovalButton.isSelected();
|
|
brushPanel.setVisible(hasBrush);
|
|
brushSettingsPanel.setVisible(hasBrush);
|
|
colorPanel.setVisible(hasBrush);
|
|
inputPanel.setVisible(hasBrush);
|
|
filterMenu.setEnabled(selectButton.isSelected());
|
|
}
|
|
|
|
public void updateBrushSliders() {
|
|
if(client.getConnection() == null || client.getConnection().getUser() == null || client.getConnection().getUser().getBrush() == null) {
|
|
return;
|
|
}
|
|
|
|
Brush brush = client.getConnection().getUser().getBrush();
|
|
|
|
brushAdjusting = true;
|
|
|
|
for(int i = 0; i < client.brushes.length; i++) {
|
|
brushButtons[i].setSelected(brush == client.brushes[i]);
|
|
}
|
|
|
|
hardnessSlider.setValue(brush.getHardness());
|
|
sizeSlider.setValue(Math.round(brush.getRadius() * 8f));
|
|
opacitySlider.setValue(brush.getOpacity());
|
|
flowSlider.setValue(brush.getFlow());
|
|
spacingSlider.setValue(Math.round(brush.getSpacing() * 100f));
|
|
jitterSlider.setValue(Math.round(brush.getJitter() * 100f));
|
|
noiseSlider.setValue(brush.getNoise());
|
|
waterSlider.setValue(brush.getWater());
|
|
waterAreaSlider.setValue(Math.round(brush.getWaterArea() * 100f));
|
|
opacityBox.setSelected(brush.isPressureToOpacity());
|
|
flowBox.setSelected(brush.isPressureToFlow());
|
|
radiusBox.setSelected(brush.isPressureToRadius());
|
|
lockTransBox.setSelected(brush.isLockTransparency());
|
|
|
|
brushAdjusting = false;
|
|
}
|
|
|
|
public void setColorSliders(int color) {
|
|
setRGBSliders(color);
|
|
setCMYSliders(color);
|
|
setHSBSliders(color);
|
|
}
|
|
|
|
public void setRGBSliders(int color) {
|
|
rgbColor.setBackground(new Color(color));
|
|
|
|
colorAdjusting = true;
|
|
redSlider.setValue(Pixels.getChannel1(color));
|
|
greenSlider.setValue(Pixels.getChannel2(color));
|
|
blueSlider.setValue(Pixels.getChannel3(color));
|
|
colorAdjusting = false;
|
|
}
|
|
|
|
public void setHSBSliders(int color) {
|
|
hsbColor.setBackground(new Color(color));
|
|
|
|
float[] hsb = new float[3];
|
|
Color.RGBtoHSB(Pixels.getChannel1(color), Pixels.getChannel2(color), Pixels.getChannel3(color), hsb);
|
|
|
|
hsb[0] *= 256f;
|
|
hsb[1] *= 256f;
|
|
hsb[2] *= 256f;
|
|
|
|
colorAdjusting = true;
|
|
hueSlider.setValue(Math.round(hsb[0]));
|
|
satSlider.setValue(Math.round(hsb[1]));
|
|
brightSlider.setValue(Math.round(hsb[2]));
|
|
colorAdjusting = false;
|
|
}
|
|
|
|
public void setCMYSliders(int color) {
|
|
cmyColor.setBackground(new Color(color));
|
|
|
|
colorAdjusting = true;
|
|
cyanSlider.setValue(255 - Pixels.getChannel1(color));
|
|
magentaSlider.setValue(255 - Pixels.getChannel2(color));
|
|
yellowSlider.setValue(255 - Pixels.getChannel3(color));
|
|
colorAdjusting = false;
|
|
}
|
|
|
|
public void println(String str) {
|
|
print("\n" + str);
|
|
}
|
|
|
|
public void print(final String str) {
|
|
Runnable swingWork = new Runnable() {
|
|
public void run() {
|
|
JScrollBar scrollBar = chatPane.getVerticalScrollBar();
|
|
BoundedRangeModel scrollModel = scrollBar.getModel();
|
|
boolean scroll = !scrollModel.getValueIsAdjusting() && scrollModel.getValue() == scrollModel.getMaximum() - scrollModel.getExtent();
|
|
|
|
chatLog.append(str);
|
|
|
|
if(scroll) {
|
|
scroll();
|
|
}
|
|
}
|
|
};
|
|
|
|
SwingUtilities.invokeLater(swingWork);
|
|
}
|
|
|
|
public void scroll() {
|
|
chatPane.validate();
|
|
BoundedRangeModel model = chatPane.getVerticalScrollBar().getModel();
|
|
model.setValue(model.getMaximum() - model.getExtent());
|
|
}
|
|
|
|
public void setCanvas(final Canvas canvas) {
|
|
editor.setCanvas(canvas);
|
|
|
|
canvas.getLayerMap().addChangeListener(new ChangeListener() {
|
|
@SuppressWarnings("unchecked")
|
|
public void stateChanged(ChangeEvent e) {
|
|
TwoWayHashMap<Integer, Layer> map = (TwoWayHashMap<Integer, Layer>)e.getSource();
|
|
final Object[] array = map.values().toArray();
|
|
|
|
ListModel model = new AbstractListModel() {
|
|
public int getSize() {
|
|
return array.length;
|
|
}
|
|
|
|
public Object getElementAt(int index) {
|
|
Layer l = (Layer)array[array.length - 1 - index];
|
|
return l.getName();
|
|
}
|
|
};
|
|
|
|
layerList.setModel(model);
|
|
layerList.invalidate();
|
|
}
|
|
});
|
|
|
|
layerList.addListSelectionListener(new ListSelectionListener() {
|
|
public void valueChanged(ListSelectionEvent e) {
|
|
if(layerAdjusting) {
|
|
return;
|
|
}
|
|
JList source = (JList)e.getSource();
|
|
Object[] array = canvas.getLayerMap().keySet().toArray();
|
|
if(source.getSelectedIndex() != -1) {
|
|
client.getCommandQueue().offer(new CommandEntry(0, new SetLayerCommand((Integer)array[array.length - 1 - source.getSelectedIndex()])));
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
public Editor getEditor() {
|
|
return editor;
|
|
}
|
|
|
|
public JScrollPane getEditorPane() {
|
|
return editorPane;
|
|
}
|
|
|
|
public void setSmoothZoom(boolean smoothZoom) {
|
|
this.smoothZoom = smoothZoom;
|
|
smoothBox.setSelected(smoothZoom);
|
|
editor.setSmoothZoom(smoothZoom);
|
|
editor.repaint();
|
|
}
|
|
|
|
public boolean isSmoothZoom() {
|
|
return smoothZoom;
|
|
}
|
|
|
|
public void setSoundItem(JCheckBoxMenuItem soundItem) {
|
|
this.soundItem = soundItem;
|
|
}
|
|
|
|
public JCheckBoxMenuItem getSoundItem() {
|
|
return soundItem;
|
|
}
|
|
|
|
public void setTagsItem(JCheckBoxMenuItem tagsItem) {
|
|
this.tagsItem = tagsItem;
|
|
}
|
|
|
|
public JCheckBoxMenuItem getTagsItem() {
|
|
return tagsItem;
|
|
}
|
|
|
|
public Set<JCollapsiblePanel> getToolPanels() {
|
|
return mainGroup;
|
|
}
|
|
|
|
public JUserList getUserList() {
|
|
return userList;
|
|
}
|
|
|
|
public void updateLayer() {
|
|
Layer currentLayer = client.getConnection().getUser().getLayer();
|
|
Set<Map.Entry<Integer, Layer>> es = client.getCanvas().getLayerMap().entrySet();
|
|
int index = es.size() - 1;
|
|
for(Map.Entry<Integer, Layer> e : es) {
|
|
if(e.getValue() == currentLayer) {
|
|
break;
|
|
}
|
|
--index;
|
|
}
|
|
layerAdjusting = true;
|
|
layerList.setSelectedIndex(index);
|
|
layerAdjusting = false;
|
|
}
|
|
|
|
public BrushButton[] getBrushButtons() {
|
|
return brushButtons;
|
|
}
|
|
|
|
public class BrushButton extends JToggleButton {
|
|
public BrushButton(final UserInterface parent, final Brush[] brushArray, final Icon[] brushIconArray, final int brushIndex) {
|
|
super();
|
|
setIcon(brushIconArray[brushIndex]);
|
|
setToolTipText(brushArray[brushIndex].getName());
|
|
setMargin(UserInterface.NO_INSETS);
|
|
setMinimumSize(new Dimension(32, 32));
|
|
setPreferredSize(new Dimension(32, 32));
|
|
|
|
addActionListener(new ActionListener() {
|
|
public void actionPerformed(ActionEvent arg0) {
|
|
if(!parent.brushAdjusting) {
|
|
parent.client.getCommandQueue().offer(new CommandEntry(0, new SetBrushCommand(brushArray[brushIndex])));
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
} |