mirror of
https://github.com/processing/processing4.git
synced 2026-05-19 06:32:26 +02:00
Merge remote-tracking branch 'upstream/master' into javamode-refactoring
This commit is contained in:
@@ -26,6 +26,8 @@ package processing.app;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -281,9 +283,16 @@ public class Platform {
|
||||
static public File getContentFile(String name) {
|
||||
if (processingRoot == null) {
|
||||
// Get the path to the .jar file that contains Base.class
|
||||
String path = Base.class.getProtectionDomain().getCodeSource().getLocation().getPath();
|
||||
// Path may have URL encoding, so remove it
|
||||
String decodedPath = PApplet.urlDecode(path);
|
||||
URL pathURL =
|
||||
Base.class.getProtectionDomain().getCodeSource().getLocation();
|
||||
// Decode URL
|
||||
String decodedPath;
|
||||
try {
|
||||
decodedPath = pathURL.toURI().getPath();
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (decodedPath.contains("/app/bin")) { // This means we're in Eclipse
|
||||
final File build = new File(decodedPath, "../../build").getAbsoluteFile();
|
||||
@@ -311,8 +320,7 @@ public class Platform {
|
||||
System.err.println("Could not find lib folder via " +
|
||||
jarFolder.getAbsolutePath() +
|
||||
", switching to user.dir");
|
||||
final String userDir = System.getProperty("user.dir");
|
||||
processingRoot = new File(PApplet.urlDecode(userDir));
|
||||
processingRoot = new File(""); // resolves to "user.dir"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,6 +133,7 @@ public class TextAreaPainter extends JComponent implements TabExpander {
|
||||
|
||||
// moved from setFont() override (never quite comfortable w/ that override)
|
||||
fm = super.getFontMetrics(plainFont);
|
||||
tabSize = fm.charWidth(' ') * Preferences.getInteger("editor.tabs.size");
|
||||
textArea.recalculateVisibleLines();
|
||||
|
||||
// fgcolor = mode.getColor("editor.fgcolor");
|
||||
@@ -465,8 +466,6 @@ public class TextAreaPainter extends JComponent implements TabExpander {
|
||||
// g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
|
||||
// RenderingHints.VALUE_FRACTIONALMETRICS_ON);
|
||||
|
||||
tabSize = fm.charWidth(' ') * ((Integer)textArea.getDocument().getProperty(PlainDocument.tabSizeAttribute)).intValue();
|
||||
|
||||
Rectangle clipRect = gfx.getClipBounds();
|
||||
|
||||
gfx.setColor(getBackground());
|
||||
@@ -670,14 +669,18 @@ public class TextAreaPainter extends JComponent implements TabExpander {
|
||||
// gfx.setFont(defaultFont);
|
||||
// gfx.setColor(defaultColor);
|
||||
|
||||
int x0 = x - textArea.getHorizontalOffset();
|
||||
|
||||
y += fm.getHeight();
|
||||
// doesn't respect fixed width like it should
|
||||
// x = Utilities.drawTabbedText(currentLine, x, y, gfx, this, 0);
|
||||
// int w = fm.charWidth(' ');
|
||||
for (int i = 0; i < currentLine.count; i++) {
|
||||
gfx.drawChars(currentLine.array, currentLine.offset+i, 1, x, y);
|
||||
x = currentLine.array[currentLine.offset + i] == '\t' ? (int)nextTabStop(x, i) :
|
||||
x = currentLine.array[currentLine.offset + i] == '\t' ?
|
||||
x0 + (int)nextTabStop(x - x0, i) :
|
||||
x + fm.charWidth(currentLine.array[currentLine.offset+i]);
|
||||
textArea.offsetToX(line, currentLine.offset + i);
|
||||
}
|
||||
|
||||
// Draw characters via input method.
|
||||
@@ -745,6 +748,8 @@ public class TextAreaPainter extends JComponent implements TabExpander {
|
||||
// Font defaultFont = gfx.getFont();
|
||||
// Color defaultColor = gfx.getColor();
|
||||
|
||||
int x0 = x - textArea.getHorizontalOffset();
|
||||
|
||||
// for (byte id = tokens.id; id != Token.END; tokens = tokens.next) {
|
||||
for (;;) {
|
||||
byte id = tokens.id;
|
||||
@@ -772,8 +777,9 @@ public class TextAreaPainter extends JComponent implements TabExpander {
|
||||
// int w = fm.charWidth(' ');
|
||||
for (int i = 0; i < line.count; i++) {
|
||||
gfx.drawChars(line.array, line.offset+i, 1, x, y);
|
||||
x = line.array[line.offset + i] == '\t' ? (int)nextTabStop(x, i) :
|
||||
x + fm.charWidth(line.array[line.offset+i]);
|
||||
x = line.array[line.offset + i] == '\t' ?
|
||||
x0 + (int)nextTabStop(x - x0, i) :
|
||||
x + fm.charWidth(line.array[line.offset+i]);
|
||||
}
|
||||
//x += fm.charsWidth(line.array, line.offset, line.count);
|
||||
//x += fm.charWidth(' ') * line.count;
|
||||
|
||||
@@ -34,7 +34,7 @@ import processing.app.syntax.TextAreaPainter;
|
||||
* @see <a href="https://processing.org/bugs/bugzilla/1531.html">Bug 1531 : Can't input full-width space when Japanese IME is on.</a>
|
||||
* @see http://docs.oracle.com/javase/8/docs/technotes/guides/imf/index.html
|
||||
* @see http://docs.oracle.com/javase/tutorial/2d/text/index.html
|
||||
*
|
||||
*
|
||||
* @author Takashi Maekawa (takachin@generative.info)
|
||||
* @author Satoshi Okita
|
||||
*/
|
||||
@@ -44,11 +44,9 @@ public class InputMethodSupport implements InputMethodRequests,
|
||||
private static final Attribute[] CUSTOM_IM_ATTRIBUTES = {
|
||||
TextAttribute.INPUT_METHOD_HIGHLIGHT,
|
||||
};
|
||||
|
||||
|
||||
private int committed_count = 0;
|
||||
private TextHitInfo caret;
|
||||
private JEditTextArea textArea;
|
||||
private AttributedCharacterIterator composedText;
|
||||
private AttributedString composedTextString;
|
||||
|
||||
public InputMethodSupport(JEditTextArea textArea) {
|
||||
@@ -70,10 +68,10 @@ public class InputMethodSupport implements InputMethodRequests,
|
||||
// '+1' mean textArea.lineToY(line) + textArea.getPainter().getFontMetrics().getHeight().
|
||||
// TextLayout#draw method need at least one height of font.
|
||||
Rectangle rectangle = new Rectangle(textArea.offsetToX(line, offsetX), textArea.lineToY(line + 1), 0, 0);
|
||||
|
||||
|
||||
Point location = textArea.getPainter().getLocationOnScreen();
|
||||
rectangle.translate(location.x, location.y);
|
||||
|
||||
|
||||
return rectangle;
|
||||
}
|
||||
|
||||
@@ -87,7 +85,7 @@ public class InputMethodSupport implements InputMethodRequests,
|
||||
public int getInsertPositionOffset() {
|
||||
return textArea.getCaretPosition() * -1;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AttributedCharacterIterator getCommittedText(int beginIndex,
|
||||
int endIndex, AttributedCharacterIterator.Attribute[] attributes) {
|
||||
@@ -118,12 +116,11 @@ public class InputMethodSupport implements InputMethodRequests,
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Handles events from InputMethod.
|
||||
*
|
||||
*
|
||||
* @param event event from Input Method.
|
||||
*/
|
||||
@Override
|
||||
public void inputMethodTextChanged(InputMethodEvent event) {
|
||||
composedText = null;
|
||||
public void inputMethodTextChanged(InputMethodEvent event) {
|
||||
if (Base.DEBUG) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("#Called inputMethodTextChanged");
|
||||
@@ -132,16 +129,16 @@ public class InputMethodSupport implements InputMethodRequests,
|
||||
sb.append("\t parmString: " + event.paramString());
|
||||
Messages.log(sb.toString());
|
||||
}
|
||||
|
||||
|
||||
AttributedCharacterIterator text = event.getText(); // text = composedText + commitedText
|
||||
committed_count = event.getCommittedCharacterCount();
|
||||
|
||||
|
||||
|
||||
|
||||
// The caret for Input Method.
|
||||
// if you type a character by a input method, original caret become off.
|
||||
// a JEditTextArea is not implemented by the AttributedStirng and TextLayout.
|
||||
// so JEditTextArea Caret On-off logic.
|
||||
//
|
||||
//
|
||||
// japanese : if the enter key pressed, event.getText is null.
|
||||
// japanese : if first space key pressed, event.getText is null.
|
||||
// chinese(pinin) : if a space key pressed, event.getText is null.
|
||||
@@ -168,7 +165,7 @@ public class InputMethodSupport implements InputMethodRequests,
|
||||
this.insertCharacter(c);
|
||||
c = text.next();
|
||||
}
|
||||
|
||||
|
||||
CompositionTextPainter compositionPainter = textArea.getPainter().getCompositionTextpainter();
|
||||
if (Base.DEBUG) {
|
||||
Messages.log(" textArea.getCaretPosition() + committed_count: " + (textArea.getCaretPosition() + committed_count));
|
||||
@@ -181,15 +178,14 @@ public class InputMethodSupport implements InputMethodRequests,
|
||||
compositionPainter.setComposedTextLayout(null, 0);
|
||||
compositionPainter.setCaret(null);
|
||||
}
|
||||
caret = event.getCaret();
|
||||
event.consume();
|
||||
textArea.repaint();
|
||||
textArea.repaint();
|
||||
}
|
||||
|
||||
|
||||
private TextLayout getTextLayout(AttributedCharacterIterator text, int committedCount) {
|
||||
boolean antialias = Preferences.getBoolean("editor.smooth");
|
||||
TextAreaPainter painter = textArea.getPainter();
|
||||
|
||||
|
||||
// create attributed string with font info.
|
||||
//if (text.getEndIndex() - (text.getBeginIndex() + committedCharacterCount) > 0) {
|
||||
if (text.getEndIndex() - (text.getBeginIndex() + committedCount) > 0) {
|
||||
@@ -197,12 +193,11 @@ public class InputMethodSupport implements InputMethodRequests,
|
||||
Font font = painter.getFontMetrics().getFont();
|
||||
composedTextString.addAttribute(TextAttribute.FONT, font);
|
||||
composedTextString.addAttribute(TextAttribute.BACKGROUND, Color.WHITE);
|
||||
composedText = composedTextString.getIterator();
|
||||
} else {
|
||||
composedTextString = new AttributedString("");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// set hint of antialiasing to render target.
|
||||
Graphics2D g2d = (Graphics2D)painter.getGraphics();
|
||||
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
|
||||
@@ -219,10 +214,9 @@ public class InputMethodSupport implements InputMethodRequests,
|
||||
|
||||
@Override
|
||||
public void caretPositionChanged(InputMethodEvent event) {
|
||||
caret = event.getCaret();
|
||||
event.consume();
|
||||
}
|
||||
|
||||
|
||||
private void insertCharacter(char c) {
|
||||
if (Base.DEBUG) {
|
||||
Messages.log("debug: insertCharacter(char c) textArea.getCaretPosition()=" + textArea.getCaretPosition());
|
||||
|
||||
+2
-2
@@ -59,8 +59,8 @@
|
||||
|
||||
<!-- Switching to 8 because updates for 7 ended April 2015 -->
|
||||
<property name="jdk.version" value="8" />
|
||||
<property name="jdk.update" value="77" />
|
||||
<property name="jdk.build" value="3" />
|
||||
<property name="jdk.update" value="92" />
|
||||
<property name="jdk.build" value="14" />
|
||||
|
||||
<property name="jdk.short" value="${jdk.version}u${jdk.update}" />
|
||||
<property name="jdk.esoteric" value="1.${jdk.version}.0_${jdk.update}" />
|
||||
|
||||
@@ -337,7 +337,10 @@ public class PGraphicsJava2D extends PGraphics {
|
||||
if (fontObject != null) {
|
||||
g2.setFont(fontObject);
|
||||
}
|
||||
|
||||
// https://github.com/processing/processing/issues/4019
|
||||
if (blendMode != 0) {
|
||||
blendMode(blendMode);
|
||||
}
|
||||
handleSmooth();
|
||||
|
||||
/*
|
||||
|
||||
@@ -5333,6 +5333,7 @@ public class PApplet implements PConstants {
|
||||
// if (params != null) {
|
||||
// image.setParams(g, params);
|
||||
// }
|
||||
image.parent = this;
|
||||
return image;
|
||||
}
|
||||
}
|
||||
@@ -7388,10 +7389,10 @@ public class PApplet implements PConstants {
|
||||
try {
|
||||
folder = System.getProperty("user.dir");
|
||||
|
||||
String jarPath =
|
||||
PApplet.class.getProtectionDomain().getCodeSource().getLocation().getPath();
|
||||
// The jarPath from above will be URL encoded (%20 for spaces)
|
||||
jarPath = urlDecode(jarPath);
|
||||
URL jarURL =
|
||||
PApplet.class.getProtectionDomain().getCodeSource().getLocation();
|
||||
// Decode URL
|
||||
String jarPath = jarURL.toURI().getPath();
|
||||
|
||||
// Workaround for bug in Java for OS X from Oracle (7u51)
|
||||
// https://github.com/processing/processing/issues/2181
|
||||
@@ -7542,12 +7543,17 @@ public class PApplet implements PConstants {
|
||||
File why = new File(where);
|
||||
if (why.isAbsolute()) return why;
|
||||
|
||||
String jarPath =
|
||||
getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
|
||||
URL jarURL = getClass().getProtectionDomain().getCodeSource().getLocation();
|
||||
// Decode URL
|
||||
String jarPath;
|
||||
try {
|
||||
jarPath = jarURL.toURI().getPath();
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
if (jarPath.contains("Contents/Java/")) {
|
||||
// The path will be URL encoded (%20 for spaces) coming from above
|
||||
// http://code.google.com/p/processing/issues/detail?id=1073
|
||||
File containingFolder = new File(urlDecode(jarPath)).getParentFile();
|
||||
File containingFolder = new File(jarPath).getParentFile();
|
||||
File dataFolder = new File(containingFolder, "data");
|
||||
return new File(dataFolder, where);
|
||||
}
|
||||
@@ -7632,6 +7638,11 @@ public class PApplet implements PConstants {
|
||||
}
|
||||
|
||||
|
||||
// DO NOT use for file paths, URLDecoder can't handle RFC2396
|
||||
// "The recommended way to manage the encoding and decoding of
|
||||
// URLs is to use URI, and to convert between these two classes
|
||||
// using toURI() and URI.toURL()."
|
||||
// https://docs.oracle.com/javase/8/docs/api/java/net/URL.html
|
||||
static public String urlDecode(String str) {
|
||||
try {
|
||||
return URLDecoder.decode(str, "UTF-8");
|
||||
|
||||
@@ -69,6 +69,22 @@ public class FloatDict {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @nowebref
|
||||
*/
|
||||
public FloatDict(String[] keys, float[] values) {
|
||||
if (keys.length != values.length) {
|
||||
throw new IllegalArgumentException("key and value arrays must be the same length");
|
||||
}
|
||||
this.keys = keys;
|
||||
this.values = values;
|
||||
count = keys.length;
|
||||
for (int i = 0; i < count; i++) {
|
||||
indices.put(keys[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor to allow (more intuitive) inline initialization, e.g.:
|
||||
* <pre>
|
||||
@@ -90,21 +106,6 @@ public class FloatDict {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @nowebref
|
||||
*/
|
||||
public FloatDict(String[] keys, float[] values) {
|
||||
if (keys.length != values.length) {
|
||||
throw new IllegalArgumentException("key and value arrays must be the same length");
|
||||
}
|
||||
this.keys = keys;
|
||||
this.values = values;
|
||||
count = keys.length;
|
||||
for (int i = 0; i < count; i++) {
|
||||
indices.put(keys[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @webref floatdict:method
|
||||
* @brief Returns the number of key/value pairs
|
||||
@@ -139,71 +140,35 @@ public class FloatDict {
|
||||
}
|
||||
|
||||
|
||||
// /**
|
||||
// * Return the internal array being used to store the keys. Allocated but
|
||||
// * unused entries will be removed. This array should not be modified.
|
||||
// */
|
||||
// public String[] keys() {
|
||||
// crop();
|
||||
// return keys;
|
||||
// }
|
||||
|
||||
/**
|
||||
* @webref floatdict:method
|
||||
* @brief Return the internal array being used to store the keys
|
||||
*/
|
||||
public Iterable<String> keys() {
|
||||
return new Iterable<String>() {
|
||||
|
||||
@Override
|
||||
public Iterator<String> iterator() {
|
||||
return new Iterator<String>() {
|
||||
int index = -1;
|
||||
|
||||
public void remove() {
|
||||
removeIndex(index);
|
||||
}
|
||||
|
||||
public String next() {
|
||||
return key(++index);
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return index+1 < size();
|
||||
}
|
||||
};
|
||||
return keyIterator();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// Use this to iterate when you want to be able to remove elements along the way
|
||||
public Iterator<String> keyIterator() {
|
||||
return new Iterator<String>() {
|
||||
int index = -1;
|
||||
|
||||
public void remove() {
|
||||
removeIndex(index);
|
||||
}
|
||||
|
||||
/*
|
||||
static class KeyIterator implements Iterator<String> {
|
||||
FloatHash parent;
|
||||
int index;
|
||||
public String next() {
|
||||
return key(++index);
|
||||
}
|
||||
|
||||
public KeyIterator(FloatHash parent) {
|
||||
this.parent = parent;
|
||||
index = -1;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
parent.removeIndex(index);
|
||||
}
|
||||
|
||||
public String next() {
|
||||
return parent.key(++index);
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return index+1 < parent.size();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
index = -1;
|
||||
}
|
||||
public boolean hasNext() {
|
||||
return index+1 < size();
|
||||
}
|
||||
};
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
@@ -213,6 +178,7 @@ public class FloatDict {
|
||||
* @brief Return a copy of the internal keys array
|
||||
*/
|
||||
public String[] keyArray() {
|
||||
crop();
|
||||
return keyArray(null);
|
||||
}
|
||||
|
||||
@@ -231,11 +197,6 @@ public class FloatDict {
|
||||
}
|
||||
|
||||
|
||||
// public float[] values() {
|
||||
// crop();
|
||||
// return values;
|
||||
// }
|
||||
|
||||
/**
|
||||
* @webref floatdict:method
|
||||
* @brief Return the internal array being used to store the values
|
||||
@@ -245,21 +206,26 @@ public class FloatDict {
|
||||
|
||||
@Override
|
||||
public Iterator<Float> iterator() {
|
||||
return new Iterator<Float>() {
|
||||
int index = -1;
|
||||
return valueIterator();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public Iterator<Float> valueIterator() {
|
||||
return new Iterator<Float>() {
|
||||
int index = -1;
|
||||
|
||||
public void remove() {
|
||||
removeIndex(index);
|
||||
}
|
||||
public void remove() {
|
||||
removeIndex(index);
|
||||
}
|
||||
|
||||
public Float next() {
|
||||
return value(++index);
|
||||
}
|
||||
public Float next() {
|
||||
return value(++index);
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return index+1 < size();
|
||||
}
|
||||
};
|
||||
public boolean hasNext() {
|
||||
return index+1 < size();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -272,6 +238,7 @@ public class FloatDict {
|
||||
* @brief Create a new array and copy each of the values into it
|
||||
*/
|
||||
public float[] valueArray() {
|
||||
crop();
|
||||
return valueArray(null);
|
||||
}
|
||||
|
||||
@@ -337,18 +304,6 @@ public class FloatDict {
|
||||
}
|
||||
|
||||
|
||||
// /** Increase the value of a specific key by 1. */
|
||||
// public void inc(String key) {
|
||||
// inc(key, 1);
|
||||
//// int index = index(key);
|
||||
//// if (index == -1) {
|
||||
//// create(key, 1);
|
||||
//// } else {
|
||||
//// values[index]++;
|
||||
//// }
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* @webref floatdict:method
|
||||
* @brief Add to a value
|
||||
@@ -363,12 +318,6 @@ public class FloatDict {
|
||||
}
|
||||
|
||||
|
||||
// /** Decrease the value of a key by 1. */
|
||||
// public void dec(String key) {
|
||||
// inc(key, -1);
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* @webref floatdict:method
|
||||
* @brief Subtract from a value
|
||||
@@ -417,8 +366,10 @@ public class FloatDict {
|
||||
* @brief Return the smallest value
|
||||
*/
|
||||
public int minIndex() {
|
||||
checkMinMax("minIndex");
|
||||
// Will still return NaN if there is 1 or more entries, and they're all NaN
|
||||
//checkMinMax("minIndex");
|
||||
if (count == 0) return -1;
|
||||
|
||||
// Will still return NaN if there are 1 or more entries, and they're all NaN
|
||||
float m = Float.NaN;
|
||||
int mi = -1;
|
||||
for (int i = 0; i < count; i++) {
|
||||
@@ -430,7 +381,7 @@ public class FloatDict {
|
||||
// calculate the rest
|
||||
for (int j = i+1; j < count; j++) {
|
||||
float d = values[j];
|
||||
if (!Float.isNaN(d) && (d < m)) {
|
||||
if ((d == d) && (d < m)) {
|
||||
m = values[j];
|
||||
mi = j;
|
||||
}
|
||||
@@ -442,6 +393,7 @@ public class FloatDict {
|
||||
}
|
||||
|
||||
|
||||
// return the key for the minimum value
|
||||
public String minKey() {
|
||||
checkMinMax("minKey");
|
||||
int index = minIndex();
|
||||
@@ -452,6 +404,7 @@ public class FloatDict {
|
||||
}
|
||||
|
||||
|
||||
// return the minimum value, or throw an error if there are no values
|
||||
public float minValue() {
|
||||
checkMinMax("minValue");
|
||||
int index = minIndex();
|
||||
@@ -468,7 +421,10 @@ public class FloatDict {
|
||||
*/
|
||||
// The index of the entry that has the max value. Reference above is incorrect.
|
||||
public int maxIndex() {
|
||||
checkMinMax("maxIndex");
|
||||
//checkMinMax("maxIndex");
|
||||
if (count == 0) {
|
||||
return -1;
|
||||
}
|
||||
// Will still return NaN if there is 1 or more entries, and they're all NaN
|
||||
float m = Float.NaN;
|
||||
int mi = -1;
|
||||
@@ -493,9 +449,9 @@ public class FloatDict {
|
||||
}
|
||||
|
||||
|
||||
/** The key for a max value, or null if everything is NaN (no max). */
|
||||
/** The key for a max value; null if empty or everything is NaN (no max). */
|
||||
public String maxKey() {
|
||||
checkMinMax("maxKey");
|
||||
//checkMinMax("maxKey");
|
||||
int index = maxIndex();
|
||||
if (index == -1) {
|
||||
return null;
|
||||
@@ -504,9 +460,9 @@ public class FloatDict {
|
||||
}
|
||||
|
||||
|
||||
/** The max value. (Or NaN if they're all NaN.) */
|
||||
/** The max value. (Or NaN if no entries or they're all NaN.) */
|
||||
public float maxValue() {
|
||||
checkMinMax("maxValue");
|
||||
//checkMinMax("maxValue");
|
||||
int index = maxIndex();
|
||||
if (index == -1) {
|
||||
return Float.NaN;
|
||||
@@ -573,24 +529,11 @@ public class FloatDict {
|
||||
keys[b] = tkey;
|
||||
values[b] = tvalue;
|
||||
|
||||
indices.put(keys[a], Integer.valueOf(a));
|
||||
indices.put(keys[b], Integer.valueOf(b));
|
||||
// indices.put(keys[a], Integer.valueOf(a));
|
||||
// indices.put(keys[b], Integer.valueOf(b));
|
||||
}
|
||||
|
||||
|
||||
// abstract class InternalSort extends Sort {
|
||||
// @Override
|
||||
// public int size() {
|
||||
// return count;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void swap(int a, int b) {
|
||||
// FloatHash.this.swap(a, b);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* Sort the keys alphabetically (ignoring case). Uses the value as a
|
||||
* tie-breaker (only really possible with a key that has a case change).
|
||||
@@ -599,36 +542,16 @@ public class FloatDict {
|
||||
* @brief Sort the keys alphabetically
|
||||
*/
|
||||
public void sortKeys() {
|
||||
sortImpl(true, false);
|
||||
// new InternalSort() {
|
||||
// @Override
|
||||
// public float compare(int a, int b) {
|
||||
// int result = keys[a].compareToIgnoreCase(keys[b]);
|
||||
// if (result != 0) {
|
||||
// return result;
|
||||
// }
|
||||
// return values[b] - values[a];
|
||||
// }
|
||||
// }.run();
|
||||
sortImpl(true, false, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @webref floatdict:method
|
||||
* @brief Sort the keys alphabetially in reverse
|
||||
* @brief Sort the keys alphabetically in reverse
|
||||
*/
|
||||
public void sortKeysReverse() {
|
||||
sortImpl(true, true);
|
||||
// new InternalSort() {
|
||||
// @Override
|
||||
// public float compare(int a, int b) {
|
||||
// int result = keys[b].compareToIgnoreCase(keys[a]);
|
||||
// if (result != 0) {
|
||||
// return result;
|
||||
// }
|
||||
// return values[a] - values[b];
|
||||
// }
|
||||
// }.run();
|
||||
sortImpl(true, true, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -639,13 +562,17 @@ public class FloatDict {
|
||||
* @brief Sort by values in ascending order
|
||||
*/
|
||||
public void sortValues() {
|
||||
sortImpl(false, false);
|
||||
// new InternalSort() {
|
||||
// @Override
|
||||
// public float compare(int a, int b) {
|
||||
//
|
||||
// }
|
||||
// }.run();
|
||||
sortValues(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set true to ensure that the order returned is identical. Slightly
|
||||
* slower because the tie-breaker for identical values compares the keys.
|
||||
* @param stable
|
||||
*/
|
||||
public void sortValues(boolean stable) {
|
||||
sortImpl(false, false, stable);
|
||||
}
|
||||
|
||||
|
||||
@@ -654,50 +581,17 @@ public class FloatDict {
|
||||
* @brief Sort by values in descending order
|
||||
*/
|
||||
public void sortValuesReverse() {
|
||||
sortImpl(false, true);
|
||||
// new InternalSort() {
|
||||
// @Override
|
||||
// public float compare(int a, int b) {
|
||||
// float diff = values[b] - values[a];
|
||||
// if (diff == 0 && keys[a] != null && keys[b] != null) {
|
||||
// diff = keys[a].compareToIgnoreCase(keys[b]);
|
||||
// }
|
||||
// return descending ? diff : -diff;
|
||||
// }
|
||||
// }.run();
|
||||
sortValuesReverse(true);
|
||||
}
|
||||
|
||||
|
||||
// // ascending puts the largest value at the end
|
||||
// // descending puts the largest value at 0
|
||||
// public void sortValues(final boolean descending, final boolean tiebreaker) {
|
||||
// Sort s = new Sort() {
|
||||
// @Override
|
||||
// public int size() {
|
||||
// return count;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public float compare(int a, int b) {
|
||||
// float diff = values[b] - values[a];
|
||||
// if (tiebreaker) {
|
||||
// if (diff == 0) {
|
||||
// diff = keys[a].compareToIgnoreCase(keys[b]);
|
||||
// }
|
||||
// }
|
||||
// return descending ? diff : -diff;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void swap(int a, int b) {
|
||||
// FloatHash.this.swap(a, b);
|
||||
// }
|
||||
// };
|
||||
// s.run();
|
||||
// }
|
||||
public void sortValuesReverse(boolean stable) {
|
||||
sortImpl(false, true, stable);
|
||||
}
|
||||
|
||||
|
||||
protected void sortImpl(final boolean useKeys, final boolean reverse) {
|
||||
protected void sortImpl(final boolean useKeys, final boolean reverse,
|
||||
final boolean stable) {
|
||||
Sort s = new Sort() {
|
||||
@Override
|
||||
public int size() {
|
||||
@@ -731,11 +625,11 @@ public class FloatDict {
|
||||
if (useKeys) {
|
||||
diff = keys[a].compareToIgnoreCase(keys[b]);
|
||||
if (diff == 0) {
|
||||
return values[a] - values[b];
|
||||
diff = values[a] - values[b];
|
||||
}
|
||||
} else { // sort values
|
||||
diff = values[a] - values[b];
|
||||
if (diff == 0) {
|
||||
if (diff == 0 && stable) {
|
||||
diff = keys[a].compareToIgnoreCase(keys[b]);
|
||||
}
|
||||
}
|
||||
@@ -748,18 +642,24 @@ public class FloatDict {
|
||||
}
|
||||
};
|
||||
s.run();
|
||||
|
||||
// Set the indices after sort/swaps (performance fix 160411)
|
||||
indices = new HashMap<String, Integer>();
|
||||
for (int i = 0; i < count; i++) {
|
||||
indices.put(keys[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sum all of the values in this dictionary, then return a new FloatDict of
|
||||
* each key, divided by the total sum. The total for all values will be ~1.0.
|
||||
* @return a Dict with the original keys, mapped to their pct of the total
|
||||
* @return a FloatDict with the original keys, mapped to their pct of the total
|
||||
*/
|
||||
public FloatDict getPercent() {
|
||||
double sum = 0;
|
||||
for (float value : valueArray()) {
|
||||
sum += value;
|
||||
for (int i = 0; i < count; i++) {
|
||||
sum += values[i];
|
||||
}
|
||||
FloatDict outgoing = new FloatDict();
|
||||
for (int i = 0; i < size(); i++) {
|
||||
|
||||
@@ -133,74 +133,20 @@ public class IntDict {
|
||||
}
|
||||
|
||||
|
||||
// private void crop() {
|
||||
// if (count != keys.length) {
|
||||
// keys = PApplet.subset(keys, 0, count);
|
||||
// values = PApplet.subset(values, 0, count);
|
||||
// }
|
||||
// }
|
||||
protected void crop() {
|
||||
if (count != keys.length) {
|
||||
keys = PApplet.subset(keys, 0, count);
|
||||
values = PApplet.subset(values, 0, count);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the internal array being used to store the keys. Allocated but
|
||||
* unused entries will be removed. This array should not be modified.
|
||||
*
|
||||
* @webref intdict:method
|
||||
* @brief Return the internal array being used to store the keys
|
||||
*/
|
||||
// public String[] keys() {
|
||||
// crop();
|
||||
// return keys;
|
||||
// }
|
||||
|
||||
|
||||
// public Iterable<String> keys() {
|
||||
// return new Iterable<String>() {
|
||||
//
|
||||
// @Override
|
||||
// public Iterator<String> iterator() {
|
||||
// return new Iterator<String>() {
|
||||
// int index = -1;
|
||||
//
|
||||
// public void remove() {
|
||||
// removeIndex(index);
|
||||
// }
|
||||
//
|
||||
// public String next() {
|
||||
// return key(++index);
|
||||
// }
|
||||
//
|
||||
// public boolean hasNext() {
|
||||
// return index+1 < size();
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
|
||||
|
||||
// Use this with 'for' loops
|
||||
public Iterable<String> keys() {
|
||||
return new Iterable<String>() {
|
||||
|
||||
@Override
|
||||
public Iterator<String> iterator() {
|
||||
return keyIterator();
|
||||
// return new Iterator<String>() {
|
||||
// int index = -1;
|
||||
//
|
||||
// public void remove() {
|
||||
// removeIndex(index);
|
||||
// }
|
||||
//
|
||||
// public String next() {
|
||||
// return key(++index);
|
||||
// }
|
||||
//
|
||||
// public boolean hasNext() {
|
||||
// return index+1 < size();
|
||||
// }
|
||||
// };
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -233,6 +179,7 @@ public class IntDict {
|
||||
* @brief Return a copy of the internal keys array
|
||||
*/
|
||||
public String[] keyArray() {
|
||||
crop();
|
||||
return keyArray(null);
|
||||
}
|
||||
|
||||
@@ -292,6 +239,7 @@ public class IntDict {
|
||||
* @brief Create a new array and copy each of the values into it
|
||||
*/
|
||||
public int[] valueArray() {
|
||||
crop();
|
||||
return valueArray(null);
|
||||
}
|
||||
|
||||
@@ -428,7 +376,9 @@ public class IntDict {
|
||||
|
||||
// return the index of the minimum value
|
||||
public int minIndex() {
|
||||
checkMinMax("minIndex");
|
||||
//checkMinMax("minIndex");
|
||||
if (count == 0) return -1;
|
||||
|
||||
int index = 0;
|
||||
int value = values[0];
|
||||
for (int i = 1; i < count; i++) {
|
||||
@@ -441,23 +391,30 @@ public class IntDict {
|
||||
}
|
||||
|
||||
|
||||
// return the minimum value
|
||||
// return the key for the minimum value
|
||||
public String minKey() {
|
||||
checkMinMax("minKey");
|
||||
int index = minIndex();
|
||||
if (index == -1) {
|
||||
return null;
|
||||
}
|
||||
return keys[index];
|
||||
}
|
||||
|
||||
|
||||
// return the minimum value, or throw an error if there are no values
|
||||
public int minValue() {
|
||||
checkMinMax("minValue");
|
||||
return values[minIndex()];
|
||||
}
|
||||
|
||||
|
||||
// return the key for the minimum value
|
||||
public String minKey() {
|
||||
checkMinMax("minKey");
|
||||
return keys[minIndex()];
|
||||
}
|
||||
|
||||
|
||||
// return the index of the max value
|
||||
public int maxIndex() {
|
||||
checkMinMax("maxIndex");
|
||||
//checkMinMax("maxIndex");
|
||||
if (count == 0) {
|
||||
return -1;
|
||||
}
|
||||
int index = 0;
|
||||
int value = values[0];
|
||||
for (int i = 1; i < count; i++) {
|
||||
@@ -470,17 +427,21 @@ public class IntDict {
|
||||
}
|
||||
|
||||
|
||||
// return the maximum value
|
||||
public int maxValue() {
|
||||
checkMinMax("maxValue");
|
||||
return values[maxIndex()];
|
||||
/** return the key corresponding to the maximum value or null if no entries */
|
||||
public String maxKey() {
|
||||
//checkMinMax("maxKey");
|
||||
int index = maxIndex();
|
||||
if (index == -1) {
|
||||
return null;
|
||||
}
|
||||
return keys[index];
|
||||
}
|
||||
|
||||
|
||||
// return the key corresponding to the maximum value
|
||||
public String maxKey() {
|
||||
checkMinMax("maxKey");
|
||||
return keys[maxIndex()];
|
||||
// return the maximum value or throw an error if zero length
|
||||
public int maxValue() {
|
||||
checkMinMax("maxIndex");
|
||||
return values[maxIndex()];
|
||||
}
|
||||
|
||||
|
||||
@@ -541,8 +502,8 @@ public class IntDict {
|
||||
keys[b] = tkey;
|
||||
values[b] = tvalue;
|
||||
|
||||
indices.put(keys[a], Integer.valueOf(a));
|
||||
indices.put(keys[b], Integer.valueOf(b));
|
||||
// indices.put(keys[a], Integer.valueOf(a));
|
||||
// indices.put(keys[b], Integer.valueOf(b));
|
||||
}
|
||||
|
||||
|
||||
@@ -554,7 +515,7 @@ public class IntDict {
|
||||
* @brief Sort the keys alphabetically
|
||||
*/
|
||||
public void sortKeys() {
|
||||
sortImpl(true, false);
|
||||
sortImpl(true, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -562,10 +523,10 @@ public class IntDict {
|
||||
* tie-breaker (only really possible with a key that has a case change).
|
||||
*
|
||||
* @webref intdict:method
|
||||
* @brief Sort the keys alphabetially in reverse
|
||||
* @brief Sort the keys alphabetically in reverse
|
||||
*/
|
||||
public void sortKeysReverse() {
|
||||
sortImpl(true, true);
|
||||
sortImpl(true, true, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -576,9 +537,20 @@ public class IntDict {
|
||||
* @brief Sort by values in ascending order
|
||||
*/
|
||||
public void sortValues() {
|
||||
sortImpl(false, false);
|
||||
sortValues(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set true to ensure that the order returned is identical. Slightly
|
||||
* slower because the tie-breaker for identical values compares the keys.
|
||||
* @param stable
|
||||
*/
|
||||
public void sortValues(boolean stable) {
|
||||
sortImpl(false, false, stable);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sort by values in descending order. The largest value will be at [0].
|
||||
*
|
||||
@@ -586,11 +558,17 @@ public class IntDict {
|
||||
* @brief Sort by values in descending order
|
||||
*/
|
||||
public void sortValuesReverse() {
|
||||
sortImpl(false, true);
|
||||
sortValuesReverse(true);
|
||||
}
|
||||
|
||||
|
||||
protected void sortImpl(final boolean useKeys, final boolean reverse) {
|
||||
public void sortValuesReverse(boolean stable) {
|
||||
sortImpl(false, true, stable);
|
||||
}
|
||||
|
||||
|
||||
protected void sortImpl(final boolean useKeys, final boolean reverse,
|
||||
final boolean stable) {
|
||||
Sort s = new Sort() {
|
||||
@Override
|
||||
public int size() {
|
||||
@@ -603,11 +581,11 @@ public class IntDict {
|
||||
if (useKeys) {
|
||||
diff = keys[a].compareToIgnoreCase(keys[b]);
|
||||
if (diff == 0) {
|
||||
return values[a] - values[b];
|
||||
diff = values[a] - values[b];
|
||||
}
|
||||
} else { // sort values
|
||||
diff = values[a] - values[b];
|
||||
if (diff == 0) {
|
||||
if (diff == 0 && stable) {
|
||||
diff = keys[a].compareToIgnoreCase(keys[b]);
|
||||
}
|
||||
}
|
||||
@@ -620,18 +598,24 @@ public class IntDict {
|
||||
}
|
||||
};
|
||||
s.run();
|
||||
|
||||
// Set the indices after sort/swaps (performance fix 160411)
|
||||
indices = new HashMap<String, Integer>();
|
||||
for (int i = 0; i < count; i++) {
|
||||
indices.put(keys[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sum all of the values in this dictionary, then return a new FloatDict of
|
||||
* each key, divided by the total sum. The total for all values will be ~1.0.
|
||||
* @return a Dict with the original keys, mapped to their pct of the total
|
||||
* @return an IntDict with the original keys, mapped to their pct of the total
|
||||
*/
|
||||
public FloatDict getPercent() {
|
||||
double sum = 0;
|
||||
for (int value : valueArray()) {
|
||||
sum += value;
|
||||
for (int i = 0; i < count; i++) {
|
||||
sum += values[i];
|
||||
}
|
||||
FloatDict outgoing = new FloatDict();
|
||||
for (int i = 0; i < size(); i++) {
|
||||
@@ -655,6 +639,13 @@ public class IntDict {
|
||||
}
|
||||
|
||||
|
||||
public void print() {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
System.out.println(keys[i] + " = " + values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write tab-delimited entries out to
|
||||
* @param writer
|
||||
@@ -667,13 +658,6 @@ public class IntDict {
|
||||
}
|
||||
|
||||
|
||||
public void print() {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
System.out.println(keys[i] + " = " + values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
@@ -142,39 +142,32 @@ public class StringDict {
|
||||
}
|
||||
|
||||
|
||||
// /**
|
||||
// * Return the internal array being used to store the keys. Allocated but
|
||||
// * unused entries will be removed. This array should not be modified.
|
||||
// */
|
||||
// public String[] keys() {
|
||||
// crop();
|
||||
// return keys;
|
||||
// }
|
||||
|
||||
/**
|
||||
* @webref stringdict:method
|
||||
* @brief Return the internal array being used to store the keys
|
||||
*/
|
||||
public Iterable<String> keys() {
|
||||
return new Iterable<String>() {
|
||||
|
||||
@Override
|
||||
public Iterator<String> iterator() {
|
||||
return new Iterator<String>() {
|
||||
int index = -1;
|
||||
return keyIterator();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
removeIndex(index);
|
||||
}
|
||||
|
||||
public String next() {
|
||||
return key(++index);
|
||||
}
|
||||
// Use this to iterate when you want to be able to remove elements along the way
|
||||
public Iterator<String> keyIterator() {
|
||||
return new Iterator<String>() {
|
||||
int index = -1;
|
||||
|
||||
public boolean hasNext() {
|
||||
return index+1 < size();
|
||||
}
|
||||
};
|
||||
public void remove() {
|
||||
removeIndex(index);
|
||||
}
|
||||
|
||||
public String next() {
|
||||
return key(++index);
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return index+1 < size();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -187,6 +180,7 @@ public class StringDict {
|
||||
* @brief Return a copy of the internal keys array
|
||||
*/
|
||||
public String[] keyArray() {
|
||||
crop();
|
||||
return keyArray(null);
|
||||
}
|
||||
|
||||
@@ -213,21 +207,26 @@ public class StringDict {
|
||||
|
||||
@Override
|
||||
public Iterator<String> iterator() {
|
||||
return new Iterator<String>() {
|
||||
int index = -1;
|
||||
return valueIterator();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
removeIndex(index);
|
||||
}
|
||||
|
||||
public String next() {
|
||||
return value(++index);
|
||||
}
|
||||
public Iterator<String> valueIterator() {
|
||||
return new Iterator<String>() {
|
||||
int index = -1;
|
||||
|
||||
public boolean hasNext() {
|
||||
return index+1 < size();
|
||||
}
|
||||
};
|
||||
public void remove() {
|
||||
removeIndex(index);
|
||||
}
|
||||
|
||||
public String next() {
|
||||
return value(++index);
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return index+1 < size();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -240,6 +239,7 @@ public class StringDict {
|
||||
* @brief Create a new array and copy each of the values into it
|
||||
*/
|
||||
public String[] valueArray() {
|
||||
crop();
|
||||
return valueArray(null);
|
||||
}
|
||||
|
||||
@@ -357,8 +357,8 @@ public class StringDict {
|
||||
keys[b] = tkey;
|
||||
values[b] = tvalue;
|
||||
|
||||
indices.put(keys[a], Integer.valueOf(a));
|
||||
indices.put(keys[b], Integer.valueOf(b));
|
||||
// indices.put(keys[a], Integer.valueOf(a));
|
||||
// indices.put(keys[b], Integer.valueOf(b));
|
||||
}
|
||||
|
||||
|
||||
@@ -375,7 +375,7 @@ public class StringDict {
|
||||
|
||||
/**
|
||||
* @webref stringdict:method
|
||||
* @brief Sort the keys alphabetially in reverse
|
||||
* @brief Sort the keys alphabetically in reverse
|
||||
*/
|
||||
public void sortKeysReverse() {
|
||||
sortImpl(true, true);
|
||||
@@ -432,6 +432,12 @@ public class StringDict {
|
||||
}
|
||||
};
|
||||
s.run();
|
||||
|
||||
// Set the indices after sort/swaps (performance fix 160411)
|
||||
indices = new HashMap<String, Integer>();
|
||||
for (int i = 0; i < count; i++) {
|
||||
indices.put(keys[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -448,6 +454,13 @@ public class StringDict {
|
||||
}
|
||||
|
||||
|
||||
public void print() {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
System.out.println(keys[i] + " = " + values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write tab-delimited entries out to
|
||||
* @param writer
|
||||
@@ -460,13 +473,6 @@ public class StringDict {
|
||||
}
|
||||
|
||||
|
||||
public void print() {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
System.out.println(keys[i] + " = " + values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
@@ -25,7 +25,10 @@ package processing.javafx;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Rectangle;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javafx.animation.Animation;
|
||||
@@ -38,9 +41,14 @@ import javafx.beans.value.ObservableValue;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.event.EventType;
|
||||
import javafx.scene.Cursor;
|
||||
import javafx.scene.ImageCursor;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.SceneAntialiasing;
|
||||
import javafx.scene.canvas.Canvas;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.PixelFormat;
|
||||
import javafx.scene.image.WritableImage;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
@@ -329,6 +337,11 @@ public class PSurfaceFX implements PSurface {
|
||||
// the stage, assign it only when it is all set up
|
||||
surface.stage = stage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() throws Exception {
|
||||
surface.sketch.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -352,6 +365,8 @@ public class PSurfaceFX implements PSurface {
|
||||
Thread.sleep(5);
|
||||
} catch (InterruptedException e) { }
|
||||
}
|
||||
|
||||
setProcessingIcon(stage);
|
||||
}
|
||||
|
||||
|
||||
@@ -390,7 +405,42 @@ public class PSurfaceFX implements PSurface {
|
||||
|
||||
|
||||
public void setIcon(PImage icon) {
|
||||
// TODO implement this in JavaFX
|
||||
int w = icon.pixelWidth;
|
||||
int h = icon.pixelHeight;
|
||||
WritableImage im = new WritableImage(w, h);
|
||||
im.getPixelWriter().setPixels(0, 0, w, h,
|
||||
PixelFormat.getIntArgbInstance(),
|
||||
icon.pixels,
|
||||
0, w);
|
||||
|
||||
Stage stage = (Stage) canvas.getScene().getWindow();
|
||||
stage.getIcons().clear();
|
||||
stage.getIcons().add(im);
|
||||
}
|
||||
|
||||
|
||||
List<Image> iconImages;
|
||||
|
||||
protected void setProcessingIcon(Stage stage) {
|
||||
// Adapted from PSurfaceAWT
|
||||
// Note: FX chooses wrong icon size, should be fixed in Java 9, see:
|
||||
// https://bugs.openjdk.java.net/browse/JDK-8091186
|
||||
// Removing smaller sizes helps a bit, but big ones are downsized
|
||||
try {
|
||||
if (iconImages == null) {
|
||||
iconImages = new ArrayList<>();
|
||||
final int[] sizes = { 48, 64, 128, 256, 512 };
|
||||
|
||||
for (int sz : sizes) {
|
||||
URL url = PApplet.class.getResource("/icon/icon-" + sz + ".png");
|
||||
Image image = new Image(url.toString());
|
||||
iconImages.add(image);
|
||||
}
|
||||
}
|
||||
List<Image> icons = stage.getIcons();
|
||||
icons.clear();
|
||||
icons.addAll(iconImages);
|
||||
} catch (Exception e) { } // harmless; keep this to ourselves
|
||||
}
|
||||
|
||||
|
||||
@@ -590,28 +640,45 @@ public class PSurfaceFX implements PSurface {
|
||||
// canvas.requestFocus();
|
||||
// }
|
||||
|
||||
Cursor lastCursor = Cursor.DEFAULT;
|
||||
|
||||
public void setCursor(int kind) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
Cursor c;
|
||||
switch (kind) {
|
||||
case PConstants.ARROW: c = Cursor.DEFAULT; break;
|
||||
case PConstants.CROSS: c = Cursor.CROSSHAIR; break;
|
||||
case PConstants.HAND: c = Cursor.HAND; break;
|
||||
case PConstants.MOVE: c = Cursor.MOVE; break;
|
||||
case PConstants.TEXT: c = Cursor.TEXT; break;
|
||||
case PConstants.WAIT: c = Cursor.WAIT; break;
|
||||
default: c = Cursor.DEFAULT; break;
|
||||
}
|
||||
lastCursor = c;
|
||||
canvas.getScene().setCursor(c);
|
||||
}
|
||||
|
||||
|
||||
public void setCursor(PImage image, int hotspotX, int hotspotY) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
int w = image.pixelWidth;
|
||||
int h = image.pixelHeight;
|
||||
WritableImage im = new WritableImage(w, h);
|
||||
im.getPixelWriter().setPixels(0, 0, w, h,
|
||||
PixelFormat.getIntArgbInstance(),
|
||||
image.pixels,
|
||||
0, w);
|
||||
ImageCursor c = new ImageCursor(im, hotspotX, hotspotY);
|
||||
lastCursor = c;
|
||||
canvas.getScene().setCursor(c);
|
||||
}
|
||||
|
||||
|
||||
public void showCursor() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
canvas.getScene().setCursor(lastCursor);
|
||||
}
|
||||
|
||||
|
||||
public void hideCursor() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
canvas.getScene().setCursor(Cursor.NONE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -149,15 +149,9 @@ class FontTexture implements PConstants {
|
||||
} else if (resize) {
|
||||
// Replacing old smaller texture with larger one.
|
||||
// But first we must copy the contents of the older
|
||||
// texture into the new one. Setting blend mode to
|
||||
// REPLACE to preserve color of transparent pixels.
|
||||
// texture into the new one.
|
||||
Texture tex0 = textures[lastTex];
|
||||
|
||||
tex.pg.pushStyle();
|
||||
tex.pg.blendMode(REPLACE);
|
||||
tex.put(tex0);
|
||||
tex.pg.popStyle();
|
||||
|
||||
textures[lastTex] = tex;
|
||||
|
||||
pg.setCache(images[lastTex], tex);
|
||||
|
||||
@@ -942,6 +942,8 @@ public abstract class PGL {
|
||||
|
||||
|
||||
protected void restoreFirstFrame() {
|
||||
if (firstFrame == null) return;
|
||||
|
||||
IntBuffer tex = allocateIntBuffer(1);
|
||||
genTextures(1, tex);
|
||||
|
||||
|
||||
@@ -12481,8 +12481,8 @@ public class PGraphicsOpenGL extends PGraphics {
|
||||
} else {
|
||||
texCache.setLastIndex(lastIndex, lastCache);
|
||||
}
|
||||
prevTexImage = newTexImage;
|
||||
}
|
||||
prevTexImage = newTexImage;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
@@ -1224,10 +1224,10 @@ public class Texture implements PConstants {
|
||||
// FBO copy:
|
||||
pg.pushFramebuffer();
|
||||
pg.setFramebuffer(tempFbo);
|
||||
// Clear the color buffer to make sure that the alpha channel is set to
|
||||
// full transparency
|
||||
pgl.clearColor(0, 0, 0, 0);
|
||||
pgl.clear(PGL.COLOR_BUFFER_BIT);
|
||||
// Replaces anything that this texture might contain in the area being
|
||||
// replaced by the new one.
|
||||
pg.pushStyle();
|
||||
pg.blendMode(REPLACE);
|
||||
if (scale) {
|
||||
// Rendering tex into "this", and scaling the source rectangle
|
||||
// to cover the entire destination region.
|
||||
@@ -1243,8 +1243,10 @@ public class Texture implements PConstants {
|
||||
0, 0, tempFbo.width, tempFbo.height, 1,
|
||||
x, y, x + w, y + h, x, y, x + w, y + h);
|
||||
}
|
||||
pgl.flush(); // Needed to make sure that the change in this texture is
|
||||
// available immediately.
|
||||
pg.popStyle();
|
||||
pg.popFramebuffer();
|
||||
|
||||
updateTexels(x, y, w, h);
|
||||
}
|
||||
|
||||
@@ -1264,6 +1266,10 @@ public class Texture implements PConstants {
|
||||
// FBO copy:
|
||||
pg.pushFramebuffer();
|
||||
pg.setFramebuffer(tempFbo);
|
||||
// Replaces anything that this texture might contain in the area being
|
||||
// replaced by the new one.
|
||||
pg.pushStyle();
|
||||
pg.blendMode(REPLACE);
|
||||
if (scale) {
|
||||
// Rendering tex into "this", and scaling the source rectangle
|
||||
// to cover the entire destination region.
|
||||
@@ -1279,6 +1285,9 @@ public class Texture implements PConstants {
|
||||
0, 0, tempFbo.width, tempFbo.height,
|
||||
x, y, w, h, x, y, w, h);
|
||||
}
|
||||
pgl.flush(); // Needed to make sure that the change in this texture is
|
||||
// available immediately.
|
||||
pg.popStyle();
|
||||
pg.popFramebuffer();
|
||||
updateTexels(x, y, w, h);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,40 @@
|
||||
0249 (3.0.3)
|
||||
X Float/IntDict changes
|
||||
X minIndex() and maxIndex() return -1 when count is zero (rather than ex)
|
||||
X bug fix to reverse sorts
|
||||
X 2x performance increase for sorting
|
||||
X added optional "stable" parameter for sorting by values
|
||||
X set to false for higher performance
|
||||
X call crop() in keyArray() and valueArray() functions
|
||||
X they're duplicates, their length is an implementation detail
|
||||
X normalize features and error handling between all of them
|
||||
|
||||
_ add push() and pop() methods to mirror js?
|
||||
|
||||
jakub
|
||||
X several JavaFX fixes
|
||||
X https://github.com/processing/processing/pull/4411
|
||||
X cursor() and noCursor() not working on FX2D
|
||||
X https://github.com/processing/processing/issues/4405
|
||||
X Make sure PImage.parent is set in loadImage()
|
||||
X https://github.com/processing/processing/pull/4412
|
||||
|
||||
andres
|
||||
X Change convention for directional lights in OpenGL-Binding for GLSL
|
||||
X https://github.com/processing/processing/issues/4275
|
||||
X internal texture copy does not update immediately
|
||||
X https://github.com/processing/processing/issues/4404
|
||||
X Font corruption issue in OpenGL
|
||||
X https://github.com/processing/processing/issues/4392
|
||||
X setStroke() does not work with imported OBJ Pshapes
|
||||
X https://github.com/processing/processing/issues/4377
|
||||
|
||||
contribs
|
||||
X blendMode() resetting with getGraphics()
|
||||
X https://github.com/processing/processing/issues/4019
|
||||
X https://github.com/processing/processing/pull/4341
|
||||
X https://github.com/processing/processing/issues/4376
|
||||
|
||||
|
||||
_ textAlign(CENTER) and pixelDensity(2) aligning incorrectly with Java2D
|
||||
_ https://github.com/processing/processing/issues/4020
|
||||
|
||||
@@ -301,20 +301,17 @@ public class JavaTextAreaPainter extends TextAreaPainter
|
||||
return;
|
||||
}
|
||||
|
||||
// Take care of offsets
|
||||
int aw = fm.stringWidth(trimRight(badCode)) + textArea.getHorizontalOffset();
|
||||
// to the left of line + text
|
||||
// width
|
||||
int rw = fm.stringWidth(badCode.trim()); // real width
|
||||
int x1 = fm.stringWidth(goodCode) + (aw - rw);
|
||||
int y1 = y + fm.getHeight() - 2, x2 = x1 + rw;
|
||||
int trimmedLength = badCode.trim().length();
|
||||
int rightTrimmedLength = trimRight(badCode).length();
|
||||
int leftTrimLength = rightTrimmedLength - trimmedLength;
|
||||
|
||||
int x1 = textArea.offsetToX(line, goodCode.length() + leftTrimLength);
|
||||
int x2 = textArea.offsetToX(line, goodCode.length() + rightTrimmedLength);
|
||||
int y1 = y + fm.getHeight() - 2;
|
||||
|
||||
if (line != problem.getLineNumber()) {
|
||||
x1 = 0; // on the following lines, wiggle extends to the left border
|
||||
x1 = Editor.LEFT_GUTTER; // on the following lines, wiggle extends to the left border
|
||||
}
|
||||
// Adding offsets for the gutter
|
||||
x1 += Editor.LEFT_GUTTER;
|
||||
x2 += Editor.LEFT_GUTTER;
|
||||
|
||||
gfx.setColor(errorUnderlineColor);
|
||||
if (problem.isWarning()) {
|
||||
|
||||
@@ -10,6 +10,9 @@ X https://github.com/processing/processing/pull/4325
|
||||
X Fix non-ARM Linux deb build process
|
||||
X https://github.com/processing/processing/issues/4308
|
||||
X https://github.com/processing/processing/pull/4309
|
||||
_ processing-java output as UTF-8 makes Windows unhappy
|
||||
_ https://github.com/processing/processing/issues/1633
|
||||
_ includes possible fix for Windows
|
||||
|
||||
jakub
|
||||
X Update app to Java 8
|
||||
@@ -22,14 +25,20 @@ X update JDT to 4.5.2
|
||||
X https://github.com/processing/processing/pull/4387
|
||||
X JavaMode cleanup
|
||||
X https://github.com/processing/processing/pull/4390
|
||||
X tabs aren't working properly (several bugs?)
|
||||
X https://github.com/processing/processing/issues/3975
|
||||
X https://github.com/processing/processing/pull/4410
|
||||
X file paths not decoding properly
|
||||
X https://github.com/processing/processing/issues/4417
|
||||
X https://github.com/processing/processing/pull/4426
|
||||
_ double check that this is working on OS X
|
||||
|
||||
|
||||
_ arrow keys aren't working in the examples window
|
||||
|
||||
_ createPreprocessor() added to JavaEditor
|
||||
https://github.com/processing/processing/commit/2ecdc36ac7c680eb36e271d17ad80b657b3ae6a0
|
||||
|
||||
_ tabs aren't working properly (several bugs?)
|
||||
_ https://github.com/processing/processing/issues/3975
|
||||
|
||||
_ possible infinite loop on modified externally
|
||||
_ https://github.com/processing/processing/issues/3965
|
||||
|
||||
@@ -871,8 +880,6 @@ DIST / Windows
|
||||
|
||||
_ PDE and sketches are 2x smaller on high-res Windows 8 machines
|
||||
_ https://github.com/processing/processing/issues/2411
|
||||
_ processing-java output as UTF-8 makes Windows unhappy
|
||||
_ https://github.com/processing/processing/issues/1633
|
||||
_ does launching p5 from inside the .zip folder cause it to quit immediately?
|
||||
_ how can we provide an error message here?
|
||||
_ how to handle double-clicked files on windows?
|
||||
|
||||
Reference in New Issue
Block a user