propane 3.1.0.pre-java → 3.2.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.mvn/wrapper/maven-wrapper.properties +1 -0
  3. data/CHANGELOG.md +1 -5
  4. data/README.md +23 -12
  5. data/Rakefile +23 -12
  6. data/lib/propane/helpers/version_error.rb +6 -0
  7. data/lib/propane/runner.rb +12 -0
  8. data/lib/propane/version.rb +1 -1
  9. data/library/slider/slider.rb +1 -1
  10. data/mvnw +234 -0
  11. data/mvnw.cmd +145 -0
  12. data/pom.xml +28 -27
  13. data/propane.gemspec +2 -2
  14. data/src/main/java/japplemenubar/JAppleMenuBar.java +41 -47
  15. data/src/main/java/monkstone/ColorUtil.java +1 -1
  16. data/src/main/java/monkstone/MathToolModule.java +12 -11
  17. data/src/main/java/monkstone/PropaneLibrary.java +9 -10
  18. data/src/main/java/monkstone/core/LibraryProxy.java +124 -113
  19. data/src/main/java/monkstone/fastmath/Deglut.java +86 -89
  20. data/src/main/java/monkstone/filechooser/Chooser.java +7 -13
  21. data/src/main/java/monkstone/noise/SimplexNoise.java +0 -1
  22. data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +4 -4
  23. data/src/main/java/monkstone/slider/CustomVerticalSlider.java +1 -1
  24. data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +9 -9
  25. data/src/main/java/monkstone/slider/SimpleSlider.java +0 -9
  26. data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +11 -13
  27. data/src/main/java/monkstone/slider/Slider.java +1 -1
  28. data/src/main/java/monkstone/slider/SliderBar.java +1 -1
  29. data/src/main/java/monkstone/slider/SliderGroup.java +1 -1
  30. data/src/main/java/monkstone/slider/WheelHandler.java +8 -9
  31. data/src/main/java/monkstone/vecmath/AppRender.java +2 -2
  32. data/src/main/java/monkstone/vecmath/ShapeRender.java +2 -2
  33. data/src/main/java/monkstone/vecmath/package-info.java +2 -2
  34. data/src/main/java/monkstone/vecmath/vec2/Vec2.java +2 -2
  35. data/src/main/java/monkstone/vecmath/vec3/Vec3.java +1 -1
  36. data/src/main/java/monkstone/videoevent/VideoInterface.java +11 -5
  37. data/src/main/java/monkstone/videoevent/package-info.java +2 -2
  38. data/src/main/java/processing/awt/PGraphicsJava2D.java +1742 -2243
  39. data/src/main/java/processing/awt/PShapeJava2D.java +268 -270
  40. data/src/main/java/processing/awt/PSurfaceAWT.java +821 -920
  41. data/src/main/java/processing/core/DesktopHandler.java +94 -0
  42. data/src/main/java/processing/core/PApplet.java +14170 -14082
  43. data/src/main/java/processing/core/PConstants.java +447 -473
  44. data/src/main/java/processing/core/PFont.java +867 -873
  45. data/src/main/java/processing/core/PGraphics.java +7193 -7428
  46. data/src/main/java/processing/core/PImage.java +3051 -3117
  47. data/src/main/java/processing/core/PMatrix.java +159 -172
  48. data/src/main/java/processing/core/PMatrix2D.java +403 -444
  49. data/src/main/java/processing/core/PMatrix3D.java +735 -749
  50. data/src/main/java/processing/core/PShape.java +2651 -2793
  51. data/src/main/java/processing/core/PShapeOBJ.java +415 -422
  52. data/src/main/java/processing/core/PShapeSVG.java +1466 -1475
  53. data/src/main/java/processing/core/PStyle.java +37 -40
  54. data/src/main/java/processing/core/PSurface.java +98 -103
  55. data/src/main/java/processing/core/PSurfaceNone.java +208 -236
  56. data/src/main/java/processing/core/PVector.java +961 -990
  57. data/src/main/java/processing/data/DoubleDict.java +709 -753
  58. data/src/main/java/processing/data/DoubleList.java +695 -748
  59. data/src/main/java/processing/data/FloatDict.java +702 -746
  60. data/src/main/java/processing/data/FloatList.java +697 -751
  61. data/src/main/java/processing/data/IntDict.java +673 -718
  62. data/src/main/java/processing/data/IntList.java +633 -699
  63. data/src/main/java/processing/data/JSONArray.java +873 -931
  64. data/src/main/java/processing/data/JSONObject.java +1165 -1262
  65. data/src/main/java/processing/data/JSONTokener.java +341 -351
  66. data/src/main/java/processing/data/LongDict.java +662 -707
  67. data/src/main/java/processing/data/LongList.java +634 -700
  68. data/src/main/java/processing/data/Sort.java +41 -37
  69. data/src/main/java/processing/data/StringDict.java +486 -522
  70. data/src/main/java/processing/data/StringList.java +580 -624
  71. data/src/main/java/processing/data/Table.java +3508 -3686
  72. data/src/main/java/processing/data/TableRow.java +183 -182
  73. data/src/main/java/processing/data/XML.java +883 -957
  74. data/src/main/java/processing/event/Event.java +66 -87
  75. data/src/main/java/processing/event/KeyEvent.java +41 -48
  76. data/src/main/java/processing/event/MouseEvent.java +93 -103
  77. data/src/main/java/processing/event/TouchEvent.java +6 -10
  78. data/src/main/java/processing/javafx/PGraphicsFX2D.java +5 -69
  79. data/src/main/java/processing/javafx/PSurfaceFX.java +2 -7
  80. data/src/main/java/processing/opengl/FontTexture.java +270 -290
  81. data/src/main/java/processing/opengl/FrameBuffer.java +363 -375
  82. data/src/main/java/processing/opengl/LinePath.java +500 -543
  83. data/src/main/java/processing/opengl/LineStroker.java +582 -593
  84. data/src/main/java/processing/opengl/PGL.java +2881 -2904
  85. data/src/main/java/processing/opengl/PGraphics2D.java +315 -408
  86. data/src/main/java/processing/opengl/PGraphics3D.java +72 -107
  87. data/src/main/java/processing/opengl/PGraphicsOpenGL.java +12043 -12230
  88. data/src/main/java/processing/opengl/PJOGL.java +1681 -1745
  89. data/src/main/java/processing/opengl/PShader.java +1257 -1260
  90. data/src/main/java/processing/opengl/PShapeOpenGL.java +4599 -4662
  91. data/src/main/java/processing/opengl/PSurfaceJOGL.java +1030 -1047
  92. data/src/main/java/processing/opengl/Texture.java +1397 -1462
  93. data/src/main/java/processing/opengl/VertexBuffer.java +55 -57
  94. data/src/main/resources/icon/icon-1024.png +0 -0
  95. data/src/main/resources/icon/icon-128.png +0 -0
  96. data/src/main/resources/icon/icon-16.png +0 -0
  97. data/src/main/resources/icon/icon-256.png +0 -0
  98. data/src/main/resources/icon/icon-32.png +0 -0
  99. data/src/main/resources/icon/icon-48.png +0 -0
  100. data/src/main/resources/icon/icon-512.png +0 -0
  101. data/src/main/resources/icon/icon-64.png +0 -0
  102. data/vendors/Rakefile +1 -1
  103. metadata +12 -8
  104. data/src/main/java/processing/core/ThinkDifferent.java +0 -70
@@ -6,7 +6,6 @@ import java.util.Iterator;
6
6
 
7
7
  import processing.core.PApplet;
8
8
 
9
-
10
9
  /**
11
10
  * A simple class to use a String as a lookup for an int value.
12
11
  *
@@ -16,785 +15,741 @@ import processing.core.PApplet;
16
15
  */
17
16
  public class LongDict {
18
17
 
19
- /** Number of elements in the table */
20
- protected int count;
21
-
22
- protected String[] keys;
23
- protected long[] values;
24
-
25
- /** Internal implementation for faster lookups */
26
- private HashMap<String, Integer> indices = new HashMap<>();
27
-
28
-
29
- public LongDict() {
30
- count = 0;
31
- keys = new String[10];
32
- values = new long[10];
33
- }
34
-
35
-
36
- /**
37
- * Create a new lookup with a specific size. This is more efficient than not
38
- * specifying a size. Use it when you know the rough size of the thing you're creating.
39
- *
40
- * @nowebref
41
- */
42
- public LongDict(int length) {
43
- count = 0;
44
- keys = new String[length];
45
- values = new long[length];
46
- }
47
-
48
-
49
- /**
50
- * Read a set of entries from a Reader that has each key/value pair on
51
- * a single line, separated by a tab.
52
- *
53
- * @nowebref
54
- */
55
- public LongDict(BufferedReader reader) {
56
- String[] lines = PApplet.loadStrings(reader);
57
- keys = new String[lines.length];
58
- values = new long[lines.length];
59
-
60
- for (int i = 0; i < lines.length; i++) {
61
- String[] pieces = PApplet.split(lines[i], '\t');
62
- if (pieces.length == 2) {
63
- keys[count] = pieces[0];
64
- values[count] = PApplet.parseInt(pieces[1]);
65
- indices.put(pieces[0], count);
66
- count++;
67
- }
68
- }
69
- }
70
-
71
- /**
72
- * @nowebref
73
- */
74
- public LongDict(String[] keys, long[] values) {
75
- if (keys.length != values.length) {
76
- throw new IllegalArgumentException("key and value arrays must be the same length");
18
+ /**
19
+ * Number of elements in the table
20
+ */
21
+ protected int count;
22
+
23
+ protected String[] keys;
24
+ protected long[] values;
25
+
26
+ /**
27
+ * Internal implementation for faster lookups
28
+ */
29
+ private HashMap<String, Integer> indices = new HashMap<>();
30
+
31
+ public LongDict() {
32
+ count = 0;
33
+ keys = new String[10];
34
+ values = new long[10];
35
+ }
36
+
37
+ /**
38
+ * Create a new lookup with a specific size. This is more efficient than not
39
+ * specifying a size. Use it when you know the rough size of the thing
40
+ * you're creating.
41
+ *
42
+ * @nowebref
43
+ */
44
+ public LongDict(int length) {
45
+ count = 0;
46
+ keys = new String[length];
47
+ values = new long[length];
48
+ }
49
+
50
+ /**
51
+ * Read a set of entries from a Reader that has each key/value pair on a
52
+ * single line, separated by a tab.
53
+ *
54
+ * @nowebref
55
+ */
56
+ public LongDict(BufferedReader reader) {
57
+ String[] lines = PApplet.loadStrings(reader);
58
+ keys = new String[lines.length];
59
+ values = new long[lines.length];
60
+
61
+ for (int i = 0; i < lines.length; i++) {
62
+ String[] pieces = PApplet.split(lines[i], '\t');
63
+ if (pieces.length == 2) {
64
+ keys[count] = pieces[0];
65
+ values[count] = PApplet.parseInt(pieces[1]);
66
+ indices.put(pieces[0], count);
67
+ count++;
68
+ }
69
+ }
77
70
  }
78
- this.keys = keys;
79
- this.values = values;
80
- count = keys.length;
81
- for (int i = 0; i < count; i++) {
82
- indices.put(keys[i], i);
83
- }
84
- }
85
-
86
-
87
- /**
88
- * Constructor to allow (more intuitive) inline initialization, e.g.:
89
- * <pre>
90
- * new FloatDict(new Object[][] {
91
- * { "key1", 1 },
92
- * { "key2", 2 }
93
- * });
94
- * </pre>
95
- */
96
- public LongDict(Object[][] pairs) {
97
- count = pairs.length;
98
- this.keys = new String[count];
99
- this.values = new long[count];
100
- for (int i = 0; i < count; i++) {
101
- keys[i] = (String) pairs[i][0];
102
- values[i] = (Integer) pairs[i][1];
103
- indices.put(keys[i], i);
104
- }
105
- }
106
-
107
-
108
- /**
109
- * Returns the number of key/value pairs
110
- *
111
- * @webref intdict:method
112
- * @brief Returns the number of key/value pairs
113
- */
114
- public int size() {
115
- return count;
116
- }
117
-
118
71
 
119
- /**
120
- * Resize the internal data, this can only be used to shrink the list.
121
- * Helpful for situations like sorting and then grabbing the top 50 entries.
122
- */
123
- public void resize(int length) {
124
- if (length > count) {
125
- throw new IllegalArgumentException("resize() can only be used to shrink the dictionary");
126
- }
127
- if (length < 1) {
128
- throw new IllegalArgumentException("resize(" + length + ") is too small, use 1 or higher");
72
+ /**
73
+ * @nowebref
74
+ */
75
+ public LongDict(String[] keys, long[] values) {
76
+ if (keys.length != values.length) {
77
+ throw new IllegalArgumentException("key and value arrays must be the same length");
78
+ }
79
+ this.keys = keys;
80
+ this.values = values;
81
+ count = keys.length;
82
+ for (int i = 0; i < count; i++) {
83
+ indices.put(keys[i], i);
84
+ }
129
85
  }
130
86
 
131
- String[] newKeys = new String[length];
132
- long[] newValues = new long[length];
133
- PApplet.arrayCopy(keys, newKeys, length);
134
- PApplet.arrayCopy(values, newValues, length);
135
- keys = newKeys;
136
- values = newValues;
137
- count = length;
138
- resetIndices();
139
- }
140
-
141
-
142
- /**
143
- * Remove all entries.
144
- *
145
- * @webref intdict:method
146
- * @brief Remove all entries
147
- */
148
- public void clear() {
149
- count = 0;
150
- indices = new HashMap<>();
151
- }
152
-
153
-
154
- private void resetIndices() {
155
- indices = new HashMap<>(count);
156
- for (int i = 0; i < count; i++) {
157
- indices.put(keys[i], i);
87
+ /**
88
+ * Constructor to allow (more intuitive) inline initialization, e.g.:
89
+ * <pre>
90
+ * new FloatDict(new Object[][] {
91
+ * { "key1", 1 },
92
+ * { "key2", 2 }
93
+ * });
94
+ * </pre>
95
+ */
96
+ public LongDict(Object[][] pairs) {
97
+ count = pairs.length;
98
+ this.keys = new String[count];
99
+ this.values = new long[count];
100
+ for (int i = 0; i < count; i++) {
101
+ keys[i] = (String) pairs[i][0];
102
+ values[i] = (Integer) pairs[i][1];
103
+ indices.put(keys[i], i);
104
+ }
158
105
  }
159
- }
160
-
161
-
162
- // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
163
106
 
164
-
165
- public class Entry {
166
- public String key;
167
- public long value;
168
-
169
- Entry(String key, long value) {
170
- this.key = key;
171
- this.value = value;
107
+ /**
108
+ * Returns the number of key/value pairs
109
+ *
110
+ * @webref intdict:method
111
+ * @brief Returns the number of key/value pairs
112
+ */
113
+ public int size() {
114
+ return count;
172
115
  }
173
- }
174
-
175
-
176
- public Iterable<Entry> entries() {
177
- return new Iterable<Entry>() {
178
-
179
- public Iterator<Entry> iterator() {
180
- return entryIterator();
181
- }
182
- };
183
- }
184
-
185
-
186
- public Iterator<Entry> entryIterator() {
187
- return new Iterator<Entry>() {
188
- int index = -1;
189
-
190
- public void remove() {
191
- removeIndex(index);
192
- index--;
193
- }
194
116
 
195
- public Entry next() {
196
- ++index;
197
- Entry e = new Entry(keys[index], values[index]);
198
- return e;
199
- }
200
-
201
- public boolean hasNext() {
202
- return index+1 < size();
203
- }
204
- };
205
- }
117
+ /**
118
+ * Resize the internal data, this can only be used to shrink the list.
119
+ * Helpful for situations like sorting and then grabbing the top 50 entries.
120
+ */
121
+ public void resize(int length) {
122
+ if (length > count) {
123
+ throw new IllegalArgumentException("resize() can only be used to shrink the dictionary");
124
+ }
125
+ if (length < 1) {
126
+ throw new IllegalArgumentException("resize(" + length + ") is too small, use 1 or higher");
127
+ }
206
128
 
129
+ String[] newKeys = new String[length];
130
+ long[] newValues = new long[length];
131
+ PApplet.arrayCopy(keys, newKeys, length);
132
+ PApplet.arrayCopy(values, newValues, length);
133
+ keys = newKeys;
134
+ values = newValues;
135
+ count = length;
136
+ resetIndices();
137
+ }
138
+
139
+ /**
140
+ * Remove all entries.
141
+ *
142
+ * @webref intdict:method
143
+ * @brief Remove all entries
144
+ */
145
+ public void clear() {
146
+ count = 0;
147
+ indices = new HashMap<>();
148
+ }
149
+
150
+ private void resetIndices() {
151
+ indices = new HashMap<>(count);
152
+ for (int i = 0; i < count; i++) {
153
+ indices.put(keys[i], i);
154
+ }
155
+ }
207
156
 
208
- // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
157
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
158
+ public class Entry {
209
159
 
160
+ public String key;
161
+ public long value;
210
162
 
211
- public String key(int index) {
212
- return keys[index];
213
- }
163
+ Entry(String key, long value) {
164
+ this.key = key;
165
+ this.value = value;
166
+ }
167
+ }
214
168
 
169
+ public Iterable<Entry> entries() {
170
+ return new Iterable<Entry>() {
215
171
 
216
- protected void crop() {
217
- if (count != keys.length) {
218
- keys = PApplet.subset(keys, 0, count);
219
- values = PApplet.subset(values, 0, count);
172
+ public Iterator<Entry> iterator() {
173
+ return entryIterator();
174
+ }
175
+ };
220
176
  }
221
- }
222
177
 
178
+ public Iterator<Entry> entryIterator() {
179
+ return new Iterator<Entry>() {
180
+ int index = -1;
223
181
 
224
- public Iterable<String> keys() {
225
- return new Iterable<String>() {
182
+ public void remove() {
183
+ removeIndex(index);
184
+ index--;
185
+ }
226
186
 
227
- @Override
228
- public Iterator<String> iterator() {
229
- return keyIterator();
230
- }
231
- };
232
- }
187
+ public Entry next() {
188
+ ++index;
189
+ Entry e = new Entry(keys[index], values[index]);
190
+ return e;
191
+ }
233
192
 
193
+ public boolean hasNext() {
194
+ return index + 1 < size();
195
+ }
196
+ };
197
+ }
234
198
 
235
- // Use this to iterate when you want to be able to remove elements along the way
236
- public Iterator<String> keyIterator() {
237
- return new Iterator<String>() {
238
- int index = -1;
199
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
200
+ public String key(int index) {
201
+ return keys[index];
202
+ }
239
203
 
240
- public void remove() {
241
- removeIndex(index);
242
- index--;
243
- }
204
+ protected void crop() {
205
+ if (count != keys.length) {
206
+ keys = PApplet.subset(keys, 0, count);
207
+ values = PApplet.subset(values, 0, count);
208
+ }
209
+ }
244
210
 
245
- public String next() {
246
- return key(++index);
247
- }
211
+ public Iterable<String> keys() {
212
+ return new Iterable<String>() {
248
213
 
249
- public boolean hasNext() {
250
- return index+1 < size();
251
- }
252
- };
253
- }
214
+ @Override
215
+ public Iterator<String> iterator() {
216
+ return keyIterator();
217
+ }
218
+ };
219
+ }
254
220
 
221
+ // Use this to iterate when you want to be able to remove elements along the way
222
+ public Iterator<String> keyIterator() {
223
+ return new Iterator<String>() {
224
+ int index = -1;
255
225
 
256
- /**
257
- * Return a copy of the internal keys array. This array can be modified.
258
- *
259
- * @webref intdict:method
260
- * @brief Return a copy of the internal keys array
261
- */
262
- public String[] keyArray() {
263
- crop();
264
- return keyArray(null);
265
- }
226
+ public void remove() {
227
+ removeIndex(index);
228
+ index--;
229
+ }
266
230
 
231
+ public String next() {
232
+ return key(++index);
233
+ }
267
234
 
268
- public String[] keyArray(String[] outgoing) {
269
- if (outgoing == null || outgoing.length != count) {
270
- outgoing = new String[count];
235
+ public boolean hasNext() {
236
+ return index + 1 < size();
237
+ }
238
+ };
271
239
  }
272
- System.arraycopy(keys, 0, outgoing, 0, count);
273
- return outgoing;
274
- }
275
-
276
-
277
- public long value(int index) {
278
- return values[index];
279
- }
280
-
281
-
282
- /**
283
- * @webref intdict:method
284
- * @brief Return the internal array being used to store the values
285
- */
286
- public Iterable<Long> values() {
287
- return new Iterable<Long>() {
288
-
289
- @Override
290
- public Iterator<Long> iterator() {
291
- return valueIterator();
292
- }
293
- };
294
- }
295
-
296
-
297
- public Iterator<Long> valueIterator() {
298
- return new Iterator<Long>() {
299
- int index = -1;
300
-
301
- public void remove() {
302
- removeIndex(index);
303
- index--;
304
- }
305
240
 
306
- public Long next() {
307
- return value(++index);
308
- }
309
-
310
- public boolean hasNext() {
311
- return index+1 < size();
312
- }
313
- };
314
- }
315
-
316
-
317
- /**
318
- * Create a new array and copy each of the values into it.
319
- *
320
- * @webref intdict:method
321
- * @brief Create a new array and copy each of the values into it
322
- */
323
- public int[] valueArray() {
324
- crop();
325
- return valueArray(null);
326
- }
327
-
328
-
329
- /**
330
- * Fill an already-allocated array with the values (more efficient than
331
- * creating a new array each time). If 'array' is null, or not the same
332
- * size as the number of values, a new array will be allocated and returned.
333
- *
334
- * @param array values to copy into the array
335
- */
336
- public int[] valueArray(int[] array) {
337
- if (array == null || array.length != size()) {
338
- array = new int[count];
339
- }
340
- System.arraycopy(values, 0, array, 0, count);
341
- return array;
342
- }
343
-
344
-
345
- /**
346
- * Return a value for the specified key.
347
- *
348
- * @webref intdict:method
349
- * @brief Return a value for the specified key
350
- */
351
- public long get(String key) {
352
- int index = index(key);
353
- if (index == -1) {
354
- throw new IllegalArgumentException("No key named '" + key + "'");
355
- }
356
- return values[index];
357
- }
358
-
359
-
360
- public long get(String key, long alternate) {
361
- int index = index(key);
362
- if (index == -1) return alternate;
363
- return values[index];
364
- }
365
-
366
-
367
- /**
368
- * Create a new key/value pair or change the value of one.
369
- *
370
- * @webref intdict:method
371
- * @brief Create a new key/value pair or change the value of one
372
- */
373
- public void set(String key, long amount) {
374
- int index = index(key);
375
- if (index == -1) {
376
- create(key, amount);
377
- } else {
378
- values[index] = amount;
379
- }
380
- }
381
-
382
-
383
- public void setIndex(int index, String key, long value) {
384
- if (index < 0 || index >= count) {
385
- throw new ArrayIndexOutOfBoundsException(index);
386
- }
387
- keys[index] = key;
388
- values[index] = value;
389
- }
390
-
391
-
392
- /**
393
- * @webref intdict:method
394
- * @brief Check if a key is a part of the data structure
395
- */
396
- public boolean hasKey(String key) {
397
- return index(key) != -1;
398
- }
399
-
400
-
401
- /**
402
- * Increase the value associated with a specific key by 1.
403
- *
404
- * @webref intdict:method
405
- * @brief Increase the value of a specific key value by 1
406
- */
407
- public void increment(String key) {
408
- add(key, 1);
409
- }
410
-
411
-
412
- /**
413
- * Merge another dictionary into this one. Calling this increment()
414
- * since it doesn't make sense in practice for the other dictionary types,
415
- * even though it's technically an add().
416
- */
417
- public void increment(LongDict dict) {
418
- for (int i = 0; i < dict.count; i++) {
419
- add(dict.key(i), dict.value(i));
420
- }
421
- }
422
-
423
-
424
- /**
425
- * @webref intdict:method
426
- * @brief Add to a value
427
- */
428
- public void add(String key, long amount) {
429
- int index = index(key);
430
- if (index == -1) {
431
- create(key, amount);
432
- } else {
433
- values[index] += amount;
434
- }
435
- }
436
-
437
-
438
- /**
439
- * @webref intdict:method
440
- * @brief Subtract from a value
441
- */
442
- public void sub(String key, long amount) {
443
- add(key, -amount);
444
- }
445
-
446
-
447
- /**
448
- * @webref intdict:method
449
- * @brief Multiply a value
450
- */
451
- public void mult(String key, long amount) {
452
- int index = index(key);
453
- if (index != -1) {
454
- values[index] *= amount;
241
+ /**
242
+ * Return a copy of the internal keys array. This array can be modified.
243
+ *
244
+ * @webref intdict:method
245
+ * @brief Return a copy of the internal keys array
246
+ */
247
+ public String[] keyArray() {
248
+ crop();
249
+ return keyArray(null);
455
250
  }
456
- }
457
251
 
458
-
459
- /**
460
- * @webref intdict:method
461
- * @brief Divide a value
462
- */
463
- public void div(String key, long amount) {
464
- int index = index(key);
465
- if (index != -1) {
466
- values[index] /= amount;
252
+ public String[] keyArray(String[] outgoing) {
253
+ if (outgoing == null || outgoing.length != count) {
254
+ outgoing = new String[count];
255
+ }
256
+ System.arraycopy(keys, 0, outgoing, 0, count);
257
+ return outgoing;
258
+ }
259
+
260
+ public long value(int index) {
261
+ return values[index];
262
+ }
263
+
264
+ /**
265
+ * @webref intdict:method
266
+ * @brief Return the internal array being used to store the values
267
+ */
268
+ public Iterable<Long> values() {
269
+ return new Iterable<Long>() {
270
+
271
+ @Override
272
+ public Iterator<Long> iterator() {
273
+ return valueIterator();
274
+ }
275
+ };
276
+ }
277
+
278
+ public Iterator<Long> valueIterator() {
279
+ return new Iterator<Long>() {
280
+ int index = -1;
281
+
282
+ public void remove() {
283
+ removeIndex(index);
284
+ index--;
285
+ }
286
+
287
+ public Long next() {
288
+ return value(++index);
289
+ }
290
+
291
+ public boolean hasNext() {
292
+ return index + 1 < size();
293
+ }
294
+ };
295
+ }
296
+
297
+ /**
298
+ * Create a new array and copy each of the values into it.
299
+ *
300
+ * @webref intdict:method
301
+ * @brief Create a new array and copy each of the values into it
302
+ */
303
+ public int[] valueArray() {
304
+ crop();
305
+ return valueArray(null);
306
+ }
307
+
308
+ /**
309
+ * Fill an already-allocated array with the values (more efficient than
310
+ * creating a new array each time). If 'array' is null, or not the same size
311
+ * as the number of values, a new array will be allocated and returned.
312
+ *
313
+ * @param array values to copy into the array
314
+ */
315
+ public int[] valueArray(int[] array) {
316
+ if (array == null || array.length != size()) {
317
+ array = new int[count];
318
+ }
319
+ System.arraycopy(values, 0, array, 0, count);
320
+ return array;
321
+ }
322
+
323
+ /**
324
+ * Return a value for the specified key.
325
+ *
326
+ * @webref intdict:method
327
+ * @brief Return a value for the specified key
328
+ */
329
+ public long get(String key) {
330
+ int index = index(key);
331
+ if (index == -1) {
332
+ throw new IllegalArgumentException("No key named '" + key + "'");
333
+ }
334
+ return values[index];
467
335
  }
468
- }
469
336
 
470
-
471
- private void checkMinMax(String functionName) {
472
- if (count == 0) {
473
- String msg =
474
- String.format("Cannot use %s() on an empty %s.",
475
- functionName, getClass().getSimpleName());
476
- throw new RuntimeException(msg);
337
+ public long get(String key, long alternate) {
338
+ int index = index(key);
339
+ if (index == -1) {
340
+ return alternate;
341
+ }
342
+ return values[index];
343
+ }
344
+
345
+ /**
346
+ * Create a new key/value pair or change the value of one.
347
+ *
348
+ * @webref intdict:method
349
+ * @brief Create a new key/value pair or change the value of one
350
+ */
351
+ public void set(String key, long amount) {
352
+ int index = index(key);
353
+ if (index == -1) {
354
+ create(key, amount);
355
+ } else {
356
+ values[index] = amount;
357
+ }
477
358
  }
478
- }
479
-
480
-
481
- // return the index of the minimum value
482
- public int minIndex() {
483
- //checkMinMax("minIndex");
484
- if (count == 0) return -1;
485
359
 
486
- int index = 0;
487
- long value = values[0];
488
- for (int i = 1; i < count; i++) {
489
- if (values[i] < value) {
490
- index = i;
491
- value = values[i];
492
- }
360
+ public void setIndex(int index, String key, long value) {
361
+ if (index < 0 || index >= count) {
362
+ throw new ArrayIndexOutOfBoundsException(index);
363
+ }
364
+ keys[index] = key;
365
+ values[index] = value;
366
+ }
367
+
368
+ /**
369
+ * @webref intdict:method
370
+ * @brief Check if a key is a part of the data structure
371
+ */
372
+ public boolean hasKey(String key) {
373
+ return index(key) != -1;
374
+ }
375
+
376
+ /**
377
+ * Increase the value associated with a specific key by 1.
378
+ *
379
+ * @webref intdict:method
380
+ * @brief Increase the value of a specific key value by 1
381
+ */
382
+ public void increment(String key) {
383
+ add(key, 1);
384
+ }
385
+
386
+ /**
387
+ * Merge another dictionary into this one. Calling this increment() since it
388
+ * doesn't make sense in practice for the other dictionary types, even
389
+ * though it's technically an add().
390
+ */
391
+ public void increment(LongDict dict) {
392
+ for (int i = 0; i < dict.count; i++) {
393
+ add(dict.key(i), dict.value(i));
394
+ }
493
395
  }
494
- return index;
495
- }
496
-
497
396
 
498
- // return the key for the minimum value
499
- public String minKey() {
500
- checkMinMax("minKey");
501
- int index = minIndex();
502
- if (index == -1) {
503
- return null;
397
+ /**
398
+ * @webref intdict:method
399
+ * @brief Add to a value
400
+ */
401
+ public void add(String key, long amount) {
402
+ int index = index(key);
403
+ if (index == -1) {
404
+ create(key, amount);
405
+ } else {
406
+ values[index] += amount;
407
+ }
504
408
  }
505
- return keys[index];
506
- }
507
-
508
-
509
- // return the minimum value, or throw an error if there are no values
510
- public long minValue() {
511
- checkMinMax("minValue");
512
- return values[minIndex()];
513
- }
514
409
 
515
-
516
- // return the index of the max value
517
- public int maxIndex() {
518
- //checkMinMax("maxIndex");
519
- if (count == 0) {
520
- return -1;
521
- }
522
- int index = 0;
523
- long value = values[0];
524
- for (int i = 1; i < count; i++) {
525
- if (values[i] > value) {
526
- index = i;
527
- value = values[i];
528
- }
410
+ /**
411
+ * @webref intdict:method
412
+ * @brief Subtract from a value
413
+ */
414
+ public void sub(String key, long amount) {
415
+ add(key, -amount);
529
416
  }
530
- return index;
531
- }
532
-
533
417
 
534
- /** return the key corresponding to the maximum value or null if no entries */
535
- public String maxKey() {
536
- //checkMinMax("maxKey");
537
- int index = maxIndex();
538
- if (index == -1) {
539
- return null;
418
+ /**
419
+ * @webref intdict:method
420
+ * @brief Multiply a value
421
+ */
422
+ public void mult(String key, long amount) {
423
+ int index = index(key);
424
+ if (index != -1) {
425
+ values[index] *= amount;
426
+ }
540
427
  }
541
- return keys[index];
542
- }
543
428
 
429
+ /**
430
+ * @webref intdict:method
431
+ * @brief Divide a value
432
+ */
433
+ public void div(String key, long amount) {
434
+ int index = index(key);
435
+ if (index != -1) {
436
+ values[index] /= amount;
437
+ }
438
+ }
544
439
 
545
- // return the maximum value or throw an error if zero length
546
- public long maxValue() {
547
- checkMinMax("maxIndex");
548
- return values[maxIndex()];
549
- }
440
+ private void checkMinMax(String functionName) {
441
+ if (count == 0) {
442
+ String msg
443
+ = String.format("Cannot use %s() on an empty %s.",
444
+ functionName, getClass().getSimpleName());
445
+ throw new RuntimeException(msg);
446
+ }
447
+ }
550
448
 
449
+ // return the index of the minimum value
450
+ public int minIndex() {
451
+ //checkMinMax("minIndex");
452
+ if (count == 0) {
453
+ return -1;
454
+ }
551
455
 
552
- public long sum() {
553
- long sum = 0;
554
- for (int i = 0; i < count; i++) {
555
- sum += values[i];
456
+ int index = 0;
457
+ long value = values[0];
458
+ for (int i = 1; i < count; i++) {
459
+ if (values[i] < value) {
460
+ index = i;
461
+ value = values[i];
462
+ }
463
+ }
464
+ return index;
556
465
  }
557
- return sum;
558
- }
559
466
 
467
+ // return the key for the minimum value
468
+ public String minKey() {
469
+ checkMinMax("minKey");
470
+ int index = minIndex();
471
+ if (index == -1) {
472
+ return null;
473
+ }
474
+ return keys[index];
475
+ }
560
476
 
561
- public int index(String what) {
562
- Integer found = indices.get(what);
563
- return (found == null) ? -1 : found.intValue();
564
- }
477
+ // return the minimum value, or throw an error if there are no values
478
+ public long minValue() {
479
+ checkMinMax("minValue");
480
+ return values[minIndex()];
481
+ }
565
482
 
483
+ // return the index of the max value
484
+ public int maxIndex() {
485
+ //checkMinMax("maxIndex");
486
+ if (count == 0) {
487
+ return -1;
488
+ }
489
+ int index = 0;
490
+ long value = values[0];
491
+ for (int i = 1; i < count; i++) {
492
+ if (values[i] > value) {
493
+ index = i;
494
+ value = values[i];
495
+ }
496
+ }
497
+ return index;
498
+ }
566
499
 
567
- protected void create(String what, long much) {
568
- if (count == keys.length) {
569
- keys = PApplet.expand(keys);
570
- values = PApplet.expand(values);
500
+ /**
501
+ * return the key corresponding to the maximum value or null if no entries
502
+ */
503
+ public String maxKey() {
504
+ //checkMinMax("maxKey");
505
+ int index = maxIndex();
506
+ if (index == -1) {
507
+ return null;
508
+ }
509
+ return keys[index];
571
510
  }
572
- indices.put(what, Integer.valueOf(count));
573
- keys[count] = what;
574
- values[count] = much;
575
- count++;
576
- }
577
511
 
512
+ // return the maximum value or throw an error if zero length
513
+ public long maxValue() {
514
+ checkMinMax("maxIndex");
515
+ return values[maxIndex()];
516
+ }
578
517
 
579
- /**
580
- * @webref intdict:method
581
- * @brief Remove a key/value pair
582
- */
583
- public int remove(String key) {
584
- int index = index(key);
585
- if (index != -1) {
586
- removeIndex(index);
518
+ public long sum() {
519
+ long sum = 0;
520
+ for (int i = 0; i < count; i++) {
521
+ sum += values[i];
522
+ }
523
+ return sum;
587
524
  }
588
- return index;
589
- }
590
525
 
526
+ public int index(String what) {
527
+ Integer found = indices.get(what);
528
+ return (found == null) ? -1 : found.intValue();
529
+ }
591
530
 
592
- public String removeIndex(int index) {
593
- if (index < 0 || index >= count) {
594
- throw new ArrayIndexOutOfBoundsException(index);
531
+ protected void create(String what, long much) {
532
+ if (count == keys.length) {
533
+ keys = PApplet.expand(keys);
534
+ values = PApplet.expand(values);
535
+ }
536
+ indices.put(what, Integer.valueOf(count));
537
+ keys[count] = what;
538
+ values[count] = much;
539
+ count++;
595
540
  }
596
- //System.out.println("index is " + which + " and " + keys[which]);
597
- String key = keys[index];
598
- indices.remove(keys[index]);
599
- for (int i = index; i < count-1; i++) {
600
- keys[i] = keys[i+1];
601
- values[i] = values[i+1];
602
- indices.put(keys[i], i);
541
+
542
+ /**
543
+ * @webref intdict:method
544
+ * @brief Remove a key/value pair
545
+ */
546
+ public int remove(String key) {
547
+ int index = index(key);
548
+ if (index != -1) {
549
+ removeIndex(index);
550
+ }
551
+ return index;
603
552
  }
604
- count--;
605
- keys[count] = null;
606
- values[count] = 0;
607
- return key;
608
- }
609
553
 
554
+ public String removeIndex(int index) {
555
+ if (index < 0 || index >= count) {
556
+ throw new ArrayIndexOutOfBoundsException(index);
557
+ }
558
+ //System.out.println("index is " + which + " and " + keys[which]);
559
+ String key = keys[index];
560
+ indices.remove(keys[index]);
561
+ for (int i = index; i < count - 1; i++) {
562
+ keys[i] = keys[i + 1];
563
+ values[i] = values[i + 1];
564
+ indices.put(keys[i], i);
565
+ }
566
+ count--;
567
+ keys[count] = null;
568
+ values[count] = 0;
569
+ return key;
570
+ }
610
571
 
611
- public void swap(int a, int b) {
612
- String tkey = keys[a];
613
- long tvalue = values[a];
614
- keys[a] = keys[b];
615
- values[a] = values[b];
616
- keys[b] = tkey;
617
- values[b] = tvalue;
572
+ public void swap(int a, int b) {
573
+ String tkey = keys[a];
574
+ long tvalue = values[a];
575
+ keys[a] = keys[b];
576
+ values[a] = values[b];
577
+ keys[b] = tkey;
578
+ values[b] = tvalue;
618
579
 
619
580
  // indices.put(keys[a], Integer.valueOf(a));
620
581
  // indices.put(keys[b], Integer.valueOf(b));
621
- }
622
-
623
-
624
- /**
625
- * Sort the keys alphabetically (ignoring case). Uses the value as a
626
- * tie-breaker (only really possible with a key that has a case change).
627
- *
628
- * @webref intdict:method
629
- * @brief Sort the keys alphabetically
630
- */
631
- public void sortKeys() {
632
- sortImpl(true, false, true);
633
- }
634
-
635
- /**
636
- * Sort the keys alphabetically in reverse (ignoring case). Uses the value as a
637
- * tie-breaker (only really possible with a key that has a case change).
638
- *
639
- * @webref intdict:method
640
- * @brief Sort the keys alphabetically in reverse
641
- */
642
- public void sortKeysReverse() {
643
- sortImpl(true, true, true);
644
- }
645
-
646
-
647
- /**
648
- * Sort by values in ascending order. The smallest value will be at [0].
649
- *
650
- * @webref intdict:method
651
- * @brief Sort by values in ascending order
652
- */
653
- public void sortValues() {
654
- sortValues(true);
655
- }
656
-
657
-
658
- /**
659
- * Set true to ensure that the order returned is identical. Slightly
660
- * slower because the tie-breaker for identical values compares the keys.
661
- * @param stable
662
- */
663
- public void sortValues(boolean stable) {
664
- sortImpl(false, false, stable);
665
- }
666
-
667
-
668
- /**
669
- * Sort by values in descending order. The largest value will be at [0].
670
- *
671
- * @webref intdict:method
672
- * @brief Sort by values in descending order
673
- */
674
- public void sortValuesReverse() {
675
- sortValuesReverse(true);
676
- }
677
-
678
-
679
- public void sortValuesReverse(boolean stable) {
680
- sortImpl(false, true, stable);
681
- }
682
-
683
-
684
- protected void sortImpl(final boolean useKeys, final boolean reverse,
685
- final boolean stable) {
686
- Sort s = new Sort() {
687
- @Override
688
- public int size() {
689
- return count;
690
- }
691
-
692
- @Override
693
- public int compare(int a, int b) {
694
- long diff = 0;
695
- if (useKeys) {
696
- diff = keys[a].compareToIgnoreCase(keys[b]);
697
- if (diff == 0) {
698
- diff = values[a] - values[b];
699
- }
700
- } else { // sort values
701
- diff = values[a] - values[b];
702
- if (diff == 0 && stable) {
703
- diff = keys[a].compareToIgnoreCase(keys[b]);
704
- }
705
- }
706
- if (diff == 0) {
707
- return 0;
708
- } else if (reverse) {
709
- return diff < 0 ? 1 : -1;
710
- } else {
711
- return diff < 0 ? -1 : 1;
712
- }
713
- }
714
-
715
- @Override
716
- public void swap(int a, int b) {
717
- LongDict.this.swap(a, b);
718
- }
719
- };
720
- s.run();
721
-
722
- // Set the indices after sort/swaps (performance fix 160411)
723
- resetIndices();
724
- }
725
-
726
-
727
- /**
728
- * Sum all of the values in this dictionary, then return a new FloatDict of
729
- * each key, divided by the total sum. The total for all values will be ~1.0.
730
- * @return an IntDict with the original keys, mapped to their pct of the total
731
- */
732
- public FloatDict getPercent() {
733
- double sum = sum(); // a little more accuracy
734
- FloatDict outgoing = new FloatDict();
735
- for (int i = 0; i < size(); i++) {
736
- double percent = value(i) / sum;
737
- outgoing.set(key(i), (float) percent);
738
582
  }
739
- return outgoing;
740
- }
741
-
742
583
 
743
- /** Returns a duplicate copy of this object. */
744
- public LongDict copy() {
745
- LongDict outgoing = new LongDict(count);
746
- System.arraycopy(keys, 0, outgoing.keys, 0, count);
747
- System.arraycopy(values, 0, outgoing.values, 0, count);
748
- for (int i = 0; i < count; i++) {
749
- outgoing.indices.put(keys[i], i);
584
+ /**
585
+ * Sort the keys alphabetically (ignoring case). Uses the value as a
586
+ * tie-breaker (only really possible with a key that has a case change).
587
+ *
588
+ * @webref intdict:method
589
+ * @brief Sort the keys alphabetically
590
+ */
591
+ public void sortKeys() {
592
+ sortImpl(true, false, true);
593
+ }
594
+
595
+ /**
596
+ * Sort the keys alphabetically in reverse (ignoring case). Uses the value
597
+ * as a tie-breaker (only really possible with a key that has a case
598
+ * change).
599
+ *
600
+ * @webref intdict:method
601
+ * @brief Sort the keys alphabetically in reverse
602
+ */
603
+ public void sortKeysReverse() {
604
+ sortImpl(true, true, true);
605
+ }
606
+
607
+ /**
608
+ * Sort by values in ascending order. The smallest value will be at [0].
609
+ *
610
+ * @webref intdict:method
611
+ * @brief Sort by values in ascending order
612
+ */
613
+ public void sortValues() {
614
+ sortValues(true);
615
+ }
616
+
617
+ /**
618
+ * Set true to ensure that the order returned is identical. Slightly slower
619
+ * because the tie-breaker for identical values compares the keys.
620
+ *
621
+ * @param stable
622
+ */
623
+ public void sortValues(boolean stable) {
624
+ sortImpl(false, false, stable);
625
+ }
626
+
627
+ /**
628
+ * Sort by values in descending order. The largest value will be at [0].
629
+ *
630
+ * @webref intdict:method
631
+ * @brief Sort by values in descending order
632
+ */
633
+ public void sortValuesReverse() {
634
+ sortValuesReverse(true);
635
+ }
636
+
637
+ public void sortValuesReverse(boolean stable) {
638
+ sortImpl(false, true, stable);
639
+ }
640
+
641
+ protected void sortImpl(final boolean useKeys, final boolean reverse,
642
+ final boolean stable) {
643
+ Sort s = new Sort() {
644
+ @Override
645
+ public int size() {
646
+ return count;
647
+ }
648
+
649
+ @Override
650
+ public int compare(int a, int b) {
651
+ long diff = 0;
652
+ if (useKeys) {
653
+ diff = keys[a].compareToIgnoreCase(keys[b]);
654
+ if (diff == 0) {
655
+ diff = values[a] - values[b];
656
+ }
657
+ } else { // sort values
658
+ diff = values[a] - values[b];
659
+ if (diff == 0 && stable) {
660
+ diff = keys[a].compareToIgnoreCase(keys[b]);
661
+ }
662
+ }
663
+ if (diff == 0) {
664
+ return 0;
665
+ } else if (reverse) {
666
+ return diff < 0 ? 1 : -1;
667
+ } else {
668
+ return diff < 0 ? -1 : 1;
669
+ }
670
+ }
671
+
672
+ @Override
673
+ public void swap(int a, int b) {
674
+ LongDict.this.swap(a, b);
675
+ }
676
+ };
677
+ s.run();
678
+
679
+ // Set the indices after sort/swaps (performance fix 160411)
680
+ resetIndices();
681
+ }
682
+
683
+ /**
684
+ * Sum all of the values in this dictionary, then return a new FloatDict of
685
+ * each key, divided by the total sum. The total for all values will be
686
+ * ~1.0.
687
+ *
688
+ * @return an IntDict with the original keys, mapped to their pct of the
689
+ * total
690
+ */
691
+ public FloatDict getPercent() {
692
+ double sum = sum(); // a little more accuracy
693
+ FloatDict outgoing = new FloatDict();
694
+ for (int i = 0; i < size(); i++) {
695
+ double percent = value(i) / sum;
696
+ outgoing.set(key(i), (float) percent);
697
+ }
698
+ return outgoing;
699
+ }
700
+
701
+ /**
702
+ * Returns a duplicate copy of this object.
703
+ */
704
+ public LongDict copy() {
705
+ LongDict outgoing = new LongDict(count);
706
+ System.arraycopy(keys, 0, outgoing.keys, 0, count);
707
+ System.arraycopy(values, 0, outgoing.values, 0, count);
708
+ for (int i = 0; i < count; i++) {
709
+ outgoing.indices.put(keys[i], i);
710
+ }
711
+ outgoing.count = count;
712
+ return outgoing;
750
713
  }
751
- outgoing.count = count;
752
- return outgoing;
753
- }
754
-
755
714
 
756
- public void print() {
757
- for (int i = 0; i < size(); i++) {
758
- System.out.println(keys[i] + " = " + values[i]);
715
+ public void print() {
716
+ for (int i = 0; i < size(); i++) {
717
+ System.out.println(keys[i] + " = " + values[i]);
718
+ }
759
719
  }
760
- }
761
-
762
-
763
- /**
764
- * Save tab-delimited entries to a file (TSV format, UTF-8 encoding)
765
- */
766
- public void save(File file) {
767
- PrintWriter writer = PApplet.createWriter(file);
768
- write(writer);
769
- writer.close();
770
- }
771
720
 
772
-
773
- /**
774
- * Write tab-delimited entries to a PrintWriter
775
- */
776
- public void write(PrintWriter writer) {
777
- for (int i = 0; i < count; i++) {
778
- writer.println(keys[i] + "\t" + values[i]);
721
+ /**
722
+ * Save tab-delimited entries to a file (TSV format, UTF-8 encoding)
723
+ */
724
+ public void save(File file) {
725
+ PrintWriter writer = PApplet.createWriter(file);
726
+ write(writer);
727
+ writer.close();
779
728
  }
780
- writer.flush();
781
- }
782
-
783
729
 
784
- /**
785
- * Return this dictionary as a String in JSON format.
786
- */
787
- public String toJSON() {
788
- StringList items = new StringList();
789
- for (int i = 0; i < count; i++) {
790
- items.append(JSONObject.quote(keys[i])+ ": " + values[i]);
730
+ /**
731
+ * Write tab-delimited entries to a PrintWriter
732
+ */
733
+ public void write(PrintWriter writer) {
734
+ for (int i = 0; i < count; i++) {
735
+ writer.println(keys[i] + "\t" + values[i]);
736
+ }
737
+ writer.flush();
791
738
  }
792
- return "{ " + items.join(", ") + " }";
793
- }
794
739
 
740
+ /**
741
+ * Return this dictionary as a String in JSON format.
742
+ */
743
+ public String toJSON() {
744
+ StringList items = new StringList();
745
+ for (int i = 0; i < count; i++) {
746
+ items.append(JSONObject.quote(keys[i]) + ": " + values[i]);
747
+ }
748
+ return "{ " + items.join(", ") + " }";
749
+ }
795
750
 
796
- @Override
797
- public String toString() {
798
- return getClass().getSimpleName() + " size=" + size() + " " + toJSON();
799
- }
751
+ @Override
752
+ public String toString() {
753
+ return getClass().getSimpleName() + " size=" + size() + " " + toJSON();
754
+ }
800
755
  }