From 6cc59d9409dc238994708a45ffa0a9d4360fd989 Mon Sep 17 00:00:00 2001 From: joelmoniz Date: Sat, 31 May 2014 14:14:56 +0530 Subject: [PATCH] Worked on GUI part of adding option to Pref window --- app/src/processing/app/Preferences.java | 717 ++++++++++++++++++++++++ 1 file changed, 717 insertions(+) diff --git a/app/src/processing/app/Preferences.java b/app/src/processing/app/Preferences.java index 68f94d44b..bfea138a5 100644 --- a/app/src/processing/app/Preferences.java +++ b/app/src/processing/app/Preferences.java @@ -28,6 +28,11 @@ import java.io.*; import java.util.*; import javax.swing.*; +import javax.swing.border.BevelBorder; +import javax.swing.border.EmptyBorder; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.*; import processing.core.*; @@ -107,6 +112,8 @@ public class Preferences { int wide, high; JTextField sketchbookLocationField; + JTextField presentColor; + JTextField presentColorHex; JCheckBox editorAntialiasBox; JCheckBox deletePreviousBox; JCheckBox whinyBox; @@ -368,6 +375,80 @@ public class Preferences { fontSizeField.setSelectedItem(Preferences.getFont("editor.font.size")); top += d.height + GUI_BETWEEN; + // Here I am + + Container colorBox = Box.createHorizontalBox(); + + label = new JLabel("Background color when Presenting: "); + colorBox.add(label); + + final String colorTip = "" + + "Select the background color used when using Present.
" + + "Present is used to present a sketch in full-screen,
" + + "accessible from the Sketch menu."; + label.setToolTipText(colorTip); + + presentColor = new JTextField(" "); + presentColor.setOpaque(true); + presentColor.setEnabled(false); + presentColor.setBorder(BorderFactory.createLineBorder(Color.BLACK)); + presentColor.setBackground(Preferences.getColor("run.present.bgcolor")); + colorBox.add(presentColor); + + colorBox.add(Box.createHorizontalStrut(GUI_SMALL)); + + label = new JLabel("#"); + colorBox.add(label); + + presentColorHex = new JTextField(6); + presentColorHex.setText(Preferences.get("run.present.bgcolor").substring(1)); + presentColorHex.setEditable(false); + presentColorHex.setBackground(Color.WHITE); + + final CustomColorChooser c = new CustomColorChooser(Preferences.getColor("run.present.bgcolor"), + presentColorHex, presentColor); + + presentColorHex.addMouseListener(new MouseListener() { + + @Override + public void mouseReleased(MouseEvent e) { + } + + @Override + public void mousePressed(MouseEvent e) { + } + + @Override + public void mouseExited(MouseEvent e) { + } + + @Override + public void mouseEntered(MouseEvent e) { + } + + @Override + public void mouseClicked(MouseEvent e) { + c.show(); + } + }); + + presentColorHex.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + c.hide(); + } + }); + + colorBox.add(presentColorHex); + + pain.add(colorBox); + d = colorBox.getPreferredSize(); + colorBox.setBounds(left, top, d.width, d.height); + + top += d.height + GUI_BETWEEN; + + // till here // [ ] Use smooth text in editor window @@ -634,7 +715,643 @@ public class Preferences { }); } + private class CustomColorChooser { + int hue, saturation, brightness; // range 360, 100, 100 + int red, green, blue; // range 256, 256, 256 + + ColorRange range; + ColorSlider slider; + + JTextField hueField, saturationField, brightnessField; + JTextField redField, greenField, blueField; + + JTextField hexField; + + JPanel colorPanel; + DocumentListener colorListener; + + JDialog window; + + JTextField externalHex, externalColor; + + + public CustomColorChooser(Color initialColor, final JTextField externalHex, + final JTextField externalColor) { + Frame owner = null; + this.externalHex = externalHex; + this.externalColor = externalColor; + window = new JDialog(owner, "Choose the background color for Present", true); + window.getContentPane().setLayout(new BorderLayout()); + + Box box = Box.createHorizontalBox(); + box.setBorder(new EmptyBorder(12, 12, 12, 12)); + + range = new ColorRange(); + range.init(); + Box rangeBox = new Box(BoxLayout.Y_AXIS); + rangeBox.setAlignmentY(0); + rangeBox.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED)); + rangeBox.add(range); + box.add(rangeBox); + box.add(Box.createHorizontalStrut(10)); + + slider = new ColorSlider(); + slider.init(); + Box sliderBox = new Box(BoxLayout.Y_AXIS); + sliderBox.setAlignmentY(0); + sliderBox.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED)); + sliderBox.add(slider); + box.add(sliderBox); + box.add(Box.createHorizontalStrut(10)); + + box.add(createColorFields(PROMPT_OK, new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + externalHex.setText(getHexColor().substring(1)); + externalColor.setBackground(getColor()); + hide(); + } + }, PROMPT_CANCEL, new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + hide(); + } + })); + + box.add(Box.createHorizontalStrut(10)); + + window.getContentPane().add(box, BorderLayout.CENTER); + + window.pack(); + window.setResizable(false); + + window.setLocationRelativeTo(null); + + window.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + window.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + hide(); + } + }); + Toolkit.registerWindowCloseKeys(window.getRootPane(), new ActionListener() { + public void actionPerformed(ActionEvent actionEvent) { + hide(); + } + }); + + Toolkit.setIcon(window); + + colorListener = new ColorListener(); + hueField.getDocument().addDocumentListener(colorListener); + saturationField.getDocument().addDocumentListener(colorListener); + brightnessField.getDocument().addDocumentListener(colorListener); + redField.getDocument().addDocumentListener(colorListener); + greenField.getDocument().addDocumentListener(colorListener); + blueField.getDocument().addDocumentListener(colorListener); + hexField.getDocument().addDocumentListener(colorListener); + + setColor(initialColor); + } + + + public void show() { + window.setVisible(true); + window.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); + } + + + public void hide() { + window.setVisible(false); + setColor(new Color(Integer.parseInt(externalHex.getText().substring(0, 2), 16), + Integer.parseInt(externalHex.getText().substring(2, 4), 16), + Integer.parseInt(externalHex.getText().substring(4, 6), 16))); + } + + + public Color getColor() { + return new Color(red, green, blue); + } + + + public void setColor(Color color) { + updateRGB(color.getRGB()); + } + + + public String getHexColor() { + return "#" + PApplet.hex(red, 2) + PApplet.hex(green, 2) + PApplet.hex(blue, 2); + } + + + public class ColorListener implements DocumentListener { + + public void changedUpdate(DocumentEvent e) { + } + + public void removeUpdate(DocumentEvent e) { + } + + + boolean updating; + + public void insertUpdate(DocumentEvent e) { + if (updating) return; // don't update forever recursively + updating = true; + + Document doc = e.getDocument(); + if (doc == hueField.getDocument()) { + hue = bounded(hue, hueField, 359); + updateRGB(); + updateHex(); + + } else if (doc == saturationField.getDocument()) { + saturation = bounded(saturation, saturationField, 99); + updateRGB(); + updateHex(); + + } else if (doc == brightnessField.getDocument()) { + brightness = bounded(brightness, brightnessField, 99); + updateRGB(); + updateHex(); + + } else if (doc == redField.getDocument()) { + red = bounded(red, redField, 255); + updateHSB(); + updateHex(); + + } else if (doc == greenField.getDocument()) { + green = bounded(green, greenField, 255); + updateHSB(); + updateHex(); + + } else if (doc == blueField.getDocument()) { + blue = bounded(blue, blueField, 255); + updateHSB(); + updateHex(); + + } else if (doc == hexField.getDocument()) { + String str = hexField.getText(); + if (str.startsWith("#")) { + str = str.substring(1); + } + while (str.length() < 6) { + str += "0"; + } + if (str.length() > 6) { + str = str.substring(0, 6); + } + updateRGB(Integer.parseInt(str, 16)); + updateHSB(); + } + range.redraw(); + slider.redraw(); + colorPanel.repaint(); + updating = false; + } + } + + + /** + * Set the RGB values based on the current HSB values. + */ + protected void updateRGB() { + updateRGB(Color.HSBtoRGB(hue / 359f, + saturation / 99f, + brightness / 99f)); + } + + + /** + * Set the RGB values based on a calculated ARGB int. + * Used by both updateRGB() to set the color from the HSB values, + * and by updateHex(), to unpack the hex colors and assign them. + */ + protected void updateRGB(int rgb) { + red = (rgb >> 16) & 0xff; + green = (rgb >> 8) & 0xff; + blue = rgb & 0xff; + + redField.setText(String.valueOf(red)); + greenField.setText(String.valueOf(green)); + blueField.setText(String.valueOf(blue)); + } + + + /** + * Set the HSB values based on the current RGB values. + */ + protected void updateHSB() { + float hsb[] = new float[3]; + Color.RGBtoHSB(red, green, blue, hsb); + + hue = (int) (hsb[0] * 359.0f); + saturation = (int) (hsb[1] * 99.0f); + brightness = (int) (hsb[2] * 99.0f); + + hueField.setText(String.valueOf(hue)); + saturationField.setText(String.valueOf(saturation)); + brightnessField.setText(String.valueOf(brightness)); + } + + + protected void updateHex() { + hexField.setText(getHexColor()); + } + + + /** + * Get the bounded value for a specific range. If the value is outside + * the max, you can't edit right away, so just act as if it's already + * been bounded and return the bounded value, then fire an event to set + * it to the value that was just returned. + */ + protected int bounded(int current, final JTextField field, final int max) { + String text = field.getText(); + if (text.length() == 0) { + return 0; + } + try { + int value = Integer.parseInt(text); + if (value > max) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + field.setText(String.valueOf(max)); + } + }); + return max; + } + return value; + + } catch (NumberFormatException e) { + return current; // should not be reachable + } + } + + + protected Container createColorFields(String buttonName, ActionListener buttonListener, + String buttonName2, ActionListener buttonListener2) { + Box box = Box.createVerticalBox(); + box.setAlignmentY(0); + + final int GAP = Base.isWindows() ? 5 : 0; + final int BETWEEN = Base.isWindows() ? 8 : 6; //10; + + Box row; + + row = Box.createHorizontalBox(); + if (Base.isMacOS()) { + row.add(Box.createHorizontalStrut(17)); + } else { + row.add(createFixedLabel("")); + } + // Can't just set the bg color of the panel because it also tints the bevel + // (on OS X), which looks odd. So instead we override paintComponent(). + colorPanel = new JPanel() { + public void paintComponent(Graphics g) { + g.setColor(new Color(red, green, blue)); + Dimension size = getSize(); + g.fillRect(0, 0, size.width, size.height); + } + }; + colorPanel.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED)); + Dimension dim = new Dimension(70, 25); + colorPanel.setMinimumSize(dim); + colorPanel.setMaximumSize(dim); + colorPanel.setPreferredSize(dim); + row.add(colorPanel); + row.add(Box.createHorizontalGlue()); + box.add(row); + box.add(Box.createVerticalStrut(BETWEEN)); + + row = Box.createHorizontalBox(); + row.add(createFixedLabel("H")); + row.add(hueField = new NumberField(4, false)); + row.add(new JLabel(" \u00B0")); // degree symbol + row.add(Box.createHorizontalGlue()); + box.add(row); + box.add(Box.createVerticalStrut(GAP)); + + row = Box.createHorizontalBox(); + row.add(createFixedLabel("S")); + row.add(saturationField = new NumberField(4, false)); + row.add(new JLabel(" %")); + row.add(Box.createHorizontalGlue()); + box.add(row); + box.add(Box.createVerticalStrut(GAP)); + + row = Box.createHorizontalBox(); + row.add(createFixedLabel("B")); + row.add(brightnessField = new NumberField(4, false)); + row.add(new JLabel(" %")); + row.add(Box.createHorizontalGlue()); + box.add(row); + box.add(Box.createVerticalStrut(BETWEEN)); + + row = Box.createHorizontalBox(); + row.add(createFixedLabel("R")); + row.add(redField = new NumberField(4, false)); + row.add(Box.createHorizontalGlue()); + box.add(row); + box.add(Box.createVerticalStrut(GAP)); + + row = Box.createHorizontalBox(); + row.add(createFixedLabel("G")); + row.add(greenField = new NumberField(4, false)); + row.add(Box.createHorizontalGlue()); + box.add(row); + box.add(Box.createVerticalStrut(GAP)); + + row = Box.createHorizontalBox(); + row.add(createFixedLabel("B")); + row.add(blueField = new NumberField(4, false)); + row.add(Box.createHorizontalGlue()); + box.add(row); + box.add(Box.createVerticalStrut(BETWEEN)); + + row = Box.createHorizontalBox(); + row.add(createFixedLabel("")); + // Windows needs extra space, OS X and Linux do not + // Mac OS X needs 6 because #CCCCCC is quite wide + final int hexCount = Base.isWindows() ? 7 : 6; + row.add(hexField = new NumberField(hexCount, true)); + row.add(Box.createHorizontalGlue()); + box.add(row); + box.add(Box.createVerticalStrut(GAP)); + + row = Box.createHorizontalBox(); + if (Base.isMacOS()) { + row.add(Box.createHorizontalStrut(11)); + } else { + row.add(createFixedLabel("")); + } + JButton button = new JButton(buttonName); + button.addActionListener(buttonListener); + + row.add(button); + row.add(Box.createHorizontalGlue()); + box.add(row); + + row = Box.createHorizontalBox(); + if (Base.isMacOS()) { + row.add(Box.createHorizontalStrut(11)); + } else { + row.add(createFixedLabel("")); + } + JButton button2 = new JButton(buttonName2); + button2.addActionListener(buttonListener2); + + row.add(button2); + row.add(Box.createHorizontalGlue()); + box.add(row); + + box.add(Box.createVerticalGlue()); + return box; + } + + + int labelH; + + /** + * return a label of a fixed width + */ + protected JLabel createFixedLabel(String title) { + JLabel label = new JLabel(title); + if (labelH == 0) { + labelH = label.getPreferredSize().height; + } + Dimension dim = new Dimension(15, labelH); + label.setPreferredSize(dim); + label.setMinimumSize(dim); + label.setMaximumSize(dim); + return label; + } + + + public class ColorRange extends PApplet { + + static final int WIDE = 256; + static final int HIGH = 256; + + int lastX, lastY; + + + public void setup() { + size(WIDE, HIGH); + noLoop(); + + colorMode(HSB, 360, 256, 256); + noFill(); + rectMode(CENTER); + + loadPixels(); + } + + public void draw() { + + if ((width != WIDE) || (height < HIGH)) { + return; + } + + int index = 0; + for (int j = 0; j < 256; j++) { + for (int i = 0; i < 256; i++) { + pixels[index++] = color(hue, i, 255 - j); + } + } + + updatePixels(); + stroke((brightness > 50) ? 0 : 255); + rect(lastX, lastY, 9, 9); + } + + public void mousePressed() { + updateMouse(); + } + + public void mouseDragged() { + updateMouse(); + } + + public void updateMouse() { + if ((mouseX >= 0) && (mouseX < 256) && + (mouseY >= 0) && (mouseY < 256)) { + int nsaturation = (int) (100 * (mouseX / 255.0f)); + int nbrightness = 100 - ((int) (100 * (mouseY / 255.0f))); + saturationField.setText(String.valueOf(nsaturation)); + brightnessField.setText(String.valueOf(nbrightness)); + + lastX = mouseX; + lastY = mouseY; + } + } + + public Dimension getPreferredSize() { + return new Dimension(WIDE, HIGH); + } + + public Dimension getMinimumSize() { + return new Dimension(WIDE, HIGH); + } + + public Dimension getMaximumSize() { + return new Dimension(WIDE, HIGH); + } + + public void keyPressed() { + if (key == ESC) { + CustomColorChooser.this.hide(); + // don't quit out of processing + // http://dev.processing.org/bugs/show_bug.cgi?id=1006 + key = 0; + } + } + } + + + public class ColorSlider extends PApplet { + + static final int WIDE = 20; + static final int HIGH = 256; + + public void setup() { + size(WIDE, HIGH); //, P3D); + colorMode(HSB, 255, 100, 100); + noLoop(); + loadPixels(); + } + + public void draw() { + if ((width != WIDE) || (height < HIGH)) { + return; + } + + int index = 0; + int sel = 255 - (int) (255 * (hue / 359f)); + for (int j = 0; j < 256; j++) { + int c = color(255 - j, 100, 100); + if (j == sel) c = 0xFF000000; + for (int i = 0; i < WIDE; i++) { + g.pixels[index++] = c; + } + } + updatePixels(); + } + + public void mousePressed() { + updateMouse(); + } + + public void mouseDragged() { + updateMouse(); + } + + public void updateMouse() { + if ((mouseX >= 0) && (mouseX < 256) && + (mouseY >= 0) && (mouseY < 256)) { + int nhue = 359 - (int) (359 * (mouseY / 255.0f)); + hueField.setText(String.valueOf(nhue)); + } + } + + public Dimension getPreferredSize() { + return new Dimension(WIDE, HIGH); + } + + public Dimension getMinimumSize() { + return new Dimension(WIDE, HIGH); + } + + public Dimension getMaximumSize() { + return new Dimension(WIDE, HIGH); + } + + public void keyPressed() { + if (key == ESC) { + CustomColorChooser.this.hide(); + // don't quit out of processing + // http://dev.processing.org/bugs/show_bug.cgi?id=1006 + key = 0; + } + } + } + + + /** + * Extension of JTextField that only allows numbers + */ + class NumberField extends JTextField { + + public boolean allowHex; + + public NumberField(int cols, boolean allowHex) { + super(cols); + this.allowHex = allowHex; + } + + protected Document createDefaultModel() { + return new NumberDocument(this); + } + + public Dimension getPreferredSize() { + if (!allowHex) { + return new Dimension(45, super.getPreferredSize().height); + } + return super.getPreferredSize(); + } + + public Dimension getMinimumSize() { + return getPreferredSize(); + } + + public Dimension getMaximumSize() { + return getPreferredSize(); + } + } + + + /** + * Document model to go with JTextField that only allows numbers. + */ + class NumberDocument extends PlainDocument { + + NumberField parentField; + + public NumberDocument(NumberField parentField) { + this.parentField = parentField; + } + + public void insertString(int offs, String str, AttributeSet a) + throws BadLocationException { + + if (str == null) return; + + char chars[] = str.toCharArray(); + int charCount = 0; + // remove any non-digit chars + for (int i = 0; i < chars.length; i++) { + boolean ok = Character.isDigit(chars[i]); + if (parentField.allowHex) { + if ((chars[i] >= 'A') && (chars[i] <= 'F')) ok = true; + if ((chars[i] >= 'a') && (chars[i] <= 'f')) ok = true; + if ((offs == 0) && (i == 0) && (chars[i] == '#')) ok = true; + } + if (ok) { + if (charCount != i) { // shift if necessary + chars[charCount] = chars[i]; + } + charCount++; + } + } + super.insertString(offs, new String(chars, 0, charCount), a); + } + } + + } + + public void sketchbookCallback(File file) { if (file != null) { sketchbookLocationField.setText(file.getAbsolutePath());