propane 3.4.1-java → 3.7.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/.mvn/extensions.xml +1 -1
  3. data/.mvn/wrapper/MavenWrapperDownloader.java +2 -2
  4. data/.mvn/wrapper/maven-wrapper.properties +2 -2
  5. data/.travis.yml +1 -1
  6. data/CHANGELOG.md +9 -1
  7. data/Gemfile +2 -0
  8. data/README.md +9 -5
  9. data/Rakefile +10 -11
  10. data/bin/propane +3 -1
  11. data/lib/propane.rb +4 -2
  12. data/lib/propane/app.rb +2 -1
  13. data/lib/propane/creators/sketch_class.rb +7 -1
  14. data/lib/propane/creators/sketch_factory.rb +4 -2
  15. data/lib/propane/creators/sketch_writer.rb +1 -0
  16. data/lib/propane/helper_methods.rb +22 -23
  17. data/lib/propane/helpers/numeric.rb +2 -0
  18. data/lib/propane/helpers/version_error.rb +1 -0
  19. data/lib/propane/library.rb +5 -1
  20. data/lib/propane/library_loader.rb +2 -0
  21. data/lib/propane/native_folder.rb +10 -9
  22. data/lib/propane/native_loader.rb +3 -0
  23. data/lib/propane/runner.rb +20 -14
  24. data/lib/propane/version.rb +2 -1
  25. data/library/boids/boids.rb +21 -11
  26. data/library/color_group/color_group.rb +2 -0
  27. data/library/control_panel/control_panel.rb +8 -5
  28. data/library/dxf/dxf.rb +2 -0
  29. data/library/file_chooser/chooser.rb +10 -9
  30. data/library/file_chooser/file_chooser.rb +10 -9
  31. data/library/library_proxy/library_proxy.rb +2 -0
  32. data/library/net/net.rb +2 -0
  33. data/library/simplex_noise/simplex_noise.rb +2 -0
  34. data/library/slider/slider.rb +23 -22
  35. data/library/vector_utils/vector_utils.rb +4 -0
  36. data/library/video_event/video_event.rb +2 -0
  37. data/pom.rb +37 -36
  38. data/pom.xml +6 -6
  39. data/propane.gemspec +12 -10
  40. data/src/main/java/japplemenubar/JAppleMenuBar.java +3 -3
  41. data/src/main/java/monkstone/ColorUtil.java +1 -3
  42. data/src/main/java/monkstone/MathToolModule.java +10 -9
  43. data/src/main/java/monkstone/PropaneLibrary.java +2 -2
  44. data/src/main/java/monkstone/fastmath/Deglut.java +1 -1
  45. data/src/main/java/monkstone/filechooser/Chooser.java +1 -1
  46. data/src/main/java/monkstone/noise/SimplexNoise.java +2 -2
  47. data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +1 -1
  48. data/src/main/java/monkstone/slider/CustomVerticalSlider.java +1 -1
  49. data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +1 -1
  50. data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +1 -1
  51. data/src/main/java/monkstone/slider/SliderBar.java +1 -1
  52. data/src/main/java/monkstone/slider/SliderGroup.java +1 -1
  53. data/src/main/java/monkstone/slider/WheelHandler.java +1 -1
  54. data/src/main/java/monkstone/vecmath/package-info.java +1 -1
  55. data/src/main/java/monkstone/vecmath/vec2/Vec2.java +1 -1
  56. data/src/main/java/monkstone/vecmath/vec3/Vec3.java +1 -2
  57. data/src/main/java/monkstone/videoevent/CaptureEvent.java +1 -1
  58. data/src/main/java/monkstone/videoevent/MovieEvent.java +1 -1
  59. data/src/main/java/monkstone/videoevent/package-info.java +1 -1
  60. data/src/main/java/processing/awt/PGraphicsJava2D.java +781 -285
  61. data/src/main/java/processing/awt/PImageAWT.java +377 -0
  62. data/src/main/java/processing/awt/PShapeJava2D.java +56 -52
  63. data/src/main/java/processing/awt/PSurfaceAWT.java +308 -208
  64. data/src/main/java/processing/awt/ShimAWT.java +581 -0
  65. data/src/main/java/processing/core/PApplet.java +4225 -4855
  66. data/src/main/java/processing/core/PConstants.java +477 -447
  67. data/src/main/java/processing/core/PFont.java +914 -880
  68. data/src/main/java/processing/core/PGraphics.java +150 -134
  69. data/src/main/java/processing/core/PImage.java +275 -372
  70. data/src/main/java/processing/core/PMatrix.java +172 -159
  71. data/src/main/java/processing/core/PMatrix2D.java +478 -415
  72. data/src/main/java/processing/core/PMatrix3D.java +762 -735
  73. data/src/main/java/processing/core/PShape.java +2887 -2651
  74. data/src/main/java/processing/core/PShapeOBJ.java +97 -92
  75. data/src/main/java/processing/core/PShapeSVG.java +1705 -1490
  76. data/src/main/java/processing/core/PStyle.java +40 -37
  77. data/src/main/java/processing/core/PSurface.java +139 -97
  78. data/src/main/java/processing/core/PSurfaceNone.java +296 -218
  79. data/src/main/java/processing/core/PVector.java +995 -963
  80. data/src/main/java/processing/core/ThinkDifferent.java +12 -8
  81. data/src/main/java/processing/data/DoubleDict.java +756 -710
  82. data/src/main/java/processing/data/DoubleList.java +749 -696
  83. data/src/main/java/processing/data/FloatDict.java +748 -702
  84. data/src/main/java/processing/data/FloatList.java +751 -697
  85. data/src/main/java/processing/data/IntDict.java +720 -673
  86. data/src/main/java/processing/data/IntList.java +699 -633
  87. data/src/main/java/processing/data/JSONArray.java +931 -873
  88. data/src/main/java/processing/data/JSONObject.java +1262 -1165
  89. data/src/main/java/processing/data/JSONTokener.java +351 -341
  90. data/src/main/java/processing/data/LongDict.java +710 -663
  91. data/src/main/java/processing/data/LongList.java +701 -635
  92. data/src/main/java/processing/data/Sort.java +37 -41
  93. data/src/main/java/processing/data/StringDict.java +525 -486
  94. data/src/main/java/processing/data/StringList.java +626 -580
  95. data/src/main/java/processing/data/Table.java +3690 -3510
  96. data/src/main/java/processing/data/TableRow.java +182 -183
  97. data/src/main/java/processing/data/XML.java +957 -883
  98. data/src/main/java/processing/event/Event.java +87 -67
  99. data/src/main/java/processing/event/KeyEvent.java +48 -41
  100. data/src/main/java/processing/event/MouseEvent.java +88 -113
  101. data/src/main/java/processing/event/TouchEvent.java +10 -6
  102. data/src/main/java/processing/javafx/PGraphicsFX2D.java +20 -345
  103. data/src/main/java/processing/javafx/PSurfaceFX.java +149 -121
  104. data/src/main/java/processing/net/Client.java +20 -20
  105. data/src/main/java/processing/net/Server.java +9 -9
  106. data/src/main/java/processing/opengl/FontTexture.java +286 -266
  107. data/src/main/java/processing/opengl/FrameBuffer.java +389 -377
  108. data/src/main/java/processing/opengl/LinePath.java +132 -89
  109. data/src/main/java/processing/opengl/LineStroker.java +588 -581
  110. data/src/main/java/processing/opengl/PGL.java +660 -567
  111. data/src/main/java/processing/opengl/PGraphics2D.java +408 -315
  112. data/src/main/java/processing/opengl/PGraphics3D.java +107 -72
  113. data/src/main/java/processing/opengl/PGraphicsOpenGL.java +12378 -12075
  114. data/src/main/java/processing/opengl/PJOGL.java +1753 -1670
  115. data/src/main/java/processing/opengl/PShader.java +369 -461
  116. data/src/main/java/processing/opengl/PShapeOpenGL.java +4678 -4580
  117. data/src/main/java/processing/opengl/PSurfaceJOGL.java +1114 -1027
  118. data/src/main/java/processing/opengl/Texture.java +1492 -1401
  119. data/src/main/java/processing/opengl/VertexBuffer.java +57 -55
  120. data/test/create_test.rb +21 -20
  121. data/test/deglut_spec_test.rb +4 -2
  122. data/test/helper_methods_test.rb +49 -20
  123. data/test/math_tool_test.rb +39 -32
  124. data/test/native_folder.rb +47 -0
  125. data/test/respond_to_test.rb +3 -2
  126. data/test/sketches/key_event.rb +2 -2
  127. data/test/sketches/library/my_library/my_library.rb +3 -0
  128. data/test/test_helper.rb +2 -0
  129. data/test/vecmath_spec_test.rb +35 -22
  130. data/vendors/Rakefile +35 -40
  131. metadata +42 -22
  132. data/src/main/java/processing/opengl/shaders/LightVert-brcm.glsl +0 -154
  133. data/src/main/java/processing/opengl/shaders/LightVert-vc4.glsl +0 -154
  134. data/src/main/java/processing/opengl/shaders/TexLightVert-brcm.glsl +0 -160
  135. data/src/main/java/processing/opengl/shaders/TexLightVert-vc4.glsl +0 -160
@@ -1,50 +1,46 @@
1
1
  package processing.data;
2
2
 
3
+
3
4
  /**
4
- * Internal sorter used by several data classes. Advanced users only, not
5
- * official API.
5
+ * Internal sorter used by several data classes.
6
+ * Advanced users only, not official API.
6
7
  */
7
8
  public abstract class Sort implements Runnable {
8
9
 
9
- public Sort() {
10
- }
11
-
12
- public void run() {
13
- int c = size();
14
- if (c > 1) {
15
- sort(0, c - 1);
16
- }
17
- }
10
+ public Sort() { }
18
11
 
19
- protected void sort(int i, int j) {
20
- int pivotIndex = (i + j) / 2;
21
- swap(pivotIndex, j);
22
- int k = partition(i - 1, j);
23
- swap(k, j);
24
- if ((k - i) > 1) {
25
- sort(i, k - 1);
26
- }
27
- if ((j - k) > 1) {
28
- sort(k + 1, j);
29
- }
30
- }
31
12
 
32
- protected int partition(int left, int right) {
33
- int pivot = right;
34
- do {
35
- while (compare(++left, pivot) < 0) {
36
- }
37
- while ((right != 0) && (compare(--right, pivot) > 0)) {
38
- }
39
- swap(left, right);
40
- } while (left < right);
41
- swap(left, right);
42
- return left;
13
+ public void run() {
14
+ int c = size();
15
+ if (c > 1) {
16
+ sort(0, c - 1);
43
17
  }
44
-
45
- abstract public int size();
46
-
47
- abstract public int compare(int a, int b);
48
-
49
- abstract public void swap(int a, int b);
50
- }
18
+ }
19
+
20
+
21
+ protected void sort(int i, int j) {
22
+ int pivotIndex = (i+j)/2;
23
+ swap(pivotIndex, j);
24
+ int k = partition(i-1, j);
25
+ swap(k, j);
26
+ if ((k-i) > 1) sort(i, k-1);
27
+ if ((j-k) > 1) sort(k+1, j);
28
+ }
29
+
30
+
31
+ protected int partition(int left, int right) {
32
+ int pivot = right;
33
+ do {
34
+ while (compare(++left, pivot) < 0) { }
35
+ while ((right != 0) && (compare(--right, pivot) > 0)) { }
36
+ swap(left, right);
37
+ } while (left < right);
38
+ swap(left, right);
39
+ return left;
40
+ }
41
+
42
+
43
+ abstract public int size();
44
+ abstract public int compare(int a, int b);
45
+ abstract public void swap(int a, int b);
46
+ }
@@ -3,9 +3,11 @@ package processing.data;
3
3
  import java.io.*;
4
4
  import java.util.HashMap;
5
5
  import java.util.Iterator;
6
+ import java.util.NoSuchElementException;
6
7
 
7
8
  import processing.core.PApplet;
8
9
 
10
+
9
11
  /**
10
12
  * A simple table class to use a String as a lookup for another String value.
11
13
  *
@@ -15,560 +17,597 @@ import processing.core.PApplet;
15
17
  */
16
18
  public class StringDict {
17
19
 
18
- /**
19
- * Number of elements in the table
20
- */
21
- protected int count;
20
+ /** Number of elements in the table */
21
+ protected int count;
22
+
23
+ protected String[] keys;
24
+ protected String[] values;
25
+
26
+ /** Internal implementation for faster lookups */
27
+ private HashMap<String, Integer> indices = new HashMap<>();
28
+
29
+
30
+ public StringDict() {
31
+ count = 0;
32
+ keys = new String[10];
33
+ values = new String[10];
34
+ }
35
+
36
+
37
+ /**
38
+ * Create a new lookup pre-allocated to a specific length. This will not
39
+ * change the size(), but is more efficient than not specifying a length.
40
+ * Use it when you know the rough size of the thing you're creating.
41
+ *
42
+ * @nowebref
43
+ */
44
+ public StringDict(int length) {
45
+ count = 0;
46
+ keys = new String[length];
47
+ values = new String[length];
48
+ }
49
+
50
+
51
+ /**
52
+ * Read a set of entries from a Reader that has each key/value pair on
53
+ * a single line, separated by a tab.
54
+ *
55
+ * @nowebref
56
+ */
57
+ public StringDict(BufferedReader reader) {
58
+ String[] lines = PApplet.loadStrings(reader);
59
+ keys = new String[lines.length];
60
+ values = new String[lines.length];
61
+
62
+ for (int i = 0; i < lines.length; i++) {
63
+ String[] pieces = PApplet.split(lines[i], '\t');
64
+ if (pieces.length == 2) {
65
+ keys[count] = pieces[0];
66
+ values[count] = pieces[1];
67
+ indices.put(keys[count], count);
68
+ count++;
69
+ }
70
+ }
71
+ }
72
+
73
+
74
+ /**
75
+ * @nowebref
76
+ */
77
+ public StringDict(String[] keys, String[] values) {
78
+ if (keys.length != values.length) {
79
+ throw new IllegalArgumentException("key and value arrays must be the same length");
80
+ }
81
+ this.keys = keys;
82
+ this.values = values;
83
+ count = keys.length;
84
+ for (int i = 0; i < count; i++) {
85
+ indices.put(keys[i], i);
86
+ }
87
+ }
88
+
89
+
90
+ /**
91
+ * Constructor to allow (more intuitive) inline initialization, e.g.:
92
+ * <pre>
93
+ * new StringDict(new String[][] {
94
+ * { "key1", "value1" },
95
+ * { "key2", "value2" }
96
+ * });
97
+ * </pre>
98
+ * It's no Python, but beats a static { } block with HashMap.put() statements.
99
+ */
100
+ public StringDict(String[][] pairs) {
101
+ count = pairs.length;
102
+ this.keys = new String[count];
103
+ this.values = new String[count];
104
+ for (int i = 0; i < count; i++) {
105
+ keys[i] = pairs[i][0];
106
+ values[i] = pairs[i][1];
107
+ indices.put(keys[i], i);
108
+ }
109
+ }
22
110
 
23
- protected String[] keys;
24
- protected String[] values;
25
111
 
26
- /**
27
- * Internal implementation for faster lookups
28
- */
29
- private HashMap<String, Integer> indices = new HashMap<>();
112
+ /**
113
+ * Create a dictionary that maps between column titles and cell entries
114
+ * in a TableRow. If two columns have the same name, the later column's
115
+ * values will override the earlier values.
116
+ */
117
+ public StringDict(TableRow row) {
118
+ this(row.getColumnCount());
30
119
 
31
- public StringDict() {
32
- count = 0;
33
- keys = new String[10];
34
- values = new String[10];
120
+ String[] titles = row.getColumnTitles();
121
+ if (titles == null) {
122
+ titles = new StringList(IntList.fromRange(row.getColumnCount())).array();
35
123
  }
36
-
37
- /**
38
- * Create a new lookup pre-allocated to a specific length. This will not
39
- * change the size(), but is more efficient than not specifying a length.
40
- * Use it when you know the rough size of the thing you're creating.
41
- *
42
- * @nowebref
43
- */
44
- public StringDict(int length) {
45
- count = 0;
46
- keys = new String[length];
47
- values = new String[length];
124
+ for (int col = 0; col < row.getColumnCount(); col++) {
125
+ set(titles[col], row.getString(col));
48
126
  }
127
+ // remove unused and overwritten entries
128
+ crop();
129
+ }
49
130
 
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 StringDict(BufferedReader reader) {
57
- String[] lines = PApplet.loadStrings(reader);
58
- keys = new String[lines.length];
59
- values = new String[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] = pieces[1];
66
- indices.put(keys[count], count);
67
- count++;
68
- }
69
- }
70
- }
71
131
 
72
- /**
73
- * @nowebref
74
- */
75
- public StringDict(String[] keys, String[] 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
- }
85
- }
132
+ /**
133
+ * @webref stringdict:method
134
+ * @brief Returns the number of key/value pairs
135
+ */
136
+ public int size() {
137
+ return count;
138
+ }
86
139
 
87
- /**
88
- * Constructor to allow (more intuitive) inline initialization, e.g.:
89
- * <pre>
90
- * new StringDict(new String[][] {
91
- * { "key1", "value1" },
92
- * { "key2", "value2" }
93
- * });
94
- * </pre> It's no Python, but beats a static { } block with HashMap.put()
95
- * statements.
96
- */
97
- public StringDict(String[][] pairs) {
98
- count = pairs.length;
99
- this.keys = new String[count];
100
- this.values = new String[count];
101
- for (int i = 0; i < count; i++) {
102
- keys[i] = pairs[i][0];
103
- values[i] = pairs[i][1];
104
- indices.put(keys[i], i);
105
- }
106
- }
107
140
 
108
- /**
109
- * Create a dictionary that maps between column titles and cell entries in a
110
- * TableRow. If two columns have the same name, the later column's values
111
- * will override the earlier values.
112
- */
113
- public StringDict(TableRow row) {
114
- this(row.getColumnCount());
115
-
116
- String[] titles = row.getColumnTitles();
117
- if (titles == null) {
118
- titles = new StringList(IntList.fromRange(row.getColumnCount())).array();
119
- }
120
- for (int col = 0; col < row.getColumnCount(); col++) {
121
- set(titles[col], row.getString(col));
122
- }
123
- // remove unused and overwritten entries
124
- crop();
141
+ /**
142
+ * Resize the internal data, this can only be used to shrink the list.
143
+ * Helpful for situations like sorting and then grabbing the top 50 entries.
144
+ */
145
+ public void resize(int length) {
146
+ if (length > count) {
147
+ throw new IllegalArgumentException("resize() can only be used to shrink the dictionary");
125
148
  }
126
-
127
- /**
128
- * @webref stringdict:method
129
- * @brief Returns the number of key/value pairs
130
- */
131
- public int size() {
132
- return count;
149
+ if (length < 1) {
150
+ throw new IllegalArgumentException("resize(" + length + ") is too small, use 1 or higher");
133
151
  }
134
152
 
135
- /**
136
- * Resize the internal data, this can only be used to shrink the list.
137
- * Helpful for situations like sorting and then grabbing the top 50 entries.
138
- */
139
- public void resize(int length) {
140
- if (length > count) {
141
- throw new IllegalArgumentException("resize() can only be used to shrink the dictionary");
142
- }
143
- if (length < 1) {
144
- throw new IllegalArgumentException("resize(" + length + ") is too small, use 1 or higher");
145
- }
153
+ String[] newKeys = new String[length];
154
+ String[] newValues = new String[length];
155
+ PApplet.arrayCopy(keys, newKeys, length);
156
+ PApplet.arrayCopy(values, newValues, length);
157
+ keys = newKeys;
158
+ values = newValues;
159
+ count = length;
160
+ resetIndices();
161
+ }
146
162
 
147
- String[] newKeys = new String[length];
148
- String[] newValues = new String[length];
149
- PApplet.arrayCopy(keys, newKeys, length);
150
- PApplet.arrayCopy(values, newValues, length);
151
- keys = newKeys;
152
- values = newValues;
153
- count = length;
154
- resetIndices();
155
- }
156
163
 
157
- /**
158
- * Remove all entries.
159
- *
160
- * @webref stringdict:method
161
- * @brief Remove all entries
162
- */
163
- public void clear() {
164
- count = 0;
165
- indices = new HashMap<>();
166
- }
164
+ /**
165
+ * Remove all entries.
166
+ *
167
+ * @webref stringdict:method
168
+ * @brief Remove all entries
169
+ */
170
+ public void clear() {
171
+ count = 0;
172
+ indices = new HashMap<>();
173
+ }
167
174
 
168
- private void resetIndices() {
169
- indices = new HashMap<>(count);
170
- for (int i = 0; i < count; i++) {
171
- indices.put(keys[i], i);
172
- }
175
+
176
+ private void resetIndices() {
177
+ indices = new HashMap<>(count);
178
+ for (int i = 0; i < count; i++) {
179
+ indices.put(keys[i], i);
173
180
  }
181
+ }
174
182
 
175
- // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
176
- public class Entry {
177
183
 
178
- public String key;
179
- public String value;
184
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
180
185
 
181
- Entry(String key, String value) {
182
- this.key = key;
183
- this.value = value;
184
- }
185
- }
186
186
 
187
- public Iterable<Entry> entries() {
188
- return new Iterable<Entry>() {
187
+ public class Entry {
188
+ public String key;
189
+ public String value;
189
190
 
190
- public Iterator<Entry> iterator() {
191
- return entryIterator();
192
- }
193
- };
191
+ Entry(String key, String value) {
192
+ this.key = key;
193
+ this.value = value;
194
194
  }
195
+ }
195
196
 
196
- public Iterator<Entry> entryIterator() {
197
- return new Iterator<Entry>() {
198
- int index = -1;
199
-
200
- public void remove() {
201
- removeIndex(index);
202
- index--;
203
- }
204
-
205
- public Entry next() {
206
- ++index;
207
- Entry e = new Entry(keys[index], values[index]);
208
- return e;
209
- }
210
-
211
- public boolean hasNext() {
212
- return index + 1 < size();
213
- }
214
- };
215
- }
216
197
 
217
- // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
218
- public String key(int index) {
219
- return keys[index];
220
- }
198
+ public Iterable<Entry> entries() {
199
+ return new Iterable<Entry>() {
221
200
 
222
- protected void crop() {
223
- if (count != keys.length) {
224
- keys = PApplet.subset(keys, 0, count);
225
- values = PApplet.subset(values, 0, count);
226
- }
227
- }
201
+ public Iterator<Entry> iterator() {
202
+ return entryIterator();
203
+ }
204
+ };
205
+ }
228
206
 
229
- public Iterable<String> keys() {
230
- return new Iterable<String>() {
231
207
 
232
- @Override
233
- public Iterator<String> iterator() {
234
- return keyIterator();
235
- }
236
- };
237
- }
208
+ public Iterator<Entry> entryIterator() {
209
+ return new Iterator<Entry>() {
210
+ int index = -1;
238
211
 
239
- // Use this to iterate when you want to be able to remove elements along the way
240
- public Iterator<String> keyIterator() {
241
- return new Iterator<String>() {
242
- int index = -1;
212
+ public void remove() {
213
+ removeIndex(index);
214
+ index--;
215
+ }
243
216
 
244
- public void remove() {
245
- removeIndex(index);
246
- index--;
247
- }
217
+ public Entry next() {
218
+ ++index;
219
+ Entry e = new Entry(keys[index], values[index]);
220
+ return e;
221
+ }
248
222
 
249
- public String next() {
250
- return key(++index);
251
- }
223
+ public boolean hasNext() {
224
+ return index+1 < size();
225
+ }
226
+ };
227
+ }
252
228
 
253
- public boolean hasNext() {
254
- return index + 1 < size();
255
- }
256
- };
257
- }
258
229
 
259
- /**
260
- * Return a copy of the internal keys array. This array can be modified.
261
- *
262
- * @webref stringdict:method
263
- * @brief Return a copy of the internal keys array
264
- */
265
- public String[] keyArray() {
266
- crop();
267
- return keyArray(null);
268
- }
230
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
269
231
 
270
- public String[] keyArray(String[] outgoing) {
271
- if (outgoing == null || outgoing.length != count) {
272
- outgoing = new String[count];
273
- }
274
- System.arraycopy(keys, 0, outgoing, 0, count);
275
- return outgoing;
276
- }
277
232
 
278
- public String value(int index) {
279
- return values[index];
280
- }
233
+ public String key(int index) {
234
+ return keys[index];
235
+ }
236
+
281
237
 
282
- /**
283
- * @webref stringdict:method
284
- * @brief Return the internal array being used to store the values
285
- */
286
- public Iterable<String> values() {
287
- return new Iterable<String>() {
288
-
289
- @Override
290
- public Iterator<String> iterator() {
291
- return valueIterator();
292
- }
293
- };
238
+ protected void crop() {
239
+ if (count != keys.length) {
240
+ keys = PApplet.subset(keys, 0, count);
241
+ values = PApplet.subset(values, 0, count);
294
242
  }
243
+ }
295
244
 
296
- public Iterator<String> valueIterator() {
297
- return new Iterator<String>() {
298
- int index = -1;
299
245
 
300
- public void remove() {
301
- removeIndex(index);
302
- index--;
303
- }
246
+ public Iterable<String> keys() {
247
+ return new Iterable<String>() {
304
248
 
305
- public String next() {
306
- return value(++index);
307
- }
249
+ @Override
250
+ public Iterator<String> iterator() {
251
+ return keyIterator();
252
+ }
253
+ };
254
+ }
308
255
 
309
- public boolean hasNext() {
310
- return index + 1 < size();
311
- }
312
- };
313
- }
314
256
 
315
- /**
316
- * Create a new array and copy each of the values into it.
317
- *
318
- * @webref stringdict:method
319
- * @brief Create a new array and copy each of the values into it
320
- */
321
- public String[] valueArray() {
322
- crop();
323
- return valueArray(null);
324
- }
257
+ // Use this to iterate when you want to be able to remove elements along the way
258
+ public Iterator<String> keyIterator() {
259
+ return new Iterator<String>() {
260
+ int index = -1;
325
261
 
326
- /**
327
- * Fill an already-allocated array with the values (more efficient than
328
- * creating a new array each time). If 'array' is null, or not the same size
329
- * as the number of values, a new array will be allocated and returned.
330
- */
331
- public String[] valueArray(String[] array) {
332
- if (array == null || array.length != size()) {
333
- array = new String[count];
334
- }
335
- System.arraycopy(values, 0, array, 0, count);
336
- return array;
337
- }
262
+ public void remove() {
263
+ removeIndex(index);
264
+ index--;
265
+ }
338
266
 
339
- /**
340
- * Return a value for the specified key.
341
- *
342
- * @webref stringdict:method
343
- * @brief Return a value for the specified key
344
- */
345
- public String get(String key) {
346
- int index = index(key);
347
- if (index == -1) {
348
- return null;
349
- }
350
- return values[index];
351
- }
267
+ public String next() {
268
+ return key(++index);
269
+ }
352
270
 
353
- public String get(String key, String alternate) {
354
- int index = index(key);
355
- if (index == -1) {
356
- return alternate;
357
- }
358
- return values[index];
359
- }
271
+ public boolean hasNext() {
272
+ return index+1 < size();
273
+ }
274
+ };
275
+ }
360
276
 
361
- /**
362
- * @webref stringdict:method
363
- * @brief Create a new key/value pair or change the value of one
364
- */
365
- public void set(String key, String value) {
366
- int index = index(key);
367
- if (index == -1) {
368
- create(key, value);
369
- } else {
370
- values[index] = value;
371
- }
372
- }
373
277
 
374
- public void setIndex(int index, String key, String value) {
375
- if (index < 0 || index >= count) {
376
- throw new ArrayIndexOutOfBoundsException(index);
377
- }
378
- keys[index] = key;
379
- values[index] = value;
380
- }
278
+ /**
279
+ * Return a copy of the internal keys array. This array can be modified.
280
+ *
281
+ * @webref stringdict:method
282
+ * @brief Return a copy of the internal keys array
283
+ */
284
+ public String[] keyArray() {
285
+ crop();
286
+ return keyArray(null);
287
+ }
381
288
 
382
- public int index(String what) {
383
- Integer found = indices.get(what);
384
- return (found == null) ? -1 : found.intValue();
385
- }
386
289
 
387
- /**
388
- * @webref stringdict:method
389
- * @brief Check if a key is a part of the data structure
390
- */
391
- public boolean hasKey(String key) {
392
- return index(key) != -1;
393
- }
290
+ public String[] keyArray(String[] outgoing) {
291
+ if (outgoing == null || outgoing.length != count) {
292
+ outgoing = new String[count];
293
+ }
294
+ System.arraycopy(keys, 0, outgoing, 0, count);
295
+ return outgoing;
296
+ }
394
297
 
395
- protected void create(String key, String value) {
396
- if (count == keys.length) {
397
- keys = PApplet.expand(keys);
398
- values = PApplet.expand(values);
399
- }
400
- indices.put(key, Integer.valueOf(count));
401
- keys[count] = key;
402
- values[count] = value;
403
- count++;
404
- }
405
298
 
406
- /**
407
- * @webref stringdict:method
408
- * @brief Remove a key/value pair
409
- */
410
- public int remove(String key) {
411
- int index = index(key);
412
- if (index != -1) {
413
- removeIndex(index);
414
- }
415
- return index;
416
- }
299
+ public String value(int index) {
300
+ return values[index];
301
+ }
302
+
303
+ /**
304
+ * @webref stringdict:method
305
+ * @brief Return the internal array being used to store the values
306
+ */
307
+ public Iterable<String> values() {
308
+ return new Iterable<String>() {
309
+
310
+ @Override
311
+ public Iterator<String> iterator() {
312
+ return valueIterator();
313
+ }
314
+ };
315
+ }
316
+
317
+
318
+ public Iterator<String> valueIterator() {
319
+ return new Iterator<String>() {
320
+ int index = -1;
417
321
 
418
- public String removeIndex(int index) {
419
- if (index < 0 || index >= count) {
420
- throw new ArrayIndexOutOfBoundsException(index);
421
- }
422
- //System.out.println("index is " + which + " and " + keys[which]);
423
- String key = keys[index];
424
- indices.remove(key);
425
- for (int i = index; i < count - 1; i++) {
426
- keys[i] = keys[i + 1];
427
- values[i] = values[i + 1];
428
- indices.put(keys[i], i);
429
- }
430
- count--;
431
- keys[count] = null;
432
- values[count] = null;
433
- return key;
434
- }
322
+ public void remove() {
323
+ removeIndex(index);
324
+ index--;
325
+ }
435
326
 
436
- public void swap(int a, int b) {
437
- String tkey = keys[a];
438
- String tvalue = values[a];
439
- keys[a] = keys[b];
440
- values[a] = values[b];
441
- keys[b] = tkey;
442
- values[b] = tvalue;
327
+ public String next() {
328
+ return value(++index);
329
+ }
330
+
331
+ public boolean hasNext() {
332
+ return index+1 < size();
333
+ }
334
+ };
335
+ }
336
+
337
+
338
+ /**
339
+ * Create a new array and copy each of the values into it.
340
+ *
341
+ * @webref stringdict:method
342
+ * @brief Create a new array and copy each of the values into it
343
+ */
344
+ public String[] valueArray() {
345
+ crop();
346
+ return valueArray(null);
347
+ }
348
+
349
+
350
+ /**
351
+ * Fill an already-allocated array with the values (more efficient than
352
+ * creating a new array each time). If 'array' is null, or not the same
353
+ * size as the number of values, a new array will be allocated and returned.
354
+ */
355
+ public String[] valueArray(String[] array) {
356
+ if (array == null || array.length != size()) {
357
+ array = new String[count];
358
+ }
359
+ System.arraycopy(values, 0, array, 0, count);
360
+ return array;
361
+ }
362
+
363
+
364
+ /**
365
+ * Return a value for the specified key.
366
+ *
367
+ * @webref stringdict:method
368
+ * @brief Return a value for the specified key
369
+ */
370
+ public String get(String key) {
371
+ int index = index(key);
372
+ if (index == -1) return null;
373
+ return values[index];
374
+ }
375
+
376
+
377
+ public String get(String key, String alternate) {
378
+ int index = index(key);
379
+ if (index == -1) return alternate;
380
+ return values[index];
381
+ }
382
+
383
+
384
+ /**
385
+ * @webref stringdict:method
386
+ * @brief Create a new key/value pair or change the value of one
387
+ */
388
+ public void set(String key, String value) {
389
+ int index = index(key);
390
+ if (index == -1) {
391
+ create(key, value);
392
+ } else {
393
+ values[index] = value;
394
+ }
395
+ }
396
+
397
+
398
+ public void setIndex(int index, String key, String value) {
399
+ if (index < 0 || index >= count) {
400
+ throw new ArrayIndexOutOfBoundsException(index);
401
+ }
402
+ keys[index] = key;
403
+ values[index] = value;
404
+ }
405
+
406
+
407
+ public int index(String what) {
408
+ Integer found = indices.get(what);
409
+ return (found == null) ? -1 : found.intValue();
410
+ }
411
+
412
+
413
+ /**
414
+ * @webref stringdict:method
415
+ * @brief Check if a key is a part of the data structure
416
+ */
417
+ public boolean hasKey(String key) {
418
+ return index(key) != -1;
419
+ }
420
+
421
+
422
+ protected void create(String key, String value) {
423
+ if (count == keys.length) {
424
+ keys = PApplet.expand(keys);
425
+ values = PApplet.expand(values);
426
+ }
427
+ indices.put(key, Integer.valueOf(count));
428
+ keys[count] = key;
429
+ values[count] = value;
430
+ count++;
431
+ }
432
+
433
+ /**
434
+ * @webref stringdict:method
435
+ * @brief Remove a key/value pair
436
+ */
437
+ public String remove(String key) {
438
+ int index = index(key);
439
+ if (index == -1) {
440
+ throw new NoSuchElementException("'" + key + "' not found");
441
+ }
442
+ String value = values[index];
443
+ removeIndex(index);
444
+ return value;
445
+ }
446
+
447
+
448
+ public String removeIndex(int index) {
449
+ if (index < 0 || index >= count) {
450
+ throw new ArrayIndexOutOfBoundsException(index);
451
+ }
452
+ String value = values[index];
453
+ indices.remove(keys[index]);
454
+ for (int i = index; i < count-1; i++) {
455
+ keys[i] = keys[i+1];
456
+ values[i] = values[i+1];
457
+ indices.put(keys[i], i);
458
+ }
459
+ count--;
460
+ keys[count] = null;
461
+ values[count] = null;
462
+ return value;
463
+ }
464
+
465
+
466
+
467
+ public void swap(int a, int b) {
468
+ String tkey = keys[a];
469
+ String tvalue = values[a];
470
+ keys[a] = keys[b];
471
+ values[a] = values[b];
472
+ keys[b] = tkey;
473
+ values[b] = tvalue;
443
474
 
444
475
  // indices.put(keys[a], Integer.valueOf(a));
445
476
  // indices.put(keys[b], Integer.valueOf(b));
446
- }
477
+ }
478
+
479
+
480
+ /**
481
+ * Sort the keys alphabetically (ignoring case). Uses the value as a
482
+ * tie-breaker (only really possible with a key that has a case change).
483
+ *
484
+ * @webref stringdict:method
485
+ * @brief Sort the keys alphabetically
486
+ */
487
+ public void sortKeys() {
488
+ sortImpl(true, false);
489
+ }
490
+
491
+ /**
492
+ * @webref stringdict:method
493
+ * @brief Sort the keys alphabetically in reverse
494
+ */
495
+ public void sortKeysReverse() {
496
+ sortImpl(true, true);
497
+ }
498
+
499
+
500
+ /**
501
+ * Sort by values in descending order (largest value will be at [0]).
502
+ *
503
+ * @webref stringdict:method
504
+ * @brief Sort by values in ascending order
505
+ */
506
+ public void sortValues() {
507
+ sortImpl(false, false);
508
+ }
509
+
510
+
511
+ /**
512
+ * @webref stringdict:method
513
+ * @brief Sort by values in descending order
514
+ */
515
+ public void sortValuesReverse() {
516
+ sortImpl(false, true);
517
+ }
518
+
519
+
520
+ protected void sortImpl(final boolean useKeys, final boolean reverse) {
521
+ Sort s = new Sort() {
522
+ @Override
523
+ public int size() {
524
+ return count;
525
+ }
526
+
527
+ @Override
528
+ public int compare(int a, int b) {
529
+ int diff = 0;
530
+ if (useKeys) {
531
+ diff = keys[a].compareToIgnoreCase(keys[b]);
532
+ if (diff == 0) {
533
+ diff = values[a].compareToIgnoreCase(values[b]);
534
+ }
535
+ } else { // sort values
536
+ diff = values[a].compareToIgnoreCase(values[b]);
537
+ if (diff == 0) {
538
+ diff = keys[a].compareToIgnoreCase(keys[b]);
539
+ }
540
+ }
541
+ return reverse ? -diff : diff;
542
+ }
447
543
 
448
- /**
449
- * Sort the keys alphabetically (ignoring case). Uses the value as a
450
- * tie-breaker (only really possible with a key that has a case change).
451
- *
452
- * @webref stringdict:method
453
- * @brief Sort the keys alphabetically
454
- */
455
- public void sortKeys() {
456
- sortImpl(true, false);
457
- }
544
+ @Override
545
+ public void swap(int a, int b) {
546
+ StringDict.this.swap(a, b);
547
+ }
548
+ };
549
+ s.run();
458
550
 
459
- /**
460
- * @webref stringdict:method
461
- * @brief Sort the keys alphabetically in reverse
462
- */
463
- public void sortKeysReverse() {
464
- sortImpl(true, true);
465
- }
551
+ // Set the indices after sort/swaps (performance fix 160411)
552
+ resetIndices();
553
+ }
466
554
 
467
- /**
468
- * Sort by values in descending order (largest value will be at [0]).
469
- *
470
- * @webref stringdict:method
471
- * @brief Sort by values in ascending order
472
- */
473
- public void sortValues() {
474
- sortImpl(false, false);
475
- }
476
555
 
477
- /**
478
- * @webref stringdict:method
479
- * @brief Sort by values in descending order
480
- */
481
- public void sortValuesReverse() {
482
- sortImpl(false, true);
556
+ /** Returns a duplicate copy of this object. */
557
+ public StringDict copy() {
558
+ StringDict outgoing = new StringDict(count);
559
+ System.arraycopy(keys, 0, outgoing.keys, 0, count);
560
+ System.arraycopy(values, 0, outgoing.values, 0, count);
561
+ for (int i = 0; i < count; i++) {
562
+ outgoing.indices.put(keys[i], i);
483
563
  }
564
+ outgoing.count = count;
565
+ return outgoing;
566
+ }
484
567
 
485
- protected void sortImpl(final boolean useKeys, final boolean reverse) {
486
- Sort s = new Sort() {
487
- @Override
488
- public int size() {
489
- return count;
490
- }
491
-
492
- @Override
493
- public int compare(int a, int b) {
494
- int diff = 0;
495
- if (useKeys) {
496
- diff = keys[a].compareToIgnoreCase(keys[b]);
497
- if (diff == 0) {
498
- diff = values[a].compareToIgnoreCase(values[b]);
499
- }
500
- } else { // sort values
501
- diff = values[a].compareToIgnoreCase(values[b]);
502
- if (diff == 0) {
503
- diff = keys[a].compareToIgnoreCase(keys[b]);
504
- }
505
- }
506
- return reverse ? -diff : diff;
507
- }
508
-
509
- @Override
510
- public void swap(int a, int b) {
511
- StringDict.this.swap(a, b);
512
- }
513
- };
514
- s.run();
515
-
516
- // Set the indices after sort/swaps (performance fix 160411)
517
- resetIndices();
518
- }
519
568
 
520
- /**
521
- * Returns a duplicate copy of this object.
522
- */
523
- public StringDict copy() {
524
- StringDict outgoing = new StringDict(count);
525
- System.arraycopy(keys, 0, outgoing.keys, 0, count);
526
- System.arraycopy(values, 0, outgoing.values, 0, count);
527
- for (int i = 0; i < count; i++) {
528
- outgoing.indices.put(keys[i], i);
529
- }
530
- outgoing.count = count;
531
- return outgoing;
569
+ public void print() {
570
+ for (int i = 0; i < size(); i++) {
571
+ System.out.println(keys[i] + " = " + values[i]);
532
572
  }
573
+ }
533
574
 
534
- public void print() {
535
- for (int i = 0; i < size(); i++) {
536
- System.out.println(keys[i] + " = " + values[i]);
537
- }
538
- }
539
575
 
540
- /**
541
- * Save tab-delimited entries to a file (TSV format, UTF-8 encoding)
542
- */
543
- public void save(File file) {
544
- PrintWriter writer = PApplet.createWriter(file);
545
- write(writer);
546
- writer.close();
547
- }
576
+ /**
577
+ * Save tab-delimited entries to a file (TSV format, UTF-8 encoding)
578
+ */
579
+ public void save(File file) {
580
+ PrintWriter writer = PApplet.createWriter(file);
581
+ write(writer);
582
+ writer.close();
583
+ }
548
584
 
549
- /**
550
- * Write tab-delimited entries to a PrintWriter
551
- */
552
- public void write(PrintWriter writer) {
553
- for (int i = 0; i < count; i++) {
554
- writer.println(keys[i] + "\t" + values[i]);
555
- }
556
- writer.flush();
557
- }
558
585
 
559
- /**
560
- * Return this dictionary as a String in JSON format.
561
- */
562
- public String toJSON() {
563
- StringList items = new StringList();
564
- for (int i = 0; i < count; i++) {
565
- items.append(JSONObject.quote(keys[i]) + ": " + JSONObject.quote(values[i]));
566
- }
567
- return "{ " + items.join(", ") + " }";
586
+ /**
587
+ * Write tab-delimited entries to a PrintWriter
588
+ */
589
+ public void write(PrintWriter writer) {
590
+ for (int i = 0; i < count; i++) {
591
+ writer.println(keys[i] + "\t" + values[i]);
568
592
  }
593
+ writer.flush();
594
+ }
595
+
569
596
 
570
- @Override
571
- public String toString() {
572
- return getClass().getSimpleName() + " size=" + size() + " " + toJSON();
597
+ /**
598
+ * Return this dictionary as a String in JSON format.
599
+ */
600
+ public String toJSON() {
601
+ StringList items = new StringList();
602
+ for (int i = 0; i < count; i++) {
603
+ items.append(JSONObject.quote(keys[i])+ ": " + JSONObject.quote(values[i]));
573
604
  }
605
+ return "{ " + items.join(", ") + " }";
606
+ }
607
+
608
+
609
+ @Override
610
+ public String toString() {
611
+ return getClass().getSimpleName() + " size=" + size() + " " + toJSON();
612
+ }
574
613
  }