├── .classpath
├── .gitattributes
├── .gitignore
├── .project
├── CHANGELOG.md
├── LICENSE_GPL.txt
├── README.md
├── config
├── DiscardedFields.txt
├── EnvDATA-variables.csv
└── RememberedHeaders.txt
├── lib
├── GLGraphics.jar
├── apple.jar
├── commons-lang3-3.11.jar
├── commons-math3-3.6.1.jar
├── core.jar
├── gicentreUtils.jar
├── gluegen-rt-natives-linux-aarch64.jar
├── gluegen-rt-natives-linux-amd64.jar
├── gluegen-rt-natives-linux-armv6.jar
├── gluegen-rt-natives-linux-armv6hf.jar
├── gluegen-rt-natives-linux-i586.jar
├── gluegen-rt-natives-macosx-universal.jar
├── gluegen-rt-natives-solaris-amd64.jar
├── gluegen-rt-natives-solaris-i586.jar
├── gluegen-rt-natives-windows-amd64.jar
├── gluegen-rt-natives-windows-i586.jar
├── gluegen-rt.jar
├── jaretutil-0.32.jar
├── javafx-swt.jar
├── javafx.base.jar
├── javafx.controls.jar
├── javafx.fxml.jar
├── javafx.graphics.jar
├── javafx.media.jar
├── javafx.swing.jar
├── javafx.web.jar
├── jcodec-0.1.6.jar
├── joda-time-2.10.10.jar
├── jogl-all-natives-linux-aarch64.jar
├── jogl-all-natives-linux-amd64.jar
├── jogl-all-natives-linux-armv6.jar
├── jogl-all-natives-linux-armv6hf.jar
├── jogl-all-natives-linux-i586.jar
├── jogl-all-natives-macosx-universal.jar
├── jogl-all-natives-solaris-amd64.jar
├── jogl-all-natives-solaris-i586.jar
├── jogl-all-natives-windows-amd64.jar
├── jogl-all-natives-windows-i586.jar
├── jogl-all.jar
├── json4processing.jar
├── log4j-1.2.15.jar
├── miglayout-core-4.2.jar
├── miglayout-swing-4.2.jar
├── opencsv-5.3.jar
├── processing-core-3.5.4.jar
├── timebars-1.49.jar
└── unfolding.0.9.9.jar
├── public-data
├── Turkey-Vulture-Acopian-Center-USA-GPS-flagged-newUplift-Dec2013.csv
├── albatross-normal-tracks-9track-tailcrosswind-2020.csv
└── albatross-normal-tracks-9track-tailcrosswind.csv
├── repo-resources
├── animation.gif
├── banner.png
├── case-study1.gif
├── case-study2.gif
├── lines.gif
├── npp.gif
└── vec.gif
├── resources
├── logo1024.png
├── logo32.png
├── logo32e.png
└── move_ucsb.png
└── src
├── data
├── CustomCSVReader.java
├── CustomOutputStream.java
├── LoadDataToJTable.java
├── LoadDiscardFields.java
├── LoadEnvFieldsFromCSV.java
└── LoadKnownDataHeaders.java
├── gui
├── BaseMapPanel.java
├── CombinedControlPanel.java
├── ControlPanel.java
├── DataPanel.java
├── GradientEditor.java
├── LegendPanel.java
├── LinePanel.java
├── PointPanel.java
├── RangeSlider.java
├── RangeSliderUI.java
├── TimeLine.java
├── VectorPanel.java
└── WideComboBox.java
├── main
├── Colors.java
├── DesktopPane.java
├── Histo.java
├── Legend.java
├── Recorder.java
├── SequenceEncoder.java
├── Sketch.java
└── SketchData.java
└── utils
├── Attributes.java
├── Field.java
├── PointRecord.java
└── Track.java
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.csv filter=lfs diff=lfs merge=lfs -text
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Files and folders in .gitignore are not tracked by Git
2 |
3 | # Visual Studio/VS Code Files
4 | .vs/
5 | .vscode/
6 | *.code-workspace
7 |
8 | # Binaries
9 | /bin
10 |
11 | # Export location
12 | /export
13 |
14 | # Data directory
15 | /data
16 |
17 | # Remembered headers file
18 | /config/RememberedHeaders.txt
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | DynamoVis
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.jdt.core.javanature
16 |
17 |
18 |
19 | 1613644797210
20 |
21 | 30
22 |
23 | org.eclipse.core.resources.regexFilterMatcher
24 | node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # CHANGES
2 |
3 | ### Project Name: `DynamoVis`
4 |
5 | ##### `1.0.2` - 2023/10/27
6 | - Updating to work on Java 17, which is the latest Java version supported by Processing, as well as fixing some Mac specific issues. Tested on M1 Mac on macOS 14.0.
7 | - Processing issue which occurs on Mac with later updates was addressed (see https://github.com/benfry/processing4/issues/544).
8 | - Also removed unnecessary Mac specific fullscreen code, which sometimes causes issues with later Java versions.
9 |
10 | ##### `1.0.1` - 2023/05/25
11 | - Updated DesktopPane to call on java.awt.Taskbar module, which is supported by later versions of Java, rather than com.apple.eawt, which is no longer supported
12 |
13 | ##### `1.0` - 2021/08/01
14 | - Renamed MacOS menubar title to "DynamoVis"
15 | - Renamed "Configure Animation" to "Input Data and Animation Configuration"
16 | - Renamed Control Panel entry "Line Thickness" under Tracks to "Line Width"
17 | - Moved Control Panel field "Underlay" under "Tracks"
18 | - Public release as 1.0
19 |
20 | ##### 0.4.2.5 - 2021/05/24
21 | - Removed base encoding and framerate dropdowns from Recorder window
22 | - Unchecked 'Store frames' option in Recorder window only deletes the associated recording session's frames
23 | - Closing the Recorder window discards the recording and resets the time
24 |
25 | ##### 0.4.2.4 - 2021/05/12
26 | - Added help box back
27 | - Changed the maximum value of underlay opacity from 255 to 100 to make it more intuitive
28 |
29 | ##### 0.4.2.3 - 2021/04/23
30 | - Changing base map changes both left and right maps if we repeat the map display for edge cases
31 | - Date outlier filter now takes into account of the current year and filters dates 20 years out
32 |
33 | ##### 0.4.2.2 - 2021/04/10-12
34 | - "data" or "public-data" as the default data directories.
35 | - Higher resolution app icon for MacOS
36 | - Processing 4 libraries for MacOS integration
37 | - Fixed a bug when closing animation window freezes the app in MacOS
38 |
39 | ##### `0.4.2-alpha.1` - 2021/04/07
40 | - Empty fields in the dataset for latitude,longitude, and time skips the whole row
41 | - Empty fields in the dataset for additional fields are marked as NaN.
42 | - Changed maximum values for interval values in data configuration window to [1000, 59, 59] for [hours, minutes, seconds], respectively.
43 | - Legend improvements for poit and vector renderings.
44 | - Gradient picker is disabled when "Tag" field is selected.
45 | - Improved control panel rendering: arrows and labels, packing, glitches
46 | - JAR export finds resources.
47 | - Exported as .jar file for alpha release.
48 |
49 | ##### 0.4.2 - 2021/03/31
50 | - "New" menu item displays an appropriate text in the animation window.
51 | - Map repeats for dataset at the edge of the map.
52 | - Legend reacts correctly to repeating maps.
53 | - Smooth pan and zoom are disabled when map is repeated.
54 | - Cleaned unused source files
55 | - Added Move@ucsb logo to exported videos.
56 |
57 | ##### 0.4.1.7 - 2021/03/25
58 | - Control panel toggles won't resize the data config window.
59 | - Loading second data file does not cause a crash now.
60 | - Data config window gets disabled once we have an animation window running.
61 | - Refined legend in sketch rendering.
62 | - Cancelling the prompt window for essential header fields aborts data loading all together (including time formatting).
63 | - Prompt window for time formatting includes details.
64 | - Remembers the names of the required header fields and time formatting after asking one time. Its database is located in './config/RememberedHeaders.txt'
65 |
66 | ##### 0.4.1.6 - 2021/03/19
67 | - "New" from task bar minimizes sketch window only
68 | - OpenGl thread does not linger on exit
69 | - Moved icons to "resources" folder
70 | - Export location changed to "export" in the root folder
71 | - "Store frames" checkbox in the Record view to either keep or delete temporary frame data
72 | - Fixed the glitchy line rendering when two consecutive locations are too close
73 | - Fixed line thickness not applying to individual vertices
74 |
75 | ##### 0.4.1.5 - 2021/03/12
76 | - Data config pane has smaller minimum width
77 | - "Create Animation" button is disabled when a sketch is already running
78 | - Data configuration panel does not crash after animation is created multiple times
79 | - Timeline is visible again after the second animation is created
80 | - Resolved a bug where the data config panel was scaling right before creating an animation
81 | - Default window locations and sizes adjusted (reset locations)
82 | - No windows are spawned outside the screen with different animation resolutions
83 | - Disabled Cancel and Help buttons for now.
84 | - Legend edits (scale, tag text cropping and wrapping).
85 | - Removed "Edit/Data Config" menubar subitem.
86 | - Removed "Help" and "Dev" menubar items
87 | - Removed disfunctional base maps
88 |
89 | ##### 0.4.1.4 - 2021/03/11
90 | - Closing Processing sketch hides timeline and control panel
91 | - Exported videos now holds "Created by DynamoVis, MoveLab@UCSB, 2021" embedded in the upper right corner.
92 | - Removed month name from the legend and made copyright statement bigger.
93 | - Changed software icons to MOVELAB icon
94 | - Sketch runs with 60fps, rather than 30fps
95 |
96 | ##### 0.4.1.3 - 2021/03/04
97 | - Closing Procesing sketch doesn't close Java Application.
98 | - Fixed PSketch title and location. Timeline and control panel positions around the map sketch.
99 | - Export video is fixed.
100 |
101 | ##### 0.4.1.2 - 2021/02/25
102 | - Changed window hiearchy slightly. We are now running the main sketch as a separate window. Configure animation window stays open (its the main window now).
103 | - Processing 3 and JFrame does not work together. Rolling back the component integrations to start fixing barebones first.
104 | - Updated to Processing 3.5.4 and Unfolding 0.9.9beta
105 |
106 | ##### 0.4.1.1 - 2021/02/20
107 | - EnvDATA-variables.csv in Config reformatted as UTF-8
108 | - Merged all components from Kate, Nathan, and Pinki
109 |
110 | ##### 0.4.1.0 - 2021/02/10
111 | - Mert started working on integration of all releases
112 | - Project name changed to DynamoVis
113 | - Started running with **Java 15.0.2.7**
114 | - Upgraded libraries: commons-math3 3.3 to 3.6.1, joda-time 2.3 to 2.10.10, opencsv 2.3 to 5.3 (added commons-lang3 3.11 for opencsv 5.3)
115 |
116 | ### Project Name: `DYNAMO`
117 | ##### 0.4.0.4 - 2020/11/22
118 | - Pushed date outlier filter from 2020 to 2040
119 |
120 | ##### 0.4.0.3 - 2015/04/30
121 | - Fixed bug where end points of scale wouldn't appear when fields have aliases
122 |
123 | ##### 0.4.0.2 - 2015/01/25
124 | - Larger default legend
125 | - Points lying directly on the hour are now displayed at the correct time
126 |
127 | ##### 0.4.0.1 - 2014/11/26
128 | - New name
129 | - Minor bug fix
130 |
131 | ### Project Name: `mb_AnimationTool`
132 | ##### 0.4.0.0 - 2014/11/17
133 | - rewrite of backend to support future development and new modules
134 | - new PointRecord & Track and Field & Attributes classes
135 | - New track underlay option
136 |
137 | ##### 0.3.0.4 - 2014/09/30
138 | - New dataprocessing on data load, results shown in status box:
139 | - Tells user number of dates before 1800 and after 2020 ignored.
140 | - Warns of any dates before 1980 and after the current system date, but these are kept.
141 | - Tells user number of records marked as outliers (false in visible field)
142 | - Tells user number of records with bad coordinates (this and outliers were already discarded behind the scenes)
143 | - All timestamps are now properly parsed as UTC again.
144 | - Build animation button disabled when interval is 0
145 |
146 | ##### 0.3.0.2 - 2014/09/05
147 | - Changed appearance of color editor slightly
148 | - Couple minor fixes
149 |
150 | ##### 0.3.0.1 - 2014/08/22
151 | - Bug fixes
152 | - If interval is in seconds, the fade duration is set in minutes instead of hours
153 |
154 | ##### 0.3.0.0 - 2014/08/21
155 | - Individual tags can now be toggled on and off by using the checkboxes on the side of the timeline panel without rebuilding the animation.
156 | - Brushing is enabled. Click the tag's bar in the timeline panel to highlight its data on the map in cyan.
157 | - Timeline panel marker can now be used to seek (awkwardly... the marker is hard to grab, the animation doesn't pause while holding the marker, and if the animation is manually paused the time doesn't snap to the polling interval until it's unpaused again).
158 | - Separated out tracks/points/vectors: each have their own color and size range that can be set individually. The color ramp lists are shared.
159 | - New legends for point color/stroke and vector color/length
160 | - Legend layout can be saved and loaded
161 | - Data panel has quick rounding button for range values (nearest integer, down for min, up for max)
162 | - Data panel fields can be sorted
163 | - Switched to individual-local-identifier as default key
164 | - Holding shift while clicking load data button will force selection dialogs for key,long,lat,and timestamp.
165 | - Some ui changes
166 |
167 | ##### 0.2.4.0 - 2014/08/12
168 | - Overhauled color system. Big list of sequential and diverging color ramps to choose from, and you can assign a ramp to each field. Currently, these assignments are lost if you rebuild the animation.
169 | - Color ramps can be fully edited, saved, and loaded. Ramps can have as many stops as you want, and the editor was designed to work similar to the one in photoshop: click anywhere to make a new stop, drag it around to move, double click or click the color button to edit the stop color, and drag the stop down or click the delete button to remove it.
170 | - Timeline panel now updates marker during animation
171 | - Program now tries a few different timestamp formats before giving up and asking
172 | - Program can now handle different timestamp formats in the same dataset in the case where a user may have merged them from different sources.
173 | - Animation Interval can now be shorter than one minute
174 | - Timestamp on legend is shorter (will add ms again if/when we allow intervals to be that short)
175 |
176 | ##### 0.2.3.0 - 2014/08/05
177 | - Added basemap provider selections. Need jre 1.7+ to access google providers. Some providers won't load at extreme zooms (Bison data), but the program won't crash if this happens.
178 | - Auto-discarded fields moved to accessible file in config folder, letting user edit as necessary
179 | - Data fields with "user:" prefix are selected for the animation by default
180 | - Window locations are now saved between animations, reset layout button in menu enabled
181 | - Fixed recording panel breaking when animation is rebuilt
182 | - All prompts should now be centered over their parent
183 | - Removed some redundant calculations during animation building process
184 | - Intervals now round up to nearest whole minute
185 |
186 | ##### 0.2.2.0 - 2014/08/03
187 | - Quick fix to diverging color ramp calculation
188 | - Added progress monitors for data loading/processing
189 | - Implemented basic video export tool. Lets you start and stop recording, then save to an h.264 mp4. Haven't tested thoroughly, and temp files are not automatically deleted.
190 |
191 | ##### 0.2.1.1 - 2014/07/31
192 | - Minor bug fixes
193 | - List of auto discarded fields will now match to the older datasets
194 | - Datetime formatter prompt moved to a looping try catch block (it won't go away until it can successfully parse a datetime)
195 |
196 | ##### 0.2.1.0 - 2014/07/30
197 | - Rebuilt GUI again for compatability with mac's lightweight/heavyweight rendering issues
198 | - Excessive zooming at start is fixed
199 | - An "overview" timeline of the tags is created, will eventually have seeking/brushing interactivity
200 | - Color and legend editing panels implemented, but gradients are limited due to HSB color space and some wonky calculations
201 | - Min/max ranges for each field are editable in the data panel - need to add a quick rounding button
202 | - Rudimentary "point vectors" option added. This option is only available if the data has an obvious directional field (360 degrees with a bit of tolerance). Basic white lines are drawn from each data point with lengths scaled to another field. User interface for this needs to be improved, as well as more visual options.
203 |
204 | ##### 0.2.0.0 - 2014/07/13
205 | - Overhaul to data structure and gui
206 | - Reads raw Movebank CSV's: works with sets that have some bad data/coords
207 | - Data configuration panel implemented: lets user enable/disable/rename fields and filter tags
208 | - Program attempts to determine an appropriate time interval for the dataset (mode), but user can override.
209 | - Matches data fields from the big list of env-data fields, enables them by default, and pulls units and misc info
210 | + Some fields are discarded in preprocessing and won't be available: anything nominal especially
211 | - Sketch should start zoomed to the extent of data points (but doesn't always...)
212 | - A few options for animation size + custom res (must be done during new/edit)
213 | - Existing animation/data can be tweaked with edit menu (animation is then rebuilt)
214 | - Processing 2.2.1 Core
215 | - Unfolding 0.9.6
216 |
217 | ##### 0.1.3.0 - 2014/05/23
218 | - Rebuilding with EE 1.6
219 | - Latest JOGL libraries (previous ones were failing in OS X)
220 | - Some UI changes for OS X
221 |
222 | ##### 0.1.2.1 - 2014/05/21
223 | - Added button to swap datasets. If the csv isn't formatted properly it will probably fail super ungracefully
224 | - Changed tag id color symbology method to use an array so it will work for other data.
225 | - Commented up the source
226 |
227 | ##### 0.1.2.0 - 2014/05/20
228 | - Added class to parse CSV to an Unfolding Feature set. CSV needs longitude, latitude, timestamp, and tag_local_identifier, although we can make this more flexible
229 | - Works with a modified Turkey Vulture dataset, but not very well unless you cut down the number of birds to 1 or 2.
230 |
231 | ##### 0.1.1.0 - 2014/05/19
232 | - Finished removing all Galapagos stuff
233 | - Rebuilt the CP5 GUI in Swing, breaking backwards compatability with the Processing IDE
234 |
235 | ##### 0.1.0.0 - 2014/05/18
236 | - Removed most of the static GalapagosSketchTest code
237 | - Added field select dropdowns for each visual variable
238 | - Only has one color gradient + colors for tags
239 |
240 | --------
241 |
242 | # KNOWN ISSUES
243 | - Malfunctioned data lines prevents loading the whole datafile (bisbing_mig.csv)
244 | - Barscale in legend becomes too long closer to poles
245 | - Occasional line between repeated maps on some zoom levels.
246 | - Timeline checkboxes does not react to Shift/Ctrl+click well.
247 |
248 | # TO-DO:
249 | - Pending library upgrades
250 | - miglayout 4.2 (5.0 available)
251 | - log4j 1.2.15 (2.14.1 available but Unfolding Maps uses 1.2.15)
252 | - jcodec 0.1.6 (0.2.5 available but drastically changes the encoding method)
253 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DynamoVis
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 | **DynamoVis** is a data visualization software specifically targeted for spatiotemporal movement data. It is developed by [Move Lab @ UC Santa Barbara](https://move.geog.ucsb.edu/) and designed to be accessible and easily usable for scientists without extensive prior experience with programming, GIS software, or custom data visualization tools. The intuitive design focuses on a simple interface for scientists to apply spatial data visualization techniques, giving ecologists and biologists of all backgrounds the power to visualize complicated spatial patterns.
12 |
13 | > Dodge, S., Toka, M. & Bae, C.J. DynamoVis 1.0: an exploratory data visualization software for mapping movement in relation to internal and external factors. Mov Ecol 9, 55 (2021). https://doi.org/10.1186/s40462-021-00291-5
14 |
15 |
16 |
17 |
18 |
19 |
20 | - An animation of the user interface using Galapagos Albatross movement data with various basemaps and visualization parameters.
21 |
22 |
23 | ## Dynamovis Web
24 | **Dynamovis Web** is now available in Beta version. Please visit Dynamovis Web here : https://dynamovis.geog.ucsb.edu/
25 |
26 | ## Usage Dynamovis Desktop
27 | 0. Make sure to have [Java 17 installed](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html) and set up in your system or user PATH.
28 | - To check Java version, start Terminal and type `java -version`. The version listed should be 17.
29 | 2. Download the latest release (`DynamoVis-1.0.2.zip`) [here](https://github.com/move-ucsb/DynamoVis/releases).
30 | 3. Unzip the folder anywhere on your machine.
31 | 4. Double-click on `DynamoVis.jar`
32 | - If this doesn't do anything:
33 | - (Windows) Double-click on `run_windows.bat`
34 | - (macOS) Start Terminal, type `cd ` (with a white space). Drag and drop the DynamoVis folder on the terminal window and press enter. Type `./run_unix.sh` or `bash run_unix.sh`and press enter.
35 |
36 | 5. If your system shows a security pop up from an unidentified developer, it is safe to ignore it.
37 | - (Windows) On the security pop up `More info -> Run anyway`.
38 | - (macOS) Click `OK` on the security pop up to close it. Then go into your `System Preferences > Security & Privacy` and then click `Open Anyway` next to the message that `DynamoVis.jar` was blocked.
39 |
40 | 6. The DynamoVis software will open with the initial _Input Data and Animation Configuration_ and _Status_ windows.
41 |
42 |
43 | Alternatively, you can also run the jar file from Terminal using below command in extracted folder:
44 |
45 | ```shell
46 | java -jar DynamoVis.jar
47 | ```
48 |
49 | See 'Compile from source' section below for notes on compiling the software from scratch.
50 |
51 | ## Use cases
52 | ### Turkey vulture [data set](https://doi.org/10.5441/001/1.46ft1k05)
53 |
54 |
55 | - An exported animation of the turkey vulture Leo on Microsoft Aerial basemap. It shows the foraging behavior of Leo -- moving slowly or pausing in high-vegetation areas (NDVI), shown with bright green circles.
56 |
57 |
58 |
59 |
60 | - Another exported track animation of turkey vulture Leo displayed on Esri World Terrain basemap. The thicker purple line visualizes thermal uplift that aids the bird to move faster. The thin underlay lines shows the prior movement of Leo, hinting its commonly-travelled routes
61 |
62 |
63 |
64 |
65 | ### Galapagos albatrosses [data set](https://doi.org/10.5441/001/1.3hp3s250)
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | - An set of exported animations of one Galapagos albatross track (4264-84830852) displayed on Esri World Terrain basemap, illustrating the relationship between the movement speed and wind support. The left visualization highlights the use of higher tail-wind support (shown in blue color) for faster outbound flights (shown with thicker lines), and the right map shows the actual wind direction using vectors of variable size.
76 |
77 |
78 |
79 |
80 | - Another animation of the albatross (4264-84830852) displayed on the Microsoft Aerial basemap. The visualization highlights the relationship between net primary production (NPP) of the ocean and albatross movement speed. The albatross appears to move slowly (smaller point size) or make frequent stops along the coast of Peru to forage in high NPP areas (shown in darker green colors). The bird appears to fly faster (larger point size) during the flights over the ocean and around the Galapagos where ocean NPP is lower (lighter green colors).
81 |
82 |
83 |
84 | ## Config
85 | `./config/` directory stores extra files that are useful for the use case of the software.
86 |
87 | - `RememberedHeaders.txt` stores the names of the required fields for DynamoVis to function properly. Upon loading data to the software, the header names of the *unique identifier, latitiude, longitude* and *timestamp* will be recorded in this file for future reference. Successive loading of the same file will use information recorded in this file.
88 |
89 | - `EnvDATA-variables.csv` keeps the details of known fields, commonly used by [EnvData system](https://www.movebank.org/cms/movebank-content/env-data).
90 |
91 | - `DiscardedFields.txt` hold a list of columns (or fields) in the data that is discarded by DynamoVis. Feel free to add more fields in your local copy to prevent loading unnecessary fields to your animations.
92 |
93 | - `./color/` and `./legend/` folders keeps a copy of the custom color ramps and legend layouts.
94 |
95 | ## BibTex
96 |
97 | ```
98 | @article{dodge2021dynamovis,
99 | title={DynamoVis 1.0: an exploratory data visualization software for mapping movement in relation to internal and external factors},
100 | author={Dodge, Somayeh and Toka, Mert and Bae, Crystal J},
101 | journal={Movement Ecology},
102 | volume={9},
103 | number={1},
104 | pages={1--17},
105 | year={2021},
106 | publisher={Springer}
107 | }
108 | ```
109 |
110 | ## Data
111 | We distribute copies of Galapagos Albatrosses and Turkey Vultures data sets along with the repository in `./public-data` directory.
112 |
113 | ## Project Sponsor
114 |
119 |
120 | ## Contact
121 | Feel free to open an [issue](https://github.com/move-ucsb/DynamoVis/issues) in case something is wrong. Please make sure to note the description of the issue and your computer specifications (operating system, java version, error messages, etc.).
122 |
123 | ## Compile from source
124 | If you'd like to clone the repository and compile from the source, make sure to have [Git Large File System](https://git-lfs.github.com/) installed and enabled. Git-LFS is required for large `*.csv` files. If you don't want to install Git-LFS, you will need to clone the repository and manually download .csv files in `/config` and `/public-data`.
125 |
126 | ## Tested on:
127 | - Windows 10
128 | - Windows 11
129 | - macOS 10.14.6 Mojave
130 | - macOS 10.15 Catalina
131 |
132 | w/ Java 15.0.2
133 |
134 | ## List of developers
135 | - Jenni Hutson
136 | - Mert Toka
137 | - Glenn Xavier
138 | - Wing Yi (Pinki) Wong
139 | - Kate Carlson
140 | - Kin (Nathan) Chan
141 |
--------------------------------------------------------------------------------
/config/DiscardedFields.txt:
--------------------------------------------------------------------------------
1 | individualtaxoncanonicalname
2 | taglocalidentifier
3 | studyname
4 | locationlat
5 | locationlong
6 | utmeasting
7 | utmnorthing
8 | utmzone
9 | timestamp
10 | studytimezone
11 | studylocaltimestamp
12 | visible
13 | behaviouralclassification
14 | comments
15 | eventid
16 | sensortype
17 | eobsbatteryvoltage
18 | eobsfixbatteryvoltage
19 | eobshorizontalaccuracyestimate
20 | eobsspeedaccuracyestimate
21 | eobsstarttimestamp
22 | eobsstatus
23 | eobstypeoffix
24 | eobsusedtimetogetfix
25 | eobskeybinchecksum
--------------------------------------------------------------------------------
/config/EnvDATA-variables.csv:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:0fdb89b4dfacdafe412cb6c997252ae63a03f553c4964d2a859413cb1932e382
3 | size 191292
4 |
--------------------------------------------------------------------------------
/config/RememberedHeaders.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/config/RememberedHeaders.txt
--------------------------------------------------------------------------------
/lib/GLGraphics.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/GLGraphics.jar
--------------------------------------------------------------------------------
/lib/apple.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/apple.jar
--------------------------------------------------------------------------------
/lib/commons-lang3-3.11.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/commons-lang3-3.11.jar
--------------------------------------------------------------------------------
/lib/commons-math3-3.6.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/commons-math3-3.6.1.jar
--------------------------------------------------------------------------------
/lib/core.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/core.jar
--------------------------------------------------------------------------------
/lib/gicentreUtils.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/gicentreUtils.jar
--------------------------------------------------------------------------------
/lib/gluegen-rt-natives-linux-aarch64.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/gluegen-rt-natives-linux-aarch64.jar
--------------------------------------------------------------------------------
/lib/gluegen-rt-natives-linux-amd64.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/gluegen-rt-natives-linux-amd64.jar
--------------------------------------------------------------------------------
/lib/gluegen-rt-natives-linux-armv6.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/gluegen-rt-natives-linux-armv6.jar
--------------------------------------------------------------------------------
/lib/gluegen-rt-natives-linux-armv6hf.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/gluegen-rt-natives-linux-armv6hf.jar
--------------------------------------------------------------------------------
/lib/gluegen-rt-natives-linux-i586.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/gluegen-rt-natives-linux-i586.jar
--------------------------------------------------------------------------------
/lib/gluegen-rt-natives-macosx-universal.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/gluegen-rt-natives-macosx-universal.jar
--------------------------------------------------------------------------------
/lib/gluegen-rt-natives-solaris-amd64.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/gluegen-rt-natives-solaris-amd64.jar
--------------------------------------------------------------------------------
/lib/gluegen-rt-natives-solaris-i586.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/gluegen-rt-natives-solaris-i586.jar
--------------------------------------------------------------------------------
/lib/gluegen-rt-natives-windows-amd64.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/gluegen-rt-natives-windows-amd64.jar
--------------------------------------------------------------------------------
/lib/gluegen-rt-natives-windows-i586.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/gluegen-rt-natives-windows-i586.jar
--------------------------------------------------------------------------------
/lib/gluegen-rt.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/gluegen-rt.jar
--------------------------------------------------------------------------------
/lib/jaretutil-0.32.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/jaretutil-0.32.jar
--------------------------------------------------------------------------------
/lib/javafx-swt.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/javafx-swt.jar
--------------------------------------------------------------------------------
/lib/javafx.base.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/javafx.base.jar
--------------------------------------------------------------------------------
/lib/javafx.controls.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/javafx.controls.jar
--------------------------------------------------------------------------------
/lib/javafx.fxml.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/javafx.fxml.jar
--------------------------------------------------------------------------------
/lib/javafx.graphics.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/javafx.graphics.jar
--------------------------------------------------------------------------------
/lib/javafx.media.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/javafx.media.jar
--------------------------------------------------------------------------------
/lib/javafx.swing.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/javafx.swing.jar
--------------------------------------------------------------------------------
/lib/javafx.web.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/javafx.web.jar
--------------------------------------------------------------------------------
/lib/jcodec-0.1.6.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/jcodec-0.1.6.jar
--------------------------------------------------------------------------------
/lib/joda-time-2.10.10.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/joda-time-2.10.10.jar
--------------------------------------------------------------------------------
/lib/jogl-all-natives-linux-aarch64.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/jogl-all-natives-linux-aarch64.jar
--------------------------------------------------------------------------------
/lib/jogl-all-natives-linux-amd64.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/jogl-all-natives-linux-amd64.jar
--------------------------------------------------------------------------------
/lib/jogl-all-natives-linux-armv6.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/jogl-all-natives-linux-armv6.jar
--------------------------------------------------------------------------------
/lib/jogl-all-natives-linux-armv6hf.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/jogl-all-natives-linux-armv6hf.jar
--------------------------------------------------------------------------------
/lib/jogl-all-natives-linux-i586.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/jogl-all-natives-linux-i586.jar
--------------------------------------------------------------------------------
/lib/jogl-all-natives-macosx-universal.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/jogl-all-natives-macosx-universal.jar
--------------------------------------------------------------------------------
/lib/jogl-all-natives-solaris-amd64.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/jogl-all-natives-solaris-amd64.jar
--------------------------------------------------------------------------------
/lib/jogl-all-natives-solaris-i586.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/jogl-all-natives-solaris-i586.jar
--------------------------------------------------------------------------------
/lib/jogl-all-natives-windows-amd64.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/jogl-all-natives-windows-amd64.jar
--------------------------------------------------------------------------------
/lib/jogl-all-natives-windows-i586.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/jogl-all-natives-windows-i586.jar
--------------------------------------------------------------------------------
/lib/jogl-all.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/jogl-all.jar
--------------------------------------------------------------------------------
/lib/json4processing.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/json4processing.jar
--------------------------------------------------------------------------------
/lib/log4j-1.2.15.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/log4j-1.2.15.jar
--------------------------------------------------------------------------------
/lib/miglayout-core-4.2.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/miglayout-core-4.2.jar
--------------------------------------------------------------------------------
/lib/miglayout-swing-4.2.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/miglayout-swing-4.2.jar
--------------------------------------------------------------------------------
/lib/opencsv-5.3.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/opencsv-5.3.jar
--------------------------------------------------------------------------------
/lib/processing-core-3.5.4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/processing-core-3.5.4.jar
--------------------------------------------------------------------------------
/lib/timebars-1.49.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/timebars-1.49.jar
--------------------------------------------------------------------------------
/lib/unfolding.0.9.9.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/lib/unfolding.0.9.9.jar
--------------------------------------------------------------------------------
/public-data/Turkey-Vulture-Acopian-Center-USA-GPS-flagged-newUplift-Dec2013.csv:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:bfec44563f08a66ed1edfb34dd84b546c1b9a01cc2b40ee9d072ddf54e90f32c
3 | size 50222554
4 |
--------------------------------------------------------------------------------
/public-data/albatross-normal-tracks-9track-tailcrosswind-2020.csv:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:8c2b3212d7f6c2df4111962a6b10152ccdb97436a5238dc5b007af03ce2cc281
3 | size 3539206
4 |
--------------------------------------------------------------------------------
/public-data/albatross-normal-tracks-9track-tailcrosswind.csv:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:4ffa9775950dcdae52948f5753881a367b13f2108da5209ce2b5ec7fefdd7747
3 | size 3649332
4 |
--------------------------------------------------------------------------------
/repo-resources/animation.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/repo-resources/animation.gif
--------------------------------------------------------------------------------
/repo-resources/banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/repo-resources/banner.png
--------------------------------------------------------------------------------
/repo-resources/case-study1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/repo-resources/case-study1.gif
--------------------------------------------------------------------------------
/repo-resources/case-study2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/repo-resources/case-study2.gif
--------------------------------------------------------------------------------
/repo-resources/lines.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/repo-resources/lines.gif
--------------------------------------------------------------------------------
/repo-resources/npp.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/repo-resources/npp.gif
--------------------------------------------------------------------------------
/repo-resources/vec.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/repo-resources/vec.gif
--------------------------------------------------------------------------------
/resources/logo1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/resources/logo1024.png
--------------------------------------------------------------------------------
/resources/logo32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/resources/logo32.png
--------------------------------------------------------------------------------
/resources/logo32e.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/resources/logo32e.png
--------------------------------------------------------------------------------
/resources/move_ucsb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/move-ucsb/DynamoVis/0996309447a14b82d0321e2e7c3c41083299d631/resources/move_ucsb.png
--------------------------------------------------------------------------------
/src/data/CustomCSVReader.java:
--------------------------------------------------------------------------------
1 | package data;
2 |
3 | /**
4 | Copyright 2005 Bytecode Pty Ltd.
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 | */
18 |
19 | import java.io.BufferedReader;
20 | import java.io.Closeable;
21 | import java.io.IOException;
22 | import java.io.Reader;
23 | import java.util.ArrayList;
24 | import java.util.List;
25 |
26 | import com.opencsv.CSVParser;
27 | import com.opencsv.CSVParserBuilder;
28 | import com.opencsv.enums.CSVReaderNullFieldIndicator;
29 |
30 | /**
31 | * A very simple CSV reader released under a commercial-friendly license.
32 | *
33 | * @author Glen Smith
34 | *
35 | */
36 |
37 | // Added a count to hook for progress monitor
38 |
39 | public class CustomCSVReader implements Closeable {
40 |
41 | private BufferedReader br;
42 |
43 | private boolean hasNext = true;
44 |
45 | private CSVParser parser;
46 |
47 | private int skipLines;
48 |
49 | private boolean linesSkiped;
50 |
51 | public long readSoFar;
52 |
53 | /**
54 | * The default line to start reading.
55 | */
56 | public static final int DEFAULT_SKIP_LINES = 0;
57 |
58 | /**
59 | * Constructs CSVReader using a comma for the separator.
60 | *
61 | * @param reader the reader to an underlying CSV source.
62 | */
63 | public CustomCSVReader(Reader reader) {
64 | this(reader, CSVParser.DEFAULT_SEPARATOR, CSVParser.DEFAULT_QUOTE_CHARACTER,
65 | CSVParser.DEFAULT_ESCAPE_CHARACTER);
66 | }
67 |
68 | /**
69 | * Constructs CSVReader with supplied separator.
70 | *
71 | * @param reader the reader to an underlying CSV source.
72 | * @param separator the delimiter to use for separating entries.
73 | */
74 | public CustomCSVReader(Reader reader, char separator) {
75 | this(reader, separator, CSVParser.DEFAULT_QUOTE_CHARACTER, CSVParser.DEFAULT_ESCAPE_CHARACTER);
76 | }
77 |
78 | /**
79 | * Constructs CSVReader with supplied separator and quote char.
80 | *
81 | * @param reader the reader to an underlying CSV source.
82 | * @param separator the delimiter to use for separating entries
83 | * @param quotechar the character to use for quoted elements
84 | */
85 | public CustomCSVReader(Reader reader, char separator, char quotechar) {
86 | this(reader, separator, quotechar, CSVParser.DEFAULT_ESCAPE_CHARACTER, DEFAULT_SKIP_LINES,
87 | CSVParser.DEFAULT_STRICT_QUOTES);
88 | }
89 |
90 | /**
91 | * Constructs CSVReader with supplied separator, quote char and quote handling
92 | * behavior.
93 | *
94 | * @param reader the reader to an underlying CSV source.
95 | * @param separator the delimiter to use for separating entries
96 | * @param quotechar the character to use for quoted elements
97 | * @param strictQuotes sets if characters outside the quotes are ignored
98 | */
99 | public CustomCSVReader(Reader reader, char separator, char quotechar, boolean strictQuotes) {
100 | this(reader, separator, quotechar, CSVParser.DEFAULT_ESCAPE_CHARACTER, DEFAULT_SKIP_LINES, strictQuotes);
101 | }
102 |
103 | /**
104 | * Constructs CSVReader with supplied separator and quote char.
105 | *
106 | * @param reader the reader to an underlying CSV source.
107 | * @param separator the delimiter to use for separating entries
108 | * @param quotechar the character to use for quoted elements
109 | * @param escape the character to use for escaping a separator or quote
110 | */
111 |
112 | public CustomCSVReader(Reader reader, char separator, char quotechar, char escape) {
113 | this(reader, separator, quotechar, escape, DEFAULT_SKIP_LINES, CSVParser.DEFAULT_STRICT_QUOTES);
114 | }
115 |
116 | /**
117 | * Constructs CSVReader with supplied separator and quote char.
118 | *
119 | * @param reader the reader to an underlying CSV source.
120 | * @param separator the delimiter to use for separating entries
121 | * @param quotechar the character to use for quoted elements
122 | * @param line the line number to skip for start reading
123 | */
124 | public CustomCSVReader(Reader reader, char separator, char quotechar, int line) {
125 | this(reader, separator, quotechar, CSVParser.DEFAULT_ESCAPE_CHARACTER, line, CSVParser.DEFAULT_STRICT_QUOTES);
126 | }
127 |
128 | /**
129 | * Constructs CSVReader with supplied separator and quote char.
130 | *
131 | * @param reader the reader to an underlying CSV source.
132 | * @param separator the delimiter to use for separating entries
133 | * @param quotechar the character to use for quoted elements
134 | * @param escape the character to use for escaping a separator or quote
135 | * @param line the line number to skip for start reading
136 | */
137 | public CustomCSVReader(Reader reader, char separator, char quotechar, char escape, int line) {
138 | this(reader, separator, quotechar, escape, line, CSVParser.DEFAULT_STRICT_QUOTES);
139 | }
140 |
141 | /**
142 | * Constructs CSVReader with supplied separator and quote char.
143 | *
144 | * @param reader the reader to an underlying CSV source.
145 | * @param separator the delimiter to use for separating entries
146 | * @param quotechar the character to use for quoted elements
147 | * @param escape the character to use for escaping a separator or quote
148 | * @param line the line number to skip for start reading
149 | * @param strictQuotes sets if characters outside the quotes are ignored
150 | */
151 | public CustomCSVReader(Reader reader, char separator, char quotechar, char escape, int line, boolean strictQuotes) {
152 | this(reader, separator, quotechar, escape, line, strictQuotes, CSVParser.DEFAULT_IGNORE_LEADING_WHITESPACE);
153 | }
154 |
155 | /**
156 | * Constructs CSVReader with supplied separator and quote char.
157 | *
158 | * @param reader the reader to an underlying CSV source.
159 | * @param separator the delimiter to use for separating entries
160 | * @param quotechar the character to use for quoted elements
161 | * @param escape the character to use for escaping a separator
162 | * or quote
163 | * @param line the line number to skip for start reading
164 | * @param strictQuotes sets if characters outside the quotes are
165 | * ignored
166 | * @param ignoreLeadingWhiteSpace it true, parser should ignore white space
167 | * before a quote in a field
168 | */
169 | public CustomCSVReader(Reader reader, char separator, char quotechar, char escape, int line, boolean strictQuotes,
170 | boolean ignoreLeadingWhiteSpace) {
171 | this.br = new BufferedReader(reader);
172 | this.parser = new CSVParserBuilder().withSeparator(separator).withQuoteChar(quotechar).withEscapeChar(escape)
173 | .withStrictQuotes(strictQuotes).withIgnoreLeadingWhiteSpace(ignoreLeadingWhiteSpace)
174 | .withFieldAsNull(CSVReaderNullFieldIndicator.EMPTY_SEPARATORS).build();
175 | // separator, quotechar, escape, strictQuotes, ignoreLeadingWhiteSpace);
176 | this.skipLines = line;
177 | this.readSoFar = 0;
178 |
179 | }
180 |
181 | /**
182 | * Reads the entire file into a List with each element being a String[] of
183 | * tokens.
184 | *
185 | * @return a List of String[], with each String[] representing a line of the
186 | * file.
187 | *
188 | * @throws IOException if bad things happen during the read
189 | */
190 | public List readAll() throws IOException {
191 |
192 | List allElements = new ArrayList();
193 | while (hasNext) {
194 | String[] nextLineAsTokens = readNext();
195 | if (nextLineAsTokens != null)
196 | allElements.add(nextLineAsTokens);
197 | }
198 | return allElements;
199 |
200 | }
201 |
202 | /**
203 | * Reads the next line from the buffer and converts to a string array.
204 | *
205 | * @return a string array with each comma-separated element as a separate entry.
206 | *
207 | * @throws IOException if bad things happen during the read
208 | */
209 | public String[] readNext() throws IOException {
210 |
211 | String[] result = null;
212 | do {
213 | String nextLine = getNextLine();
214 | if (!hasNext) {
215 | return result; // should throw if still pending?
216 | }
217 | String[] r = parser.parseLineMulti(nextLine);
218 | if (r.length > 0) {
219 | if (result == null) {
220 | result = r;
221 | } else {
222 | String[] t = new String[result.length + r.length];
223 | System.arraycopy(result, 0, t, 0, result.length);
224 | System.arraycopy(r, 0, t, result.length, r.length);
225 | result = t;
226 | }
227 | }
228 | } while (parser.isPending());
229 | return result;
230 | }
231 |
232 | /**
233 | * Reads the next line from the file.
234 | *
235 | * @return the next line from the file without trailing newline
236 | * @throws IOException if bad things happen during the read
237 | */
238 | private String getNextLine() throws IOException {
239 | if (!this.linesSkiped) {
240 | for (int i = 0; i < skipLines; i++) {
241 | br.readLine();
242 | }
243 | this.linesSkiped = true;
244 | }
245 | String nextLine = br.readLine();
246 | if (nextLine == null) {
247 | hasNext = false;
248 | } else {
249 | readSoFar += nextLine.length() + 1;
250 | }
251 | return hasNext ? nextLine : null;
252 | }
253 |
254 | /**
255 | * Closes the underlying reader.
256 | *
257 | * @throws IOException if the close fails
258 | */
259 | public void close() throws IOException {
260 | br.close();
261 | }
262 |
263 | }
264 |
--------------------------------------------------------------------------------
/src/data/CustomOutputStream.java:
--------------------------------------------------------------------------------
1 | package data;
2 |
3 | import java.io.IOException;
4 | import java.io.OutputStream;
5 |
6 | import javax.swing.JTextArea;
7 |
8 | public class CustomOutputStream extends OutputStream {
9 | private JTextArea textArea;
10 |
11 | public CustomOutputStream(JTextArea textArea) {
12 | this.textArea = textArea;
13 | }
14 |
15 | @Override
16 | public void write(int b) throws IOException {
17 | // redirects data to the text area
18 | textArea.append(String.valueOf((char) b));
19 | // scrolls the text area to the end of data
20 | textArea.setCaretPosition(textArea.getDocument().getLength());
21 | }
22 | }
--------------------------------------------------------------------------------
/src/data/LoadDiscardFields.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 |
22 | package data;
23 |
24 | import java.io.File;
25 | import java.io.FileNotFoundException;
26 | import java.io.FileReader;
27 | import java.io.IOException;
28 | import java.util.ArrayList;
29 | import java.util.List;
30 |
31 | public class LoadDiscardFields {
32 |
33 | public List loadData(String fileName) {
34 | List list = new ArrayList();
35 | CustomCSVReader reader = null;
36 | try {
37 | File file = new File(fileName);
38 | reader = new CustomCSVReader(new FileReader(file));
39 | } catch (FileNotFoundException e2) {
40 | e2.printStackTrace();
41 | }
42 |
43 | String row[];
44 | try {
45 | while ((row = reader.readNext()) != null) {
46 | list.add(row[0].replace(":", "").replace("-", "").replace(".", ""));
47 | }
48 | } catch (IOException e) {
49 | e.printStackTrace();
50 | }
51 |
52 | try {
53 | reader.close();
54 | } catch (IOException e) {
55 | e.printStackTrace();
56 | }
57 |
58 | return list;
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/data/LoadEnvFieldsFromCSV.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 |
22 | package data;
23 |
24 | import java.io.FileNotFoundException;
25 | import java.io.IOException;
26 | import java.nio.charset.StandardCharsets;
27 | import java.nio.file.Files;
28 | import java.nio.file.Path;
29 | import java.nio.file.Paths;
30 | import java.util.ArrayList;
31 |
32 | import com.opencsv.CSVParser;
33 | import com.opencsv.CSVReader;
34 | import com.opencsv.CSVReaderBuilder;
35 | import com.opencsv.exceptions.CsvValidationException;
36 |
37 |
38 | public class LoadEnvFieldsFromCSV {
39 |
40 | public ArrayList> loadData(String fileName) {
41 | ArrayList> data = new ArrayList>();
42 |
43 | CSVReader reader = null;
44 | try {
45 | Path path = Paths.get(fileName);
46 | reader = new CSVReaderBuilder(Files.newBufferedReader(path, StandardCharsets.UTF_8)).withCSVParser(new CSVParser()).build();
47 | } catch (FileNotFoundException e2) {
48 | e2.printStackTrace();
49 | } catch (IOException e) {
50 | e.printStackTrace();
51 | }
52 | String[] header = null;
53 | try {
54 | header = reader.readNext();
55 | } catch (IOException e1) {
56 | e1.printStackTrace();
57 | } catch (CsvValidationException e) {
58 | e.printStackTrace();
59 | }
60 | if (header == null) {
61 | throw new RuntimeException("No header");
62 | }
63 |
64 | String[] row;
65 | // int i = 0;
66 | try {
67 | while ((row = reader.readNext()) != null) {
68 | // i++;
69 |
70 | String fieldFull = row[0] + " ";
71 | if (!row[1].equals("N/A")) {
72 | fieldFull = fieldFull + row[1] + " ";
73 | }
74 | fieldFull = fieldFull + row[2];
75 | String fieldShort = row[2];
76 | String units = row[3].replace("^-2", "\u00b2").replace("^-3", "\u00b3");
77 | ArrayList temp = new ArrayList();
78 | temp.add(fieldFull);
79 | temp.add(fieldShort);
80 | temp.add(units);
81 | data.add(temp);
82 | }
83 |
84 | } catch (IOException e) {
85 | e.printStackTrace();
86 | } catch (CsvValidationException e) {
87 | e.printStackTrace();
88 | }
89 | try {
90 | reader.close();
91 | } catch (IOException e) {
92 | e.printStackTrace();
93 | }
94 | return data;
95 |
96 | }
97 |
98 | }
99 |
--------------------------------------------------------------------------------
/src/data/LoadKnownDataHeaders.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 |
22 | package data;
23 |
24 | import java.io.BufferedWriter;
25 | import java.io.File;
26 | import java.io.FileNotFoundException;
27 | import java.io.FileReader;
28 | import java.io.FileWriter;
29 | import java.io.IOException;
30 | import java.io.Writer;
31 | import java.util.ArrayList;
32 | import java.util.List;
33 |
34 | public class LoadKnownDataHeaders {
35 | private String filename;
36 | private List list;
37 |
38 | public LoadKnownDataHeaders (String fn) {
39 | this.filename = fn;
40 | list = new ArrayList();
41 | loadData();
42 | }
43 |
44 | // read
45 | public boolean loadData() {
46 | CustomCSVReader reader = null;
47 | try {
48 | File file = new File(filename);
49 | reader = new CustomCSVReader(new FileReader(file));
50 | } catch (FileNotFoundException e2) {
51 | e2.printStackTrace();
52 | return false;
53 | }
54 |
55 | String row[];
56 | // HEADER
57 | // filename, fieldfortag, fieldforlong, fieldforlat, fieldfortime, timeformat
58 | // row[0], row[1], row[2], row[3], row[4], row[5]
59 | try {
60 | while ((row = reader.readNext()) != null) {
61 | list.add(new String[] { row[0], row[1], row[2], row[3], row[4], row[5] } );
62 | }
63 | } catch (IOException e) {
64 | e.printStackTrace();
65 | return false;
66 | }
67 |
68 | try {
69 | reader.close();
70 | return true;
71 | } catch (IOException e) {
72 | e.printStackTrace();
73 | return false;
74 | }
75 | }
76 |
77 | // check
78 | public String[] queryFilename(String fname) {
79 | // see if it already exists
80 | for (String[] strings : list) {
81 | if(fname.equals(strings[0])) return strings;
82 | }
83 | return null;
84 | }
85 |
86 | // write
87 | public void keepInfoIfMissing(String fname,
88 | String tag, String longitude, String latitude,
89 | String time, String timeformat) {
90 |
91 | // see if it already exists
92 | if(queryFilename(fname) == null) {
93 | // if not, write it in the file
94 | Writer output = null;
95 | try {
96 | output = new BufferedWriter(new FileWriter(filename, true));
97 | } catch (FileNotFoundException e) {
98 | e.printStackTrace();
99 | } catch (IOException e) {
100 | e.printStackTrace();
101 | }
102 |
103 | try {
104 | StringBuilder sb = new StringBuilder();
105 | sb.append(fname);sb.append(',');
106 | sb.append(tag);sb.append(',');
107 | sb.append(longitude);sb.append(',');
108 | sb.append(latitude);sb.append(',');
109 | sb.append(time);sb.append(',');
110 | sb.append(timeformat);sb.append('\n');
111 |
112 | output.append(sb.toString());
113 | output.close();
114 | } catch (IOException e) {
115 | e.printStackTrace();
116 | }
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/src/gui/BaseMapPanel.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 |
22 | package gui;
23 |
24 | import java.awt.event.ActionEvent;
25 | import java.awt.event.ActionListener;
26 | import java.util.Map;
27 | import java.util.Map.Entry;
28 | import java.util.TreeMap;
29 |
30 | import javax.swing.ButtonGroup;
31 | import javax.swing.JPanel;
32 |
33 | import main.DesktopPane;
34 | import net.miginfocom.swing.MigLayout;
35 |
36 | import javax.swing.JRadioButton;
37 |
38 | import de.fhpotsdam.unfolding.providers.AbstractMapProvider;
39 | import de.fhpotsdam.unfolding.providers.EsriProvider;
40 | import de.fhpotsdam.unfolding.providers.Google;
41 | // import de.fhpotsdam.unfolding.providers.MapBox;
42 | // import de.fhpotsdam.unfolding.providers.MapQuestProvider;
43 | import de.fhpotsdam.unfolding.providers.Microsoft;
44 | // import de.fhpotsdam.unfolding.providers.Yahoo;
45 |
46 | @SuppressWarnings("serial")
47 | public class BaseMapPanel extends JPanel {
48 | DesktopPane parent;
49 | public AbstractMapProvider chosenProvider;
50 |
51 | Map providerList = new TreeMap() {
52 | {
53 | put("Google Maps", new Google.GoogleMapProvider());
54 | put("Google Terrain", new Google.GoogleTerrainProvider());
55 | put("Google Maps Simple", new Google.GoogleSimplifiedProvider());
56 | put("Microsoft Aerial", new Microsoft.AerialProvider());
57 | // put("MapBox World Light", new MapBox.WorldLightProvider());
58 | put("ESRI World Terrain", new EsriProvider.WorldTerrain());
59 | put("ESRI NatGeo", new EsriProvider.NatGeoWorldMap());
60 | put("ESRI Ocean Basemap", new EsriProvider.OceanBasemap());
61 | put("ESRI World Gray Canvas", new EsriProvider.WorldGrayCanvas());
62 | // put("ESRI World Physical", new EsriProvider.WorldPhysical());
63 | put("ESRI World Shaded Relief", new EsriProvider.WorldShadedRelief());
64 | put("ESRI World Topo", new EsriProvider.WorldTopoMap());
65 | // put("Yahoo Aerial", new Yahoo.AerialProvider());
66 | // put("MapQuest Aerial", new MapQuestProvider.Aerial());
67 | }
68 | };
69 |
70 | public BaseMapPanel(DesktopPane father) {
71 | parent = father;
72 |
73 | setLayout(new MigLayout("wrap 1"));
74 | ButtonGroup group = new ButtonGroup();
75 |
76 | for (Entry entry : providerList.entrySet()) {
77 | String name = entry.getKey();
78 | final AbstractMapProvider provider = entry.getValue();
79 | JRadioButton button = new JRadioButton(name);
80 | add(button);
81 |
82 | group.add(button);
83 | button.addActionListener(new ActionListener() {
84 | public void actionPerformed(ActionEvent e) {
85 | chosenProvider = provider;
86 | if (parent.sketch != null) {
87 | parent.sketch.map.mapDisplay.setProvider(provider);
88 | if(parent.sketch.leftMap != null) parent.sketch.leftMap.mapDisplay.setProvider(provider);
89 | if(parent.sketch.rightMap != null) parent.sketch.rightMap.mapDisplay.setProvider(provider);
90 | }
91 | }
92 | });
93 | if (name.equals("Microsoft Aerial")) {
94 | button.doClick();
95 | }
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/gui/CombinedControlPanel.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 |
22 | package gui;
23 |
24 | import java.awt.Color;
25 | import java.awt.Font;
26 | import java.awt.event.MouseAdapter;
27 | import java.awt.event.MouseEvent;
28 |
29 | import javax.swing.JPanel;
30 |
31 | import main.DesktopPane;
32 | import net.miginfocom.swing.MigLayout;
33 |
34 | import javax.swing.JSeparator;
35 | import javax.swing.JLabel;
36 |
37 | public class CombinedControlPanel extends JPanel {
38 |
39 | /**
40 | *
41 | */
42 | private static final long serialVersionUID = 1L;
43 | private DesktopPane parent;
44 | boolean line = true;
45 | boolean point = false;
46 | boolean vector = false;
47 | // boolean ghost = false;
48 | LinePanel linePanel;
49 | PointPanel pointPanel;
50 | VectorPanel vectorPanel;
51 | // GhostPanel ghostPanel;
52 |
53 | String formattedLabel(String str, boolean flag) {
54 | String downArrowLabel = "\u25BC "+str;
55 | String upArrowLabel = "\u25B2 "+str;
56 | return (flag?downArrowLabel:upArrowLabel);
57 | }
58 |
59 | public CombinedControlPanel(DesktopPane father) {
60 | parent = father;
61 | setLayout(new MigLayout("insets 10", "[145!]", "[]10[]10[]10[]10[]10[]10[]10[]10[]10[]10[]10[]10[]"));
62 | add(parent.controlPanel, "cell 0 0,growx");
63 |
64 | linePanel = new LinePanel(parent);
65 | pointPanel = new PointPanel(parent);
66 | vectorPanel = new VectorPanel(parent);
67 | // ghostPanel = new GhostPanel(parent);
68 |
69 | JSeparator separator = new JSeparator();
70 | add(separator, "cell 0 1,growx");
71 |
72 | // Tracks -- Added Underlay(Ghost) here
73 | JLabel linelabel = new JLabel(formattedLabel("Tracks", line));
74 | linelabel.setForeground(Color.BLACK);
75 | linelabel.setFont(new Font("Arial", Font.BOLD, 10));
76 | linelabel.setBackground(Color.LIGHT_GRAY);
77 | add(linelabel, "cell 0 2");
78 | linelabel.addMouseListener(new MouseAdapter() {
79 | @Override
80 | public void mousePressed(MouseEvent e) {
81 | if (line) {
82 | remove(linePanel);
83 | } else {
84 | add(linePanel, "cell 0 3,grow");
85 | }
86 | revalidate();
87 | parent.controlContainer.pack();
88 | line = !line;
89 | ((JLabel) e.getSource()).setText(formattedLabel("Tracks", line));
90 | }
91 | });
92 | if (line){
93 | add(linePanel, "cell 0 3,grow");
94 | }
95 |
96 | JSeparator separator1 = new JSeparator();
97 | add(separator1, "cell 0 4,growx");
98 |
99 | JLabel pointlabel = new JLabel(formattedLabel("Points", point));
100 | pointlabel.setForeground(Color.BLACK);
101 | pointlabel.setFont(new Font("Arial", Font.BOLD, 10));
102 | pointlabel.setBackground(Color.LIGHT_GRAY);
103 | add(pointlabel, "cell 0 5");
104 | pointlabel.addMouseListener(new MouseAdapter() {
105 | @Override
106 | public void mousePressed(MouseEvent e) {
107 | if (point) {
108 | remove(pointPanel);
109 | } else {
110 | add(pointPanel, "cell 0 6,grow");
111 | }
112 | revalidate();
113 | parent.controlContainer.pack();
114 | point = !point;
115 | ((JLabel) e.getSource()).setText(formattedLabel("Points", point));
116 | }
117 | });
118 |
119 | JSeparator separator2 = new JSeparator();
120 | add(separator2, "cell 0 7,growx");
121 |
122 | JLabel vectorlabel = new JLabel(formattedLabel("Vectors", vector));
123 | vectorlabel.setForeground(Color.BLACK);
124 | vectorlabel.setFont(new Font("Arial", Font.BOLD, 10));
125 | vectorlabel.setBackground(Color.LIGHT_GRAY);
126 | add(vectorlabel, "cell 0 8");
127 | vectorlabel.addMouseListener(new MouseAdapter() {
128 | @Override
129 | public void mousePressed(MouseEvent e) {
130 | if (vector) {
131 | remove(vectorPanel);
132 | } else {
133 | add(vectorPanel, "cell 0 9,grow");
134 | }
135 | revalidate();
136 | parent.controlContainer.pack();
137 | vector = !vector;
138 | ((JLabel) e.getSource()).setText(formattedLabel("Vectors", vector));
139 | }
140 | });
141 |
142 | JSeparator separator3 = new JSeparator();
143 | add(separator3, "cell 0 10,growx");
144 |
145 | JLabel legendlabel = new JLabel(formattedLabel("Legend", parent.legend));
146 | legendlabel.setForeground(Color.BLACK);
147 | legendlabel.setFont(new Font("Arial", Font.BOLD, 10));
148 | legendlabel.setBackground(Color.LIGHT_GRAY);
149 | add(legendlabel, "cell 0 11");
150 | legendlabel.addMouseListener(new MouseAdapter() {
151 | @Override
152 | public void mousePressed(MouseEvent e) {
153 | if (parent.legend) {
154 | remove(parent.legendPanel);
155 | } else {
156 | add(parent.legendPanel, "cell 0 12,grow");
157 | }
158 | revalidate();
159 | parent.controlContainer.pack();
160 | parent.legend = !parent.legend;
161 | ((JLabel) e.getSource()).setText(formattedLabel("Legend", parent.legend));
162 | }
163 | });
164 |
165 | revalidate();
166 | parent.controlContainer.pack();
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/src/gui/ControlPanel.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 |
22 | package gui;
23 |
24 | import java.awt.Color;
25 | import java.awt.Font;
26 | import java.awt.Insets;
27 | import java.awt.event.ActionEvent;
28 | import java.awt.event.ActionListener;
29 | import java.awt.event.MouseAdapter;
30 | import java.awt.event.MouseEvent;
31 |
32 | import javax.swing.JButton;
33 | import javax.swing.JCheckBox;
34 | import javax.swing.JFileChooser;
35 | import javax.swing.JLabel;
36 | import javax.swing.JPanel;
37 | import javax.swing.JSlider;
38 | import javax.swing.JSpinner;
39 | import javax.swing.SpinnerNumberModel;
40 | import javax.swing.SwingConstants;
41 | import javax.swing.ToolTipManager;
42 | import javax.swing.UIManager;
43 | import javax.swing.event.ChangeEvent;
44 | import javax.swing.event.ChangeListener;
45 |
46 | import main.DesktopPane;
47 | import main.SketchData;
48 | import net.miginfocom.swing.MigLayout;
49 |
50 | import java.awt.Dimension;
51 |
52 | public class ControlPanel extends JPanel {
53 | /**
54 | *
55 | */
56 | private static final long serialVersionUID = 1L;
57 | static int openFrameCount = 0;
58 | static final int xOffset = 30, yOffset = 30;
59 |
60 | public JSlider seek;
61 | public JFileChooser dataChooser;
62 | private DesktopPane parent;
63 | private SketchData data;
64 |
65 | public ControlPanel(DesktopPane father) {
66 | parent = father;
67 | data = parent.data;
68 | try {
69 | UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
70 | } catch (Exception e) {
71 | e.printStackTrace();
72 | }
73 | setLayout(new MigLayout("insets 0", "[20px:20px:20px][15.00][20px:20px:20px,fill][][grow,fill][]",
74 | "[][][][grow,fill][][grow,fill][][][]"));
75 |
76 | JSlider speed = new JSlider();
77 | speed.setForeground(Color.BLACK);
78 | speed.setBackground(Color.LIGHT_GRAY);
79 | speed.setToolTipText("Speed");
80 | speed.setPaintTicks(true);
81 | speed.setMajorTickSpacing(1);
82 | speed.setSnapToTicks(true);
83 | speed.setMinimum(0);
84 | speed.setMaximum(10);
85 | speed.setOrientation(SwingConstants.VERTICAL);
86 | speed.setInverted(false);
87 | this.add(speed, "cell 0 0 1 8,alignx center");
88 | speed.addChangeListener(new ChangeListener() {
89 | public void stateChanged(ChangeEvent evt) {
90 | JSlider slider = (JSlider) evt.getSource();
91 | int reverseValue = 1 + ((slider.getValue() - 10) * -1); // remap 10-1 to 1-10
92 | data.speed = reverseValue;
93 | }
94 | });
95 | speed.setValue(7);
96 |
97 | seek = new JSlider();
98 | seek.setForeground(Color.BLACK);
99 | seek.setBackground(Color.LIGHT_GRAY);
100 | seek.setToolTipText("Seek");
101 | seek.setMajorTickSpacing(5);
102 | seek.setOrientation(SwingConstants.VERTICAL);
103 | seek.setValue(data.seek);
104 | seek.setMinimum(0);
105 | seek.setMaximum((data.totalTime / data.dataInterval));
106 | this.add(seek, "cell 2 0 1 8,alignx center");
107 | seek.addChangeListener(new ChangeListener() {
108 | public void stateChanged(ChangeEvent evt) {
109 | JSlider slider = (JSlider) evt.getSource();
110 | if (data.timeUnit.equals("minutes")) {
111 | data.currentTime = data.startTime.plusMinutes(slider.getValue() * data.dataInterval);
112 | } else if (data.timeUnit.equals("seconds")) {
113 | data.currentTime = data.startTime.plusSeconds(slider.getValue() * data.dataInterval);
114 | }
115 | parent.timeLine.setMarker(data.currentTime);
116 | }
117 | });
118 | seek.addMouseListener(new MouseAdapter() {
119 | @Override
120 | public void mousePressed(MouseEvent arg0) {
121 | data.mouse = true;
122 | }
123 |
124 | @Override
125 | public void mouseReleased(MouseEvent arg0) {
126 | data.mouse = false;
127 | }
128 | });
129 |
130 | final JButton Pause = new JButton("Play");
131 | Pause.setIconTextGap(0);
132 | Pause.setHorizontalTextPosition(SwingConstants.LEFT);
133 | Pause.setForeground(Color.BLACK);
134 | Pause.setBackground(new Color(227, 227, 227));
135 | Pause.setFont(new Font("Arial", Font.PLAIN, 9));
136 | Pause.setMargin(new Insets(0, 0, 0, 0));
137 | Pause.setFont(new Font("Arial", Font.PLAIN, 9));
138 | this.add(Pause, "cell 4 0 2 1,growx");
139 | Pause.addActionListener(new ActionListener() {
140 | public void actionPerformed(ActionEvent evt) {
141 | JButton button = (JButton) evt.getSource();
142 | data.pause = !data.pause;
143 | if (data.pause) {
144 | button.setText("Play");
145 | } else {
146 | button.setText("Pause");
147 |
148 | }
149 | }
150 | });
151 |
152 | JButton Reset = new JButton("Stop");
153 | Reset.setIconTextGap(0);
154 | Reset.setHorizontalTextPosition(SwingConstants.LEFT);
155 | Reset.setForeground(Color.BLACK);
156 | Reset.setBackground(new Color(227, 227, 227));
157 | Reset.setFont(new Font("Arial", Font.PLAIN, 9));
158 | Reset.setMargin(new Insets(0, 0, 0, 0));
159 | this.add(Reset, "cell 4 1 2 1,growx");
160 | Reset.addActionListener(new ActionListener() {
161 | public void actionPerformed(ActionEvent evt) {
162 | seek.setValue(0);
163 | data.pause = true;
164 | Pause.setText("Play");
165 | }
166 | });
167 |
168 | JCheckBox Loop = new JCheckBox("Loop");
169 | Loop.setForeground(Color.BLACK);
170 | Loop.setBackground(Color.LIGHT_GRAY);
171 | Loop.setFont(new Font("Arial", Font.PLAIN, 9));
172 | this.add(Loop, "cell 4 2 2 1,growx");
173 | Loop.addActionListener(new ActionListener() {
174 | public void actionPerformed(ActionEvent evt) {
175 | JCheckBox cb = (JCheckBox) evt.getSource();
176 | if (cb.isSelected()) {
177 | data.loop = true;
178 | } else {
179 | data.loop = false;
180 | }
181 | }
182 | });
183 |
184 | JButton zoomIn = new JButton("+");
185 | zoomIn.setMaximumSize(new Dimension(45, 26));
186 | zoomIn.setIconTextGap(0);
187 | zoomIn.setHorizontalTextPosition(SwingConstants.LEFT);
188 | zoomIn.setForeground(Color.BLACK);
189 | zoomIn.setBackground(new Color(227, 227, 227));
190 | zoomIn.setFont(new Font("Arial", Font.PLAIN, 9));
191 | zoomIn.setMargin(new Insets(0, 0, 0, 0));
192 | zoomIn.setFont(new Font("Arial", Font.PLAIN, 9));
193 | this.add(zoomIn, "flowy,cell 4 4 2 1,alignx right");
194 | zoomIn.addActionListener(new ActionListener() {
195 | public void actionPerformed(ActionEvent evt) {
196 | parent.sketch.zoomIn();
197 | }
198 | });
199 |
200 | JButton center = new JButton("Reset");
201 | center.setMaximumSize(new Dimension(45, 26));
202 | center.setIconTextGap(0);
203 | center.setHorizontalTextPosition(SwingConstants.LEFT);
204 | center.setForeground(Color.BLACK);
205 | center.setBackground(new Color(227, 227, 227));
206 | center.setFont(new Font("Arial", Font.PLAIN, 9));
207 | center.setMargin(new Insets(0, 0, 0, 0));
208 | center.setFont(new Font("Arial", Font.PLAIN, 9));
209 | this.add(center, "cell 4 4 2 1,alignx right");
210 | center.addActionListener(new ActionListener() {
211 | public void actionPerformed(ActionEvent evt) {
212 | parent.sketch.zoomAndPan(data.locations);
213 | }
214 | });
215 |
216 | JButton zoomOut = new JButton("-");
217 | zoomOut.setMaximumSize(new Dimension(45, 26));
218 | zoomOut.setIconTextGap(0);
219 | zoomOut.setHorizontalTextPosition(SwingConstants.LEFT);
220 | zoomOut.setForeground(Color.BLACK);
221 | zoomOut.setBackground(new Color(227, 227, 227));
222 | zoomOut.setFont(new Font("Arial", Font.PLAIN, 9));
223 | zoomOut.setMargin(new Insets(0, 0, 0, 0));
224 | zoomOut.setFont(new Font("Arial", Font.PLAIN, 9));
225 | this.add(zoomOut, "cell 4 4 2 1,alignx right");
226 | zoomOut.addActionListener(new ActionListener() {
227 | public void actionPerformed(ActionEvent evt) {
228 | parent.sketch.zoomOut();
229 | }
230 | });
231 |
232 | JCheckBox Alpha = new JCheckBox("Fade Data");
233 | Alpha.setForeground(Color.BLACK);
234 | Alpha.setBackground(Color.LIGHT_GRAY);
235 | Alpha.setFont(new Font("Arial", Font.PLAIN, 9));
236 | Alpha.setToolTipText("");
237 | ToolTipManager.sharedInstance().registerComponent(Alpha);
238 | this.add(Alpha, "cell 4 6 2 1,growx");
239 | Alpha.addChangeListener(new ChangeListener() {
240 | public void stateChanged(ChangeEvent evt) {
241 | JCheckBox cb = (JCheckBox) evt.getSource();
242 | if (cb.isSelected()) {
243 | data.falloff = true;
244 | } else {
245 | data.falloff = false;
246 | }
247 | }
248 | });
249 | Alpha.setSelected(true);
250 |
251 | JSpinner AlphaValue = new JSpinner();
252 | AlphaValue.setForeground(Color.BLACK);
253 | AlphaValue.setBackground(Color.LIGHT_GRAY);
254 | AlphaValue.setFont(new Font("Arial", Font.PLAIN, 9));
255 | AlphaValue.setModel(new SpinnerNumberModel(data.alphaMaxHours, 1, data.alphaMaxHours * 100, 1));
256 | AlphaValue.setToolTipText("");
257 | ToolTipManager.sharedInstance().registerComponent(AlphaValue);
258 | this.add(AlphaValue, "flowx,cell 4 7 2 1,growx");
259 | AlphaValue.addChangeListener(new ChangeListener() {
260 | public void stateChanged(ChangeEvent evt) {
261 | JSpinner spin = (JSpinner) evt.getSource();
262 | data.alphaMaxHours = (Integer) spin.getValue();
263 | }
264 | });
265 |
266 | JLabel label = new JLabel("Speed");
267 | label.setBackground(Color.LIGHT_GRAY);
268 | label.setForeground(Color.BLACK);
269 | label.setFont(new Font("Arial", Font.PLAIN, 8));
270 | this.add(label, "cell 0 8");
271 |
272 | JLabel lblSeek = new JLabel("Seek");
273 | lblSeek.setBackground(Color.LIGHT_GRAY);
274 | lblSeek.setForeground(Color.BLACK);
275 | lblSeek.setFont(new Font("Arial", Font.PLAIN, 8));
276 | this.add(lblSeek, "cell 2 8");
277 |
278 | String unit;
279 | if (data.timeUnit.equals("minutes")) {
280 | unit = "(h)";
281 | } else {
282 | unit = "(m)";
283 | }
284 | JLabel lblPointLifehours = new JLabel("Fade Duration " + unit);
285 | lblPointLifehours.setHorizontalAlignment(SwingConstants.RIGHT);
286 | lblPointLifehours.setForeground(Color.BLACK);
287 | lblPointLifehours.setFont(new Font("Arial", Font.PLAIN, 8));
288 | lblPointLifehours.setBackground(Color.LIGHT_GRAY);
289 | this.add(lblPointLifehours, "cell 4 8 2 1,alignx right");
290 |
291 | }
292 | }
293 |
--------------------------------------------------------------------------------
/src/gui/GradientEditor.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 |
22 | package gui;
23 |
24 | import java.awt.Color;
25 | import java.awt.Dimension;
26 | import java.awt.Graphics;
27 | import java.awt.Graphics2D;
28 | import java.awt.Polygon;
29 | import java.awt.Rectangle;
30 | import java.awt.event.ActionEvent;
31 | import java.awt.event.ActionListener;
32 | import java.awt.event.MouseAdapter;
33 | import java.awt.event.MouseEvent;
34 | import java.awt.event.MouseMotionListener;
35 | import java.io.File;
36 | import java.io.FileInputStream;
37 | import java.io.FileOutputStream;
38 | import java.io.InputStream;
39 | import java.io.OutputStream;
40 | import java.text.DecimalFormat;
41 | import java.util.ArrayList;
42 | import java.util.Collections;
43 | import java.util.Comparator;
44 | import java.util.Vector;
45 |
46 | import javax.swing.DefaultComboBoxModel;
47 | import javax.swing.ImageIcon;
48 | import javax.swing.JButton;
49 | import javax.swing.JColorChooser;
50 | import javax.swing.JComboBox;
51 | import javax.swing.JComponent;
52 | import javax.swing.JDialog;
53 | import javax.swing.JFileChooser;
54 | import javax.swing.JLabel;
55 | import javax.swing.JPanel;
56 | import javax.swing.JTextField;
57 | import javax.swing.filechooser.FileNameExtensionFilter;
58 |
59 | import org.gicentre.utils.colour.ColourRule;
60 | import org.gicentre.utils.colour.ColourTable;
61 |
62 | import main.DesktopPane;
63 | import net.miginfocom.swing.MigLayout;
64 |
65 | @SuppressWarnings("serial")
66 | public class GradientEditor extends JPanel {
67 |
68 | public DesktopPane parent;
69 | private ArrayList list;
70 | private ControlPoint selected;
71 | private Polygon poly = new Polygon();
72 | private Polygon square = new Polygon();
73 | private JButton del = new JButton("Delete");
74 | private int x;
75 | private int y;
76 | private int width;
77 | private int barHeight;
78 | public ColourTable currentSwatch;
79 | private ArrayList listeners = new ArrayList();
80 | private JComboBox comboBox;
81 | private JButton okButton = new JButton("OK");
82 | private JButton resetButton = new JButton("Reset");
83 | private JButton loadButton = new JButton("Load File");
84 | private JButton saveButton = new JButton("Save File");
85 | private JButton newButton = new JButton("Add to List");
86 | private JButton colButton = new JButton("");
87 | private JTextField textField = new JTextField();
88 | private JLabel colLabel = new JLabel("Color:");
89 | private JLabel locLabel = new JLabel("Location:");
90 | private JLabel label = new JLabel("%");
91 | private JTextField nameField = new JTextField();
92 | private JDialog mom;
93 | DecimalFormat df = new DecimalFormat("##.##");
94 |
95 | LinePanel lp;
96 | PointPanel pp;
97 | VectorPanel vp;
98 | // BoundaryPanel bp;
99 | static int LINE = 1;
100 | static int POINT = 2;
101 | static int VECTOR = 3;
102 | static int BOUNDARY = 4;
103 | int owner;
104 |
105 | public GradientEditor(DesktopPane father, JDialog m, LinePanel l) {
106 | this(father, m, LINE);
107 | }
108 |
109 | public GradientEditor(DesktopPane father, JDialog m, PointPanel p) {
110 | this(father, m, POINT);
111 | }
112 |
113 | public GradientEditor(DesktopPane father, JDialog m, VectorPanel v) {
114 | this(father, m, VECTOR);
115 | }
116 |
117 | // public GradientEditor(DesktopPane father, JDialog m, BoundaryPanel b) {
118 | // this(father, m, BOUNDARY);
119 | // }
120 |
121 | public GradientEditor(DesktopPane father, JDialog m, int o) {
122 |
123 | owner = o;
124 | parent = father;
125 | mom = m;
126 |
127 | textField.setMaximumSize(new Dimension(50, 2147483647));
128 | textField.setColumns(10);
129 |
130 | comboBox = new JComboBox(parent.colors.largeRampList.toArray());
131 |
132 | setLayout(new MigLayout("", "[grow][grow][fill]", "[][][][][][grow][]"));
133 |
134 | Gradient gradient = new Gradient();
135 | gradient.setMinimumSize(new Dimension(400, 65));
136 | add(gradient, "cell 0 5 3 1,growx");
137 |
138 | comboBox.addActionListener(new ActionListener() {
139 | public void actionPerformed(ActionEvent e) {
140 | JComboBox comboBox = (JComboBox) e.getSource();
141 | convertSwatch(parent.colors.coloursCont.get(comboBox.getSelectedIndex()));
142 | }
143 | });
144 |
145 | setSelected();
146 |
147 | // add(lblName, "flowx,cell 0 4 2 1,alignx trailing");
148 | nameField.setColumns(10);
149 |
150 | // add(nameField, "cell 0 4 2 1,growx");
151 |
152 | add(newButton, "cell 2 4,growx");
153 | newButton.addActionListener(new ActionListener() {
154 | public void actionPerformed(ActionEvent e) {
155 | ImageIcon largeSwatch = parent.colors.createSwatch(currentSwatch, "large");
156 | ImageIcon smallSwatch = parent.colors.createSwatch(currentSwatch, "small");
157 | parent.colors.coloursCont.add(currentSwatch);
158 | parent.colors.colorRampList.add(smallSwatch);
159 | parent.cp.linePanel.colorRampList.addItem(smallSwatch);
160 | parent.cp.pointPanel.colorRampList.addItem(smallSwatch);
161 | parent.cp.vectorPanel.colorRampList.addItem(smallSwatch);
162 | parent.colors.largeRampList.add(largeSwatch);
163 | comboBox.addItem(largeSwatch);
164 | comboBox.setSelectedIndex(comboBox.getItemCount() - 1);
165 | }
166 | });
167 |
168 | add(saveButton, "cell 2 3,growx");
169 | saveButton.addActionListener(new ActionListener() {
170 | public void actionPerformed(ActionEvent e) {
171 | JFileChooser chooser = new JFileChooser();
172 | chooser.setCurrentDirectory(new File("./config/color"));
173 | chooser.setAcceptAllFileFilterUsed(false);
174 | FileNameExtensionFilter filter = new FileNameExtensionFilter("ColourTable File", "ctb", "CTB");
175 | chooser.addChoosableFileFilter(filter);
176 | int retrival = chooser.showSaveDialog(null);
177 | if (retrival == JFileChooser.APPROVE_OPTION) {
178 | try {
179 | String string = chooser.getSelectedFile().getAbsolutePath();
180 | if (!string.endsWith(".ctb")) {
181 | string = string + ".ctb";
182 | }
183 | OutputStream out = new FileOutputStream(string);
184 | ColourTable.writeFile(currentSwatch, out);
185 | System.out.println("Saved Color Table: " + string);
186 | } catch (Exception ex) {
187 | ex.printStackTrace();
188 | }
189 | }
190 | }
191 | });
192 |
193 | add(loadButton, "cell 2 2,growx");
194 | loadButton.addActionListener(new ActionListener() {
195 | public void actionPerformed(ActionEvent e) {
196 | JFileChooser chooser = new JFileChooser();
197 | chooser.setCurrentDirectory(new File("./config/color"));
198 | chooser.setAcceptAllFileFilterUsed(false);
199 | FileNameExtensionFilter filter = new FileNameExtensionFilter("ColourTable File", "ctb", "CTB");
200 | chooser.addChoosableFileFilter(filter);
201 | int retrival = chooser.showOpenDialog(null);
202 | if (retrival == JFileChooser.APPROVE_OPTION) {
203 | try {
204 | InputStream in = new FileInputStream(chooser.getSelectedFile());
205 | convertSwatch(ColourTable.readFile(in));
206 | newButton.doClick();
207 | System.out.println("Loaded Color Table: " + chooser.getSelectedFile());
208 | } catch (Exception ex) {
209 | ex.printStackTrace();
210 | }
211 | }
212 | }
213 | });
214 |
215 | add(resetButton, "cell 2 1,growx");
216 | resetButton.addActionListener(new ActionListener() {
217 | public void actionPerformed(ActionEvent e) {
218 | convertSwatch(parent.colors.coloursCont.get(comboBox.getSelectedIndex()));
219 | }
220 | });
221 |
222 | add(okButton, "cell 2 0,growx");
223 | okButton.addActionListener(new ActionListener() {
224 | public void actionPerformed(ActionEvent e) {
225 | if (owner == LINE)
226 | parent.cp.linePanel.colorRampList.setSelectedIndex(comboBox.getSelectedIndex());
227 | if (owner == POINT)
228 | parent.cp.pointPanel.colorRampList.setSelectedIndex(comboBox.getSelectedIndex());
229 | if (owner == VECTOR)
230 | parent.cp.vectorPanel.colorRampList.setSelectedIndex(comboBox.getSelectedIndex());
231 | mom.setVisible(false);
232 | }
233 | });
234 |
235 | add(comboBox, "cell 0 0 2 1,growx");
236 |
237 | add(colLabel, "flowx,cell 0 6,alignx center");
238 | colButton.setMinimumSize(new Dimension(50, 20));
239 |
240 | add(colButton, "cell 0 6,alignx center");
241 | colButton.addActionListener(new ActionListener() {
242 | public void actionPerformed(ActionEvent e) {
243 | editPoint();
244 | }
245 | });
246 | add(locLabel, "flowx,cell 1 6");
247 |
248 | add(textField, "cell 1 6");
249 |
250 | add(label, "cell 1 6");
251 | add(del, "cell 2 6,growx");
252 | del.addActionListener(new ActionListener() {
253 | public void actionPerformed(ActionEvent e) {
254 | delPoint();
255 | }
256 | });
257 |
258 | poly.addPoint(0, 0);
259 | poly.addPoint(5, 5);
260 | poly.addPoint(-5, 5);
261 |
262 | square.addPoint(-5, 5);
263 | square.addPoint(5, 5);
264 | square.addPoint(5, 15);
265 | square.addPoint(-5, 15);
266 |
267 | gradient.addMouseListener(new MouseAdapter() {
268 | public void mousePressed(MouseEvent e) {
269 | selectPoint(e.getX(), e.getY());
270 | repaint(0);
271 |
272 | if (e.getClickCount() == 2) {
273 | editPoint();
274 | }
275 | }
276 | });
277 |
278 | gradient.addMouseMotionListener(new MouseMotionListener() {
279 | public void mouseDragged(MouseEvent e) {
280 | movePoint(e.getX(), e.getY());
281 | repaint(0);
282 | }
283 |
284 | public void mouseMoved(MouseEvent e) {
285 | }
286 | });
287 | }
288 |
289 | public void reBuildList() {
290 | comboBox.setModel(new DefaultComboBoxModel(parent.colors.largeRampList.toArray()));
291 | }
292 |
293 | public void setSelected() {
294 | if (owner == LINE)
295 | comboBox.setSelectedIndex(parent.data.selectedLineSwatch);
296 | if (owner == POINT)
297 | comboBox.setSelectedIndex(parent.data.selectedPointSwatch);
298 | if (owner == VECTOR)
299 | comboBox.setSelectedIndex(parent.data.selectedVectorSwatch);
300 | if (owner == BOUNDARY)
301 | comboBox.setSelectedIndex(parent.data.selectedVectorSwatch);
302 | }
303 |
304 | private void convertSwatch(ColourTable colourTable) {
305 | list = new ArrayList();
306 | currentSwatch = colourTable;
307 | Vector rules = currentSwatch.getColourRules();
308 | for (int i = 1; i < rules.size(); i++) {
309 | ColourRule rule = rules.get(i);
310 | String string = Integer.toHexString(rule.getlColour());
311 | string = string.substring(2, string.length());
312 | Color color = Color.decode("#" + string);
313 | list.add(new ControlPoint(color, rule.getlIndex()));
314 | }
315 | repaint();
316 | }
317 |
318 | public void addActionListener(ActionListener listener) {
319 | listeners.add(listener);
320 | }
321 |
322 | public void removeActionListener(ActionListener listener) {
323 | listeners.remove(listener);
324 | }
325 |
326 | private void fireUpdate() {
327 | currentSwatch = new ColourTable();
328 | for (int i = 0; i < list.size(); i++) {
329 | ControlPoint now = (ControlPoint) list.get(i);
330 | currentSwatch.addContinuousColourRule(now.pos, now.col.getRGB());
331 | }
332 | repaint();
333 | ActionEvent event = new ActionEvent(this, 0, "");
334 | for (int i = 0; i < listeners.size(); i++) {
335 | ((ActionListener) listeners.get(i)).actionPerformed(event);
336 | }
337 | }
338 |
339 | private boolean checkPoint(int mx, int my, ControlPoint pt) {
340 | int dx = (int) Math.abs((10 + (width * pt.pos)) - mx);
341 | int dy = Math.abs((y + barHeight + 7) - my);
342 |
343 | if ((dx < 5) && (dy < 7)) {
344 | return true;
345 | }
346 |
347 | return false;
348 | }
349 |
350 | private void addPoint() {
351 | ControlPoint point = new ControlPoint(colButton.getBackground(), 0.5f);
352 | for (int i = 0; i < list.size() - 1; i++) {
353 | ControlPoint now = (ControlPoint) list.get(i);
354 | ControlPoint next = (ControlPoint) list.get(i + 1);
355 | if ((now.pos <= 0.5f) && (next.pos >= 0.5f)) {
356 | list.add(i + 1, point);
357 | break;
358 | }
359 |
360 | }
361 | selected = point;
362 | sortPoints();
363 | repaint(0);
364 |
365 | fireUpdate();
366 | }
367 |
368 | private void sortPoints() {
369 | final ControlPoint firstPt = (ControlPoint) list.get(0);
370 | final ControlPoint lastPt = (ControlPoint) list.get(list.size() - 1);
371 | Comparator compare = new Comparator() {
372 | public int compare(Object first, Object second) {
373 | if (first == firstPt) {
374 | return -1;
375 | }
376 | if (second == lastPt) {
377 | return -1;
378 | }
379 |
380 | float a = ((ControlPoint) first).pos;
381 | float b = ((ControlPoint) second).pos;
382 | return (int) ((a - b) * 10000);
383 | }
384 | };
385 | Collections.sort(list, compare);
386 | }
387 |
388 | private void editPoint() {
389 | if (selected == null) {
390 | Color color = null;
391 | Color col = JColorChooser.showDialog(this, "Select Color", color);
392 | if (col != null) {
393 | colButton.setBackground(col);
394 | }
395 | return;
396 | }
397 | Color col = JColorChooser.showDialog(this, "Select Color", selected.col);
398 | if (col != null) {
399 | selected.col = col;
400 | colButton.setBackground(col);
401 | repaint(0);
402 | fireUpdate();
403 | }
404 | }
405 |
406 | private void selectPoint(int mx, int my) {
407 | if (!isEnabled()) {
408 | return;
409 | }
410 |
411 | for (int i = 1; i < list.size() - 1; i++) {
412 | if (checkPoint(mx, my, (ControlPoint) list.get(i))) {
413 | selected = (ControlPoint) list.get(i);
414 | textField.setText(df.format(selected.pos * 100));
415 | colButton.setBackground(selected.col);
416 | return;
417 | }
418 | }
419 | if (checkPoint(mx, my, (ControlPoint) list.get(0))) {
420 | selected = (ControlPoint) list.get(0);
421 | textField.setText(df.format(selected.pos * 100));
422 | colButton.setBackground(selected.col);
423 | return;
424 | }
425 | if (checkPoint(mx, my, (ControlPoint) list.get(list.size() - 1))) {
426 | selected = (ControlPoint) list.get(list.size() - 1);
427 | textField.setText(df.format(selected.pos * 100));
428 | colButton.setBackground(selected.col);
429 | return;
430 | } else {
431 | // click to add like ps
432 | addPoint();
433 | movePoint(mx, my);
434 | return;
435 | }
436 | }
437 |
438 | private void delPoint() {
439 | if (!isEnabled()) {
440 | return;
441 | }
442 |
443 | if (selected == null) {
444 | return;
445 | }
446 | if (list.indexOf(selected) == 0) {
447 | return;
448 | }
449 | if (list.indexOf(selected) == list.size() - 1) {
450 | return;
451 | }
452 |
453 | list.remove(selected);
454 | sortPoints();
455 | repaint(0);
456 | fireUpdate();
457 | }
458 |
459 | private void movePoint(int mx, int my) {
460 | if (!isEnabled()) {
461 | return;
462 | }
463 |
464 | // drag down to delete like ps
465 | if (my > 75) {
466 | delPoint();
467 | return;
468 | }
469 |
470 | if (selected == null) {
471 | return;
472 | }
473 | if (list.indexOf(selected) == 0) {
474 | return;
475 | }
476 | if (list.indexOf(selected) == list.size() - 1) {
477 | return;
478 | }
479 |
480 | float newPos = (mx - 10) / (float) width;
481 | newPos = Math.min(1, newPos);
482 | newPos = Math.max(0, newPos);
483 |
484 | selected.pos = newPos;
485 | textField.setText(df.format(selected.pos * 100));
486 | sortPoints();
487 | fireUpdate();
488 | }
489 |
490 | public class Gradient extends JComponent {
491 |
492 | @Override
493 | public void paintComponent(Graphics g1d) {
494 |
495 | Graphics2D g = (Graphics2D) g1d;
496 | width = getWidth() - 20;
497 | x = 10;
498 | y = 20;
499 | barHeight = 27;
500 | for (int s = 0; s < width; s++) {
501 | Rectangle rect = new Rectangle(s + x, y, 1, barHeight);
502 | String string = Integer.toHexString(currentSwatch.findColour((float) s / (width)));
503 | string = string.substring(2, string.length());
504 | Color color = Color.decode("#" + string);
505 | g.setPaint(color);
506 | g.fill(rect);
507 | }
508 |
509 | g.setColor(Color.black);
510 | g.drawRect(10, y, width, barHeight - 1);
511 |
512 | for (int i = 0; i < list.size(); i++) {
513 | ControlPoint pt = (ControlPoint) list.get(i);
514 | g.translate(10 + (width * pt.pos), y + barHeight);
515 |
516 | if (pt == selected) {
517 | // g.drawLine(-5, 12, 5, 12);
518 | g.setColor(Color.DARK_GRAY);
519 | g.fillPolygon(poly);
520 | }
521 | g.setColor(pt.col);
522 | g.fillPolygon(square);
523 | g.setColor(Color.black);
524 | g.drawPolygon(square);
525 | g.drawPolygon(poly);
526 |
527 | g.translate(-10 - (width * pt.pos), -y - barHeight);
528 | }
529 | }
530 | }
531 |
532 | public void addPoint(float pos, Color col) {
533 | ControlPoint point = new ControlPoint(col, pos);
534 | for (int i = 0; i < list.size() - 1; i++) {
535 | ControlPoint now = (ControlPoint) list.get(i);
536 | ControlPoint next = (ControlPoint) list.get(i + 1);
537 | if ((now.pos <= 0.5f) && (next.pos >= 0.5f)) {
538 | list.add(i + 1, point);
539 | break;
540 | }
541 | }
542 | repaint(0);
543 | }
544 |
545 | public void setStart(Color col) {
546 | ((ControlPoint) list.get(0)).col = col;
547 | repaint(0);
548 | }
549 |
550 | public void setEnd(Color col) {
551 | ((ControlPoint) list.get(list.size() - 1)).col = col;
552 | repaint(0);
553 | }
554 |
555 | public void clearPoints() {
556 | for (int i = 1; i < list.size() - 1; i++) {
557 | list.remove(1);
558 | }
559 |
560 | repaint(0);
561 | fireUpdate();
562 | }
563 |
564 | public int getControlPointCount() {
565 | return list.size();
566 | }
567 |
568 | public float getPointPos(int index) {
569 | return ((ControlPoint) list.get(index)).pos;
570 | }
571 |
572 | public Color getColor(int index) {
573 | return ((ControlPoint) list.get(index)).col;
574 | }
575 |
576 | public class ControlPoint {
577 |
578 | public Color col;
579 | public float pos;
580 |
581 | private ControlPoint(Color col, float pos) {
582 | this.col = col;
583 | this.pos = pos;
584 | }
585 | }
586 |
587 | }
588 |
--------------------------------------------------------------------------------
/src/gui/LegendPanel.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 | package gui;
22 |
23 | import javax.swing.JPanel;
24 |
25 | import main.DesktopPane;
26 | import main.SketchData;
27 |
28 | import net.miginfocom.swing.MigLayout;
29 |
30 | import javax.swing.JColorChooser;
31 | import javax.swing.JDialog;
32 | import javax.swing.JFileChooser;
33 | import javax.swing.JLabel;
34 | import javax.swing.JComboBox;
35 | import javax.swing.SwingConstants;
36 | import javax.swing.UIManager;
37 |
38 | import java.awt.Color;
39 | import java.awt.Component;
40 | import java.awt.Dimension;
41 | import java.awt.Font;
42 | import java.awt.Insets;
43 | import java.awt.event.ActionEvent;
44 | import java.awt.event.ActionListener;
45 |
46 | import javax.swing.JButton;
47 | import javax.swing.filechooser.FileNameExtensionFilter;
48 |
49 | import java.io.File;
50 | import java.io.FileInputStream;
51 | import java.io.FileOutputStream;
52 | import java.io.InputStream;
53 | import java.io.OutputStream;
54 |
55 | public class LegendPanel extends JPanel {
56 |
57 | /**
58 | *
59 | */
60 | private static final long serialVersionUID = 1L;
61 |
62 | DesktopPane parent;
63 | SketchData data;
64 |
65 | WideComboBox fontChooser;
66 | JComboBox size;
67 |
68 | public LegendPanel(DesktopPane father) {
69 | parent = father;
70 | data = parent.data;
71 |
72 | setLayout(new MigLayout("insets 0", "[50%][][][grow]", "[][][][][][]"));
73 |
74 | JLabel lblFont = new JLabel("Font");
75 | lblFont.setForeground(Color.BLACK);
76 | lblFont.setFont(new Font("Arial", Font.PLAIN, 8));
77 | lblFont.setBackground(Color.LIGHT_GRAY);
78 | this.add(lblFont, "cell 0 0");
79 |
80 | fontChooser = new WideComboBox(parent.fonts);
81 | // fontChooser.setEditable(true);
82 | fontChooser.setMaximumSize(new Dimension(80, 200));
83 | fontChooser.setForeground(Color.BLACK);
84 | fontChooser.setBackground(UIManager.getColor("CheckBox.background"));
85 | fontChooser.setFont(new Font("Arial", Font.PLAIN, 9));
86 | this.add(fontChooser, "cell 0 1 2 1,grow");
87 | fontChooser.setSelectedItem("Arial");
88 | fontChooser.addActionListener(new ActionListener() {
89 | public void actionPerformed(ActionEvent e) {
90 | WideComboBox temp = (WideComboBox) e.getSource();
91 | String name = (String) temp.getSelectedItem();
92 | if (name != null) {
93 | parent.sketch.legend.setFont(name, (Integer) size.getSelectedItem());
94 | }
95 | }
96 | });
97 |
98 | size = new JComboBox();
99 | size.setForeground(Color.BLACK);
100 | size.setBackground(UIManager.getColor("CheckBox.background"));
101 | size.setFont(new Font("Arial", Font.PLAIN, 9));
102 | this.add(size, "cell 2 1,growx");
103 | for (int i = 8; i <= 18; i++) {
104 | size.addItem(i);
105 | }
106 | size.setSelectedIndex(2);
107 | size.addActionListener(new ActionListener() {
108 | public void actionPerformed(ActionEvent e) {
109 | JComboBox> temp = (JComboBox>) e.getSource();
110 | int size = (Integer) temp.getSelectedItem();
111 | parent.sketch.legend.setFont((String) fontChooser.getSelectedItem(), size);
112 | }
113 | });
114 |
115 | JButton btnNewButton = new JButton("Unlock");
116 | btnNewButton.setIconTextGap(0);
117 | btnNewButton.setHorizontalTextPosition(SwingConstants.LEFT);
118 | btnNewButton.setForeground(Color.BLACK);
119 | btnNewButton.setBackground(new Color(227, 227, 227));
120 | btnNewButton.setFont(new Font("Arial", Font.PLAIN, 9));
121 | btnNewButton.setMargin(new Insets(0, 0, 0, 0));
122 | btnNewButton.setFont(new Font("Arial", Font.PLAIN, 9));
123 | btnNewButton.addActionListener(new ActionListener() {
124 | public void actionPerformed(ActionEvent evt) {
125 | JButton button = (JButton) evt.getSource();
126 | data.legendLocked = !data.legendLocked;
127 | if (data.legendLocked) {
128 | button.setText("Unlock");
129 | parent.sketch.register();
130 | } else {
131 | button.setText("Lock");
132 | parent.sketch.unregister();
133 | }
134 | }
135 | });
136 |
137 | final JButton btnNewButton_1 = new JButton("");
138 | add(btnNewButton_1, "cell 3 1,grow");
139 | // btnNewButton_1.setMinimumSize(new Dimension(15,15));
140 | btnNewButton_1.setBackground(parent.colors.getLegendColor());
141 | btnNewButton_1.setMargin(new Insets(0, 0, 0, 0));
142 | btnNewButton_1.addActionListener(new ActionListener() {
143 | public void actionPerformed(ActionEvent evt) {
144 | final JColorChooser colorChooser = new JColorChooser();
145 | JDialog maxDialog = JColorChooser.createDialog((Component) evt.getSource(), "Pick a Color", true, // modal
146 | colorChooser, new ActionListener() {
147 |
148 | @Override
149 | public void actionPerformed(ActionEvent e) {
150 | parent.colors.setLegendColor(colorChooser.getColor());
151 | btnNewButton_1.setBackground(parent.colors.getLegendColor());
152 | parent.sketch.legend.setFontColor(parent.colors.getLegendColor().getRGB());
153 |
154 | }
155 | }, new ActionListener() {
156 | @Override
157 | public void actionPerformed(ActionEvent event) {
158 | }
159 | });
160 | maxDialog.setVisible(true);
161 | }
162 | });
163 | this.add(btnNewButton, "cell 0 3 4 1,growx");
164 |
165 | JButton resetButton = new JButton("Reset");
166 | resetButton.setIconTextGap(0);
167 | resetButton.setHorizontalTextPosition(SwingConstants.LEFT);
168 | resetButton.setForeground(Color.BLACK);
169 | resetButton.setBackground(new Color(227, 227, 227));
170 | resetButton.setFont(new Font("Arial", Font.PLAIN, 9));
171 | resetButton.setMargin(new Insets(0, 0, 0, 0));
172 | resetButton.setFont(new Font("Arial", Font.PLAIN, 9));
173 | resetButton.addActionListener(new ActionListener() {
174 | public void actionPerformed(ActionEvent evt) {
175 | parent.sketch.resetLegend();
176 | fontChooser.setSelectedItem("Arial");
177 | size.setSelectedIndex(2);
178 | parent.colors.setLegendColor(Color.WHITE);
179 | btnNewButton_1.setBackground(parent.colors.getLegendColor());
180 | parent.sketch.legend.setFontColor(parent.colors.getLegendColor().getRGB());
181 | }
182 | });
183 | this.add(resetButton, "cell 0 4 4 1,growx");
184 |
185 | JButton btnSave = new JButton("Save");
186 | btnSave.setMargin(new Insets(0, 0, 0, 0));
187 | btnSave.setIconTextGap(0);
188 | btnSave.setHorizontalTextPosition(SwingConstants.LEFT);
189 | btnSave.setForeground(Color.BLACK);
190 | btnSave.setFont(new Font("Arial", Font.PLAIN, 9));
191 | btnSave.setBackground(new Color(227, 227, 227));
192 | add(btnSave, "cell 0 5,growx");
193 | btnSave.addActionListener(new ActionListener() {
194 | public void actionPerformed(ActionEvent e) {
195 | JFileChooser chooser = new JFileChooser();
196 | chooser.setCurrentDirectory(new File("./config/legend"));
197 | chooser.setAcceptAllFileFilterUsed(false);
198 | FileNameExtensionFilter filter = new FileNameExtensionFilter("Legend File", "xml", "XML");
199 | chooser.addChoosableFileFilter(filter);
200 | int retrival = chooser.showSaveDialog(null);
201 | if (retrival == JFileChooser.APPROVE_OPTION) {
202 | try {
203 | String string = chooser.getSelectedFile().getAbsolutePath();
204 | if (!string.endsWith(".xml")) {
205 | string = string + ".xml";
206 | }
207 | OutputStream out = new FileOutputStream(string);
208 | parent.sketch.legend.writeFile(out);
209 | System.out.println("Saved Legend Layout: " + string);
210 | } catch (Exception ex) {
211 | ex.printStackTrace();
212 | }
213 | }
214 | }
215 | });
216 |
217 | JButton btnLoad = new JButton("Load");
218 | btnLoad.setMargin(new Insets(0, 0, 0, 0));
219 | btnLoad.setIconTextGap(0);
220 | btnLoad.setHorizontalTextPosition(SwingConstants.LEFT);
221 | btnLoad.setForeground(Color.BLACK);
222 | btnLoad.setFont(new Font("Arial", Font.PLAIN, 9));
223 | btnLoad.setBackground(new Color(227, 227, 227));
224 | add(btnLoad, "cell 1 5 3 1,growx");
225 | btnLoad.addActionListener(new ActionListener() {
226 | public void actionPerformed(ActionEvent e) {
227 | JFileChooser chooser = new JFileChooser();
228 | chooser.setCurrentDirectory(new File("./config/legend"));
229 | chooser.setAcceptAllFileFilterUsed(false);
230 | FileNameExtensionFilter filter = new FileNameExtensionFilter("Legend File", "xml", "XML");
231 | chooser.addChoosableFileFilter(filter);
232 | int retrival = chooser.showOpenDialog(null);
233 | if (retrival == JFileChooser.APPROVE_OPTION) {
234 | try {
235 | InputStream in = new FileInputStream(chooser.getSelectedFile());
236 | parent.sketch.legend.readFile(in);
237 | System.out.println("Loaded Legend Layout: " + chooser.getSelectedFile());
238 | } catch (Exception ex) {
239 | ex.printStackTrace();
240 | }
241 | }
242 | }
243 | });
244 |
245 | }
246 | }
247 |
--------------------------------------------------------------------------------
/src/gui/LinePanel.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 |
22 | package gui;
23 |
24 | import javax.swing.JPanel;
25 | import javax.swing.JSpinner;
26 | import javax.swing.SpinnerNumberModel;
27 |
28 | import main.DesktopPane;
29 | import main.SketchData;
30 | import net.miginfocom.swing.MigLayout;
31 |
32 | import javax.swing.JButton;
33 | import javax.swing.JCheckBox;
34 | import javax.swing.JColorChooser;
35 | import javax.swing.JDialog;
36 | import javax.swing.JLabel;
37 | import javax.swing.SwingConstants;
38 | import javax.swing.ToolTipManager;
39 | import javax.swing.UIManager;
40 |
41 | import java.awt.Color;
42 | import java.awt.Component;
43 | import java.awt.Dimension;
44 | import java.awt.Font;
45 | import java.awt.Insets;
46 | import java.awt.event.ActionEvent;
47 | import java.awt.event.ActionListener;
48 | import java.util.ArrayList;
49 |
50 | import javax.swing.event.ChangeEvent;
51 | import javax.swing.event.ChangeListener;
52 |
53 | public class LinePanel extends JPanel {
54 |
55 | /**
56 | *
57 | */
58 | private static final long serialVersionUID = 1L;
59 |
60 | DesktopPane parent;
61 | SketchData data;
62 |
63 | public WideComboBox strokeColor;
64 | public WideComboBox strokeWeight;
65 | public WideComboBox colorRampList;
66 | JDialog geCtr;
67 | LinePanel me;
68 | GradientEditor ge;
69 |
70 | public LinePanel(DesktopPane father) {
71 | parent = father;
72 | data = parent.data;
73 | me = this;
74 | setLayout(new MigLayout("insets 0", "[grow][grow][][]", "[][][][][][][][][][]"));
75 |
76 | JLabel lblLineColor = new JLabel("Line Color");
77 | lblLineColor.setForeground(Color.BLACK);
78 | lblLineColor.setFont(new Font("Arial", Font.PLAIN, 8));
79 | lblLineColor.setBackground(Color.LIGHT_GRAY);
80 | this.add(lblLineColor, "cell 0 0,alignx left,aligny baseline");
81 |
82 | // 2 - color ramp list
83 | colorRampList = new WideComboBox(parent.colors.colorRampList.toArray());
84 | colorRampList.setMaximumSize(new Dimension(120, 32767));
85 | colorRampList.setMaximumRowCount(100);
86 | colorRampList.setForeground(Color.BLACK);
87 | colorRampList.setBackground(UIManager.getColor("CheckBox.background"));
88 | colorRampList.setFont(new Font("Arial", Font.PLAIN, 9));
89 | this.add(colorRampList, "cell 0 2 3 1,growx");
90 | colorRampList.addActionListener(new ActionListener() {
91 | public void actionPerformed(ActionEvent e) {
92 | WideComboBox comboBox = (WideComboBox) e.getSource();
93 | parent.data.selectedLineSwatch = (int) comboBox.getSelectedIndex();
94 | }
95 | });
96 |
97 | // 1 - line color field name
98 | strokeColor = new WideComboBox();
99 | strokeColor.setMaximumSize(new Dimension(120, 32767));
100 | strokeColor.setMaximumRowCount(100);
101 | strokeColor.setForeground(Color.BLACK);
102 | strokeColor.setBackground(UIManager.getColor("CheckBox.background"));
103 | strokeColor.setFont(new Font("Arial", Font.PLAIN, 9));
104 | this.add(strokeColor, "cell 0 1 3 1,growx");
105 | strokeColor.addActionListener(new ActionListener() {
106 | public void actionPerformed(ActionEvent e) {
107 | WideComboBox cb = (WideComboBox) e.getSource();
108 | String item = (String) cb.getSelectedItem();
109 |
110 | if(item.equals("Identifier")) colorRampList.setEnabled(false);
111 | else colorRampList.setEnabled(true);
112 |
113 | data.strokeColorSelection = parent.attributes.getName(item);
114 | String unit = parent.attributes.getUnit(data.strokeColorSelection);
115 | if (unit.contains("none")) {
116 | unit = "";
117 | }
118 | data.selectedColorUnit = unit;
119 | if (data.fieldColors.get(data.strokeColorSelection) != null) {
120 | // parent.colorPanel.colorRampList.setSelectedIndex(data.fieldColors.get(data.strokeColorSelection));
121 | }
122 | }
123 | });
124 |
125 | JCheckBox strokeColorToggle = new JCheckBox("");
126 | strokeColorToggle.setForeground(Color.BLACK);
127 | strokeColorToggle.setFont(new Font("Arial", Font.PLAIN, 9));
128 | strokeColorToggle.setBackground(Color.LIGHT_GRAY);
129 | this.add(strokeColorToggle, "cell 3 1,growx");
130 | strokeColorToggle.addChangeListener(new ChangeListener() {
131 | public void stateChanged(ChangeEvent evt) {
132 | JCheckBox cb = (JCheckBox) evt.getSource();
133 | if (cb.isSelected()) {
134 | data.strokeColorToggle = true;
135 | } else {
136 | data.strokeColorToggle = false;
137 | }
138 | }
139 | });
140 | strokeColorToggle.setSelected(true);
141 |
142 |
143 |
144 | JButton editColor = new JButton("Edit");
145 | editColor.setIconTextGap(0);
146 | editColor.setHorizontalTextPosition(SwingConstants.LEFT);
147 | editColor.setForeground(Color.BLACK);
148 | editColor.setBackground(new Color(227, 227, 227));
149 | editColor.setFont(new Font("Arial", Font.PLAIN, 9));
150 | editColor.setMargin(new Insets(0, 0, 0, 0));
151 | this.add(editColor, "cell 3 2,grow");
152 | editColor.addActionListener(new ActionListener() {
153 | public void actionPerformed(ActionEvent evt) {
154 | if (geCtr == null) {
155 | geCtr = new JDialog(parent);
156 | geCtr.setTitle("Gradient Editor");
157 | geCtr.setLocationRelativeTo(parent);
158 | ge = new GradientEditor(parent, geCtr, me);
159 | geCtr.setContentPane(ge);
160 | geCtr.pack();
161 | geCtr.setMinimumSize(geCtr.getSize());
162 | } else {
163 | ge.reBuildList();
164 | ge.setSelected();
165 | }
166 | geCtr.setVisible(true);
167 | }
168 | });
169 |
170 | JLabel lblLineWeight = new JLabel("Line Width");
171 | lblLineWeight.setForeground(Color.BLACK);
172 | lblLineWeight.setFont(new Font("Arial", Font.PLAIN, 8));
173 | lblLineWeight.setBackground(Color.LIGHT_GRAY);
174 | this.add(lblLineWeight, "cell 0 3,alignx left,aligny baseline");
175 |
176 | strokeWeight = new WideComboBox();
177 | strokeWeight.setMaximumSize(new Dimension(120, 32767));
178 | strokeWeight.setMaximumRowCount(100);
179 | strokeWeight.setForeground(Color.BLACK);
180 | strokeWeight.setBackground(UIManager.getColor("CheckBox.background"));
181 | strokeWeight.setFont(new Font("Arial", Font.PLAIN, 9));
182 | this.add(strokeWeight, "cell 0 4 3 1,growx");
183 | strokeWeight.addActionListener(new ActionListener() {
184 | public void actionPerformed(ActionEvent e) {
185 | WideComboBox cb = (WideComboBox) e.getSource();
186 | String item = (String) cb.getSelectedItem();
187 | data.strokeWeightSelection = parent.attributes.getName(item);
188 | if (data.strokeWeightSelection != null) {
189 | String unit = parent.attributes.getUnit(data.strokeWeightSelection);
190 | if (unit.contains("none")) {
191 | unit = "";
192 | }
193 | data.selectedStrokeWeightUnit = unit;
194 | }
195 | }
196 | });
197 |
198 | JCheckBox strokeWeightToggle = new JCheckBox("");
199 | strokeWeightToggle.setForeground(Color.BLACK);
200 | strokeWeightToggle.setBackground(Color.LIGHT_GRAY);
201 | strokeWeightToggle.setFont(new Font("Arial", Font.PLAIN, 9));
202 | this.add(strokeWeightToggle, "cell 3 4,growx");
203 | strokeWeightToggle.addChangeListener(new ChangeListener() {
204 | public void stateChanged(ChangeEvent evt) {
205 | JCheckBox cb = (JCheckBox) evt.getSource();
206 | if (cb.isSelected()) {
207 | data.strokeWeightToggle = true;
208 | } else {
209 | data.strokeWeightToggle = false;
210 | }
211 | }
212 | });
213 | strokeWeightToggle.setSelected(true);
214 |
215 | RangeSlider slider = new RangeSlider();
216 | slider.setValue(1);
217 | slider.setUpperValue(10);
218 | slider.setMinimum(0);
219 | slider.setMaximum(20);
220 | slider.setMaximumSize(new Dimension(120, 32767));
221 | this.add(slider, "cell 0 5 3 1,growx");
222 | slider.addChangeListener(new ChangeListener() {
223 | public void stateChanged(ChangeEvent evt) {
224 | RangeSlider slider = (RangeSlider) evt.getSource();
225 | data.strokeWeightMin = slider.getValue();
226 | data.strokeWeightMax = slider.getUpperValue();
227 | }
228 | });
229 |
230 | ArrayList fields = parent.attributes.getSelectedFieldNames();
231 | for (String string : fields) {
232 | strokeWeight.addItem(string);
233 | strokeColor.addItem(string);
234 | }
235 |
236 | strokeWeight.removeItem(parent.attributes.getIndexAlias());
237 |
238 | if (data.strokeWeightSelection == null) {
239 | strokeWeight.setEnabled(false);
240 | strokeWeightToggle.setSelected(false);
241 | strokeWeightToggle.setEnabled(false);
242 | }
243 |
244 |
245 | // UNDERLAY
246 | // ===================
247 |
248 | JSpinner ghostWeight = new JSpinner();
249 | ghostWeight.setForeground(Color.BLACK);
250 | ghostWeight.setBackground(Color.LIGHT_GRAY);
251 | ghostWeight.setFont(new Font("Arial", Font.PLAIN, 9));
252 | ghostWeight.setModel(new SpinnerNumberModel(1, 1, 100, 1));
253 | ghostWeight.setToolTipText("");
254 | ToolTipManager.sharedInstance().registerComponent(ghostWeight);
255 | ghostWeight.addChangeListener(new ChangeListener() {
256 | public void stateChanged(ChangeEvent evt) {
257 | JSpinner spin = (JSpinner) evt.getSource();
258 | data.ghostWeight = (Integer) spin.getValue();
259 | }
260 | });
261 |
262 | // Underlay label
263 | JLabel lblUnderlaySubheader = new JLabel("Underlay");
264 | lblUnderlaySubheader.setForeground(Color.BLACK);
265 | lblUnderlaySubheader.setFont(new Font("Arial", Font.BOLD, 9));
266 | lblUnderlaySubheader.setBackground(Color.LIGHT_GRAY);
267 | this.add(lblUnderlaySubheader, "cell 0 7,alignx left,aligny baseline");
268 | //
269 |
270 | JLabel lblLineThickness = new JLabel("Line Width");
271 | lblLineThickness.setForeground(Color.BLACK);
272 | lblLineThickness.setFont(new Font("Arial", Font.PLAIN, 8));
273 | lblLineThickness.setBackground(Color.LIGHT_GRAY);
274 | this.add(lblLineThickness, "cell 0 8,alignx left,aligny baseline");
275 |
276 | JLabel lblOpac = new JLabel("Opacity (%)");
277 | lblOpac.setForeground(Color.BLACK);
278 | lblOpac.setFont(new Font("Arial", Font.PLAIN, 8));
279 | lblOpac.setBackground(Color.LIGHT_GRAY);
280 | this.add(lblOpac, "cell 1 8,alignx left,aligny baseline");
281 | ghostWeight.setValue(2);
282 | this.add(ghostWeight, "flowx,cell 0 9");
283 |
284 | JCheckBox check = new JCheckBox("");
285 | check.setForeground(Color.BLACK);
286 | check.setBackground(Color.LIGHT_GRAY);
287 | check.setFont(new Font("Arial", Font.PLAIN, 9));
288 | check.setToolTipText("");
289 | ToolTipManager.sharedInstance().registerComponent(check);
290 | this.add(check, "cell 3 9,growx");
291 | check.addChangeListener(new ChangeListener() {
292 | public void stateChanged(ChangeEvent evt) {
293 | JCheckBox cb = (JCheckBox) evt.getSource();
294 | if (cb.isSelected()) {
295 | data.ghost = true;
296 | } else {
297 | data.ghost = false;
298 | }
299 | }
300 | });
301 |
302 | final JButton colorButton = new JButton("");
303 | add(colorButton, "cell 2 9,grow");
304 | colorButton.setMinimumSize(new Dimension(15, 15));
305 | colorButton.setMaximumSize(new Dimension(15, 15));
306 | colorButton.setBackground(data.ghostColor);
307 | colorButton.setMargin(new Insets(0, 0, 0, 0));
308 | colorButton.addActionListener(new ActionListener() {
309 | public void actionPerformed(ActionEvent evt) {
310 | final JColorChooser colorChooser = new JColorChooser();
311 | JDialog maxDialog = JColorChooser.createDialog((Component) evt.getSource(), "Pick a Color", true, // modal
312 | colorChooser, new ActionListener() {
313 |
314 | @Override
315 | public void actionPerformed(ActionEvent e) {
316 | data.ghostColor = colorChooser.getColor();
317 | colorButton.setBackground(data.ghostColor);
318 | }
319 | }, new ActionListener() {
320 | @Override
321 | public void actionPerformed(ActionEvent event) {
322 | }
323 | });
324 | maxDialog.setVisible(true);
325 | }
326 | });
327 |
328 | JSpinner AlphaValue = new JSpinner();
329 | AlphaValue.setForeground(Color.BLACK);
330 | AlphaValue.setBackground(Color.LIGHT_GRAY);
331 | AlphaValue.setFont(new Font("Arial", Font.PLAIN, 9));
332 | AlphaValue.setModel(new SpinnerNumberModel(1, 1, 100, 1));
333 | AlphaValue.setToolTipText("");
334 | ToolTipManager.sharedInstance().registerComponent(AlphaValue);
335 | AlphaValue.addChangeListener(new ChangeListener() {
336 | public void stateChanged(ChangeEvent evt) {
337 | JSpinner spin = (JSpinner) evt.getSource();
338 | data.ghostAlpha = (Integer) spin.getValue() * 255 / 100; // scale back to [0-255]
339 | }
340 | });
341 | AlphaValue.setValue(15);
342 | this.add(AlphaValue, "flowx,cell 1 9");
343 | }
344 | }
345 |
--------------------------------------------------------------------------------
/src/gui/PointPanel.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 |
22 | package gui;
23 |
24 | import javax.swing.JPanel;
25 |
26 | import main.DesktopPane;
27 | import main.SketchData;
28 | import net.miginfocom.swing.MigLayout;
29 |
30 | import javax.swing.JButton;
31 | import javax.swing.JCheckBox;
32 | import javax.swing.JDialog;
33 | import javax.swing.JLabel;
34 | import javax.swing.SwingConstants;
35 | import javax.swing.UIManager;
36 |
37 | import java.awt.Color;
38 | import java.awt.Dimension;
39 | import java.awt.Font;
40 | import java.awt.Insets;
41 | import java.awt.event.ActionEvent;
42 | import java.awt.event.ActionListener;
43 | import java.util.ArrayList;
44 |
45 | import javax.swing.event.ChangeEvent;
46 | import javax.swing.event.ChangeListener;
47 |
48 | public class PointPanel extends JPanel {
49 |
50 | /**
51 | *
52 | */
53 | private static final long serialVersionUID = 1L;
54 |
55 | DesktopPane parent;
56 | SketchData data;
57 |
58 | public WideComboBox pointColor;
59 | public WideComboBox pointSize;
60 | public WideComboBox colorRampList;
61 | GradientEditor ge;
62 | JDialog geCtr;
63 | PointPanel me;
64 |
65 | public PointPanel(DesktopPane father) {
66 | parent = father;
67 | data = parent.data;
68 | me = this;
69 |
70 | setLayout(new MigLayout("insets 0", "[grow][]", "[][]"));
71 |
72 | JLabel lblPointColor = new JLabel("Point Color");
73 | lblPointColor.setForeground(Color.BLACK);
74 | lblPointColor.setFont(new Font("Arial", Font.PLAIN, 8));
75 | lblPointColor.setBackground(Color.LIGHT_GRAY);
76 | this.add(lblPointColor, "cell 0 0,alignx left,aligny baseline");
77 |
78 | // 2 - color ramp list
79 | colorRampList = new WideComboBox(parent.colors.colorRampList.toArray());
80 | colorRampList.setMaximumSize(new Dimension(120, 32767));
81 | colorRampList.setMaximumRowCount(100);
82 | colorRampList.setForeground(Color.BLACK);
83 | colorRampList.setBackground(UIManager.getColor("CheckBox.background"));
84 | colorRampList.setFont(new Font("Arial", Font.PLAIN, 9));
85 | this.add(colorRampList, "cell 0 2,growx");
86 | colorRampList.addActionListener(new ActionListener() {
87 | public void actionPerformed(ActionEvent e) {
88 | WideComboBox comboBox = (WideComboBox) e.getSource();
89 | parent.data.selectedPointSwatch = (int) comboBox.getSelectedIndex();
90 | }
91 | });
92 |
93 | // 1 - point color field name
94 | pointColor = new WideComboBox();
95 | pointColor.setMaximumSize(new Dimension(120, 32767));
96 | pointColor.setMaximumRowCount(100);
97 | pointColor.setForeground(Color.BLACK);
98 | pointColor.setBackground(UIManager.getColor("CheckBox.background"));
99 | pointColor.setFont(new Font("Arial", Font.PLAIN, 9));
100 | this.add(pointColor, "cell 0 1,growx");
101 | pointColor.addActionListener(new ActionListener() {
102 | public void actionPerformed(ActionEvent e) {
103 | WideComboBox cb = (WideComboBox) e.getSource();
104 | String item = (String) cb.getSelectedItem();
105 |
106 | if(item.equals("Identifier")) colorRampList.setEnabled(false);
107 | else colorRampList.setEnabled(true);
108 |
109 | data.pointColorSelection = parent.attributes.getName(item);
110 | }
111 | });
112 |
113 |
114 |
115 | JButton editColor = new JButton("Edit");
116 | editColor.setIconTextGap(0);
117 | editColor.setHorizontalTextPosition(SwingConstants.LEFT);
118 | editColor.setForeground(Color.BLACK);
119 | editColor.setBackground(new Color(227, 227, 227));
120 | editColor.setFont(new Font("Arial", Font.PLAIN, 9));
121 | editColor.setMargin(new Insets(0, 0, 0, 0));
122 | this.add(editColor, "cell 1 2,grow");
123 | editColor.addActionListener(new ActionListener() {
124 | public void actionPerformed(ActionEvent evt) {
125 | if (geCtr == null) {
126 | geCtr = new JDialog(parent);
127 | geCtr.setTitle("Gradient Editor");
128 | geCtr.setLocationRelativeTo(parent);
129 | ge = new GradientEditor(parent, geCtr, me);
130 | geCtr.setContentPane(ge);
131 | geCtr.pack();
132 | geCtr.setMinimumSize(geCtr.getSize());
133 | } else {
134 | ge.reBuildList();
135 | ge.setSelected();
136 | }
137 | geCtr.setVisible(true);
138 | }
139 | });
140 |
141 | JLabel lblPointSize = new JLabel("Point Size");
142 | lblPointSize.setForeground(Color.BLACK);
143 | lblPointSize.setFont(new Font("Arial", Font.PLAIN, 8));
144 | lblPointSize.setBackground(Color.LIGHT_GRAY);
145 | this.add(lblPointSize, "cell 0 3,alignx left,aligny baseline");
146 |
147 | pointSize = new WideComboBox();
148 | pointSize.setMaximumSize(new Dimension(120, 32767));
149 | pointSize.setMaximumRowCount(100);
150 | pointSize.setForeground(Color.BLACK);
151 | pointSize.setBackground(UIManager.getColor("CheckBox.background"));
152 | pointSize.setFont(new Font("Arial", Font.PLAIN, 9));
153 | this.add(pointSize, "cell 0 4,growx");
154 | pointSize.addActionListener(new ActionListener() {
155 | public void actionPerformed(ActionEvent e) {
156 | WideComboBox cb = (WideComboBox) e.getSource();
157 | String item = (String) cb.getSelectedItem();
158 | data.pointSizeSelection = parent.attributes.getName(item);
159 | }
160 | });
161 |
162 | JCheckBox pointColorToggle = new JCheckBox("");
163 | pointColorToggle.setForeground(Color.BLACK);
164 | pointColorToggle.setBackground(Color.LIGHT_GRAY);
165 | pointColorToggle.setFont(new Font("Arial", Font.PLAIN, 9));
166 | this.add(pointColorToggle, "cell 1 1,growx");
167 | pointColorToggle.addChangeListener(new ChangeListener() {
168 | public void stateChanged(ChangeEvent evt) {
169 | JCheckBox cb = (JCheckBox) evt.getSource();
170 | if (cb.isSelected()) {
171 | data.pointColorToggle = true;
172 | } else {
173 | data.pointColorToggle = false;
174 | }
175 | }
176 | });
177 | pointColorToggle.setSelected(false);
178 |
179 | JCheckBox pointSizeToggle = new JCheckBox("");
180 | pointSizeToggle.setForeground(Color.BLACK);
181 | pointSizeToggle.setBackground(Color.LIGHT_GRAY);
182 | pointSizeToggle.setFont(new Font("Arial", Font.PLAIN, 9));
183 | this.add(pointSizeToggle, "cell 1 4,growx");
184 | pointSizeToggle.addChangeListener(new ChangeListener() {
185 | public void stateChanged(ChangeEvent evt) {
186 | JCheckBox cb = (JCheckBox) evt.getSource();
187 | if (cb.isSelected()) {
188 | data.pointSizeToggle = true;
189 | } else {
190 | data.pointSizeToggle = false;
191 | }
192 | }
193 | });
194 | pointSizeToggle.setSelected(false);
195 |
196 | RangeSlider slider = new RangeSlider();
197 | slider.setValue(1);
198 | slider.setUpperValue(10);
199 | slider.setMinimum(0);
200 | slider.setMaximum(30);
201 | slider.setMaximumSize(new Dimension(120, 32767));
202 | this.add(slider, "cell 0 5 2 1,growx");
203 | slider.addChangeListener(new ChangeListener() {
204 | public void stateChanged(ChangeEvent evt) {
205 | RangeSlider slider = (RangeSlider) evt.getSource();
206 | data.pointSizeMin = slider.getValue();
207 | data.pointSizeMax = slider.getUpperValue();
208 | }
209 | });
210 |
211 | ArrayList fields = parent.attributes.getSelectedFieldNames();
212 | for (String s : fields) {
213 | pointColor.addItem(s);
214 | pointSize.addItem(s);
215 | }
216 | pointSize.removeItem(parent.attributes.getIndexAlias());
217 |
218 | if (data.pointSizeSelection == null) {
219 | pointSize.setEnabled(false);
220 | pointSizeToggle.setSelected(false);
221 | pointSizeToggle.setEnabled(false);
222 | }
223 |
224 | }
225 | }
226 |
--------------------------------------------------------------------------------
/src/gui/RangeSlider.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 |
22 | package gui;
23 |
24 | import javax.swing.JSlider;
25 |
26 | /**
27 | * An extension of JSlider to select a range of values using two thumb controls.
28 | * The thumb controls are used to select the lower and upper value of a range
29 | * with predetermined minimum and maximum values.
30 | *
31 | *
32 | * Note that RangeSlider makes use of the default BoundedRangeModel, which
33 | * supports an inner range defined by a value and an extent. The upper value
34 | * returned by RangeSlider is simply the lower value plus the extent.
35 | *
36 | */
37 | @SuppressWarnings("serial")
38 | public class RangeSlider extends JSlider {
39 | /**
40 | * Constructs a RangeSlider with default minimum and maximum values of 0 and
41 | * 100.
42 | */
43 | public RangeSlider() {
44 | initSlider();
45 | }
46 |
47 | /**
48 | * Constructs a RangeSlider with the specified default minimum and maximum
49 | * values.
50 | */
51 | public RangeSlider(int min, int max) {
52 | super(min, max);
53 | initSlider();
54 | }
55 |
56 | /**
57 | * Initializes the slider by setting default properties.
58 | */
59 | private void initSlider() {
60 | setOrientation(HORIZONTAL);
61 | }
62 |
63 | /**
64 | * Overrides the superclass method to install the UI delegate to draw two
65 | * thumbs.
66 | */
67 | @Override
68 | public void updateUI() {
69 | setUI(new RangeSliderUI(this));
70 | // Update UI for slider labels. This must be called after updating the
71 | // UI of the slider. Refer to JSlider.updateUI().
72 | updateLabelUIs();
73 | }
74 |
75 | /**
76 | * Returns the lower value in the range.
77 | */
78 | @Override
79 | public int getValue() {
80 | return super.getValue();
81 | }
82 |
83 | /**
84 | * Sets the lower value in the range.
85 | */
86 | @Override
87 | public void setValue(int value) {
88 | int oldValue = getValue();
89 | if (oldValue == value) {
90 | return;
91 | }
92 | // Compute new value and extent to maintain upper value.
93 | int oldExtent = getExtent();
94 | int newValue = Math.min(Math.max(getMinimum(), value), oldValue + oldExtent);
95 | int newExtent = oldExtent + oldValue - newValue;
96 | // Set new value and extent, and fire a single change event.
97 | getModel().setRangeProperties(newValue, newExtent, getMinimum(), getMaximum(), getValueIsAdjusting());
98 | }
99 |
100 | /**
101 | * Returns the upper value in the range.
102 | */
103 | public int getUpperValue() {
104 | return getValue() + getExtent();
105 | }
106 |
107 | /**
108 | * Sets the upper value in the range.
109 | */
110 | public void setUpperValue(int value) {
111 | // Compute new extent.
112 | int lowerValue = getValue();
113 | int newExtent = Math.min(Math.max(0, value - lowerValue), getMaximum() - lowerValue);
114 | // Set extent to set upper value.
115 | setExtent(newExtent);
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/src/gui/VectorPanel.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 | package gui;
22 |
23 | import javax.swing.JPanel;
24 |
25 | import main.DesktopPane;
26 | import main.SketchData;
27 | import utils.Field;
28 | import net.miginfocom.swing.MigLayout;
29 |
30 | import javax.swing.JButton;
31 | import javax.swing.JCheckBox;
32 | import javax.swing.JDialog;
33 | import javax.swing.JLabel;
34 | import javax.swing.SwingConstants;
35 | import javax.swing.UIManager;
36 |
37 | import java.awt.Color;
38 | import java.awt.Dimension;
39 | import java.awt.Font;
40 | import java.awt.Insets;
41 | import java.awt.event.ActionEvent;
42 | import java.awt.event.ActionListener;
43 | import java.util.ArrayList;
44 |
45 | import javax.swing.event.ChangeEvent;
46 | import javax.swing.event.ChangeListener;
47 |
48 | public class VectorPanel extends JPanel {
49 |
50 | /**
51 | *
52 | */
53 | private static final long serialVersionUID = 1L;
54 |
55 | DesktopPane parent;
56 | SketchData data;
57 |
58 | public WideComboBox vectorLength;
59 | public WideComboBox headingField;
60 | public WideComboBox colorRampList;
61 | JCheckBox vectorCheck;
62 | GradientEditor ge;
63 | JDialog geCtr;
64 | VectorPanel me;
65 |
66 | public VectorPanel(DesktopPane father) {
67 | parent = father;
68 | data = parent.data;
69 | me = this;
70 |
71 | setLayout(new MigLayout("insets 0", "[grow][]", "[]"));
72 |
73 | JLabel lblDirection = new JLabel("Direction");
74 | lblDirection.setForeground(Color.BLACK);
75 | lblDirection.setFont(new Font("Arial", Font.PLAIN, 8));
76 | lblDirection.setBackground(Color.LIGHT_GRAY);
77 | this.add(lblDirection, "cell 0 0,alignx left,aligny baseline");
78 |
79 | headingField = new WideComboBox();
80 | headingField.setMaximumSize(new Dimension(120, 32767));
81 | headingField.setMaximumRowCount(100);
82 | headingField.setForeground(Color.BLACK);
83 | headingField.setBackground(UIManager.getColor("CheckBox.background"));
84 | headingField.setFont(new Font("Arial", Font.PLAIN, 9));
85 |
86 | this.add(headingField, "cell 0 1,growx");
87 |
88 | headingField.addActionListener(new ActionListener() {
89 | public void actionPerformed(ActionEvent e) {
90 | WideComboBox cb = (WideComboBox) e.getSource();
91 | String item = (String) cb.getSelectedItem();
92 | data.headingFieldSelection = parent.attributes.getName(item);
93 | }
94 | });
95 |
96 | vectorCheck = new JCheckBox("");
97 | vectorCheck.setForeground(Color.BLACK);
98 | vectorCheck.setBackground(Color.LIGHT_GRAY);
99 | vectorCheck.setFont(new Font("Arial", Font.PLAIN, 9));
100 |
101 | this.add(vectorCheck, "cell 1 1,growx");
102 |
103 | vectorCheck.addChangeListener(new ChangeListener() {
104 | public void stateChanged(ChangeEvent evt) {
105 | JCheckBox cb = (JCheckBox) evt.getSource();
106 | if (cb.isSelected()) {
107 | data.vectorToggle = true;
108 | } else {
109 | data.vectorToggle = false;
110 | }
111 | }
112 | });
113 | vectorCheck.setSelected(false);
114 |
115 | JLabel lblColor = new JLabel("Vector Color");
116 | lblColor.setForeground(Color.BLACK);
117 | lblColor.setFont(new Font("Arial", Font.PLAIN, 8));
118 | lblColor.setBackground(Color.LIGHT_GRAY);
119 | this.add(lblColor, "cell 0 2,alignx left,aligny baseline");
120 |
121 | // 2 - color ramp list
122 | colorRampList = new WideComboBox(parent.colors.colorRampList.toArray());
123 | colorRampList.setMaximumSize(new Dimension(120, 32767));
124 | colorRampList.setMaximumRowCount(100);
125 | colorRampList.setForeground(Color.BLACK);
126 | colorRampList.setBackground(UIManager.getColor("CheckBox.background"));
127 | colorRampList.setFont(new Font("Arial", Font.PLAIN, 9));
128 | this.add(colorRampList, "cell 0 4,growx");
129 | colorRampList.addActionListener(new ActionListener() {
130 | public void actionPerformed(ActionEvent e) {
131 | WideComboBox comboBox = (WideComboBox) e.getSource();
132 | parent.data.selectedVectorSwatch = (int) comboBox.getSelectedIndex();
133 | }
134 | });
135 |
136 | // 1 - vector color field name
137 | WideComboBox vectorColor = new WideComboBox();
138 | vectorColor.setMaximumSize(new Dimension(120, 32767));
139 | vectorColor.setMaximumRowCount(100);
140 | vectorColor.setForeground(Color.BLACK);
141 | vectorColor.setBackground(UIManager.getColor("CheckBox.background"));
142 | vectorColor.setFont(new Font("Arial", Font.PLAIN, 9));
143 | this.add(vectorColor, "cell 0 3,growx");
144 | vectorColor.addActionListener(new ActionListener() {
145 | public void actionPerformed(ActionEvent e) {
146 | WideComboBox cb = (WideComboBox) e.getSource();
147 | String item = (String) cb.getSelectedItem();
148 |
149 | if(item.equals("Identifier")) colorRampList.setEnabled(false);
150 | else colorRampList.setEnabled(true);
151 |
152 | data.vectorColorSelection = parent.attributes.getName(item);
153 | }
154 | });
155 |
156 | JCheckBox vectorColorCheck = new JCheckBox("");
157 | vectorColorCheck.setForeground(Color.BLACK);
158 | vectorColorCheck.setBackground(Color.LIGHT_GRAY);
159 | vectorColorCheck.setFont(new Font("Arial", Font.PLAIN, 9));
160 |
161 | this.add(vectorColorCheck, "cell 1 3,growx");
162 | vectorColorCheck.addChangeListener(new ChangeListener() {
163 | public void stateChanged(ChangeEvent evt) {
164 | JCheckBox cb = (JCheckBox) evt.getSource();
165 | if (cb.isSelected()) {
166 | data.vectorColorToggle = true;
167 | } else {
168 | data.vectorColorToggle = false;
169 | }
170 | }
171 | });
172 | vectorColorCheck.setSelected(false);
173 |
174 | JButton editColor = new JButton("Edit");
175 | editColor.setIconTextGap(0);
176 | editColor.setHorizontalTextPosition(SwingConstants.LEFT);
177 | editColor.setForeground(Color.BLACK);
178 | editColor.setBackground(new Color(227, 227, 227));
179 | editColor.setFont(new Font("Arial", Font.PLAIN, 9));
180 | editColor.setMargin(new Insets(0, 0, 0, 0));
181 | this.add(editColor, "cell 1 4,grow");
182 | editColor.addActionListener(new ActionListener() {
183 | public void actionPerformed(ActionEvent evt) {
184 | if (geCtr == null) {
185 | geCtr = new JDialog(parent);
186 | geCtr.setTitle("Gradient Editor");
187 | geCtr.setLocationRelativeTo(parent);
188 | ge = new GradientEditor(parent, geCtr, me);
189 | geCtr.setContentPane(ge);
190 | geCtr.pack();
191 | geCtr.setMinimumSize(geCtr.getSize());
192 | } else {
193 | ge.reBuildList();
194 | ge.setSelected();
195 | }
196 | geCtr.setVisible(true);
197 | }
198 | });
199 |
200 | JLabel lblLength = new JLabel("Vector Length");
201 | lblLength.setForeground(Color.BLACK);
202 | lblLength.setFont(new Font("Arial", Font.PLAIN, 8));
203 | lblLength.setBackground(Color.LIGHT_GRAY);
204 | this.add(lblLength, "cell 0 5,alignx left,aligny baseline");
205 |
206 | vectorLength = new WideComboBox();
207 | vectorLength.setMaximumSize(new Dimension(120, 32767));
208 | vectorLength.setMaximumRowCount(100);
209 | vectorLength.setForeground(Color.BLACK);
210 | vectorLength.setBackground(UIManager.getColor("CheckBox.background"));
211 | vectorLength.setFont(new Font("Arial", Font.PLAIN, 9));
212 |
213 | this.add(vectorLength, "cell 0 6,growx");
214 |
215 | vectorLength.addActionListener(new ActionListener() {
216 | public void actionPerformed(ActionEvent e) {
217 | WideComboBox cb = (WideComboBox) e.getSource();
218 | String item = (String) cb.getSelectedItem();
219 | data.vectorFieldSelection = parent.attributes.getName(item);
220 | }
221 | });
222 |
223 | JCheckBox vectorLengthCheck = new JCheckBox("");
224 | vectorLengthCheck.setForeground(Color.BLACK);
225 | vectorLengthCheck.setBackground(Color.LIGHT_GRAY);
226 | vectorLengthCheck.setFont(new Font("Arial", Font.PLAIN, 9));
227 |
228 | this.add(vectorLengthCheck, "cell 1 6,growx");
229 | vectorLengthCheck.addChangeListener(new ChangeListener() {
230 | public void stateChanged(ChangeEvent evt) {
231 | JCheckBox cb = (JCheckBox) evt.getSource();
232 | if (cb.isSelected()) {
233 | data.vectorLengthToggle = true;
234 | } else {
235 | data.vectorLengthToggle = false;
236 | }
237 | }
238 | });
239 | vectorLengthCheck.setSelected(false);
240 |
241 | RangeSlider slider = new RangeSlider();
242 | slider.setValue(5);
243 | slider.setUpperValue(20);
244 | slider.setMinimum(0);
245 | slider.setMaximum(50);
246 | slider.setMaximumSize(new Dimension(120, 32767));
247 | this.add(slider, "cell 0 7 2 1,growx");
248 | slider.addChangeListener(new ChangeListener() {
249 | public void stateChanged(ChangeEvent evt) {
250 | RangeSlider slider = (RangeSlider) evt.getSource();
251 | data.vectorLengthMin = slider.getValue();
252 | data.vectorLengthMax = slider.getUpperValue();
253 | }
254 | });
255 |
256 | ArrayList fields = parent.attributes.getSelectedFields();
257 | for (Field field : fields) {
258 | String name = field.getAlias();
259 | vectorColor.addItem(name);
260 |
261 | float min = field.getMin();
262 | float max = field.getMax();
263 |
264 | if (max - min >= 345f && max - min <= 375f) {
265 | headingField.addItem(name);
266 | } else {
267 | vectorLength.addItem(name);
268 | }
269 | }
270 |
271 | headingField.removeItem(parent.attributes.getIndexAlias());
272 | vectorLength.removeItem(parent.attributes.getIndexAlias());
273 |
274 | if (headingField.getItemCount() == 0) {
275 | vectorCheck.setEnabled(false);
276 | headingField.setEnabled(false);
277 | vectorLength.setEnabled(false);
278 | vectorLengthCheck.setEnabled(false);
279 | vectorColor.setEnabled(false);
280 | vectorColorCheck.setEnabled(false);
281 | }
282 |
283 | }
284 | }
285 |
--------------------------------------------------------------------------------
/src/gui/WideComboBox.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 |
22 | package gui;
23 |
24 | import java.awt.Dimension;
25 | import java.util.Vector;
26 |
27 | import javax.swing.ComboBoxModel;
28 | import javax.swing.JComboBox;
29 |
30 | //makes the popup wide enough for listed items
31 | @SuppressWarnings("serial")
32 | public class WideComboBox extends JComboBox {
33 | public WideComboBox() {
34 | }
35 |
36 | public WideComboBox(final Object items[]) {
37 | super(items);
38 | }
39 |
40 | @SuppressWarnings("rawtypes")
41 | public WideComboBox(Vector items) {
42 | super(items);
43 | }
44 |
45 | public WideComboBox(ComboBoxModel aModel) {
46 | super(aModel);
47 | }
48 |
49 | private boolean layingOut = false;
50 |
51 | public void doLayout() {
52 | try {
53 | layingOut = true;
54 | super.doLayout();
55 | } finally {
56 | layingOut = false;
57 | }
58 | }
59 |
60 | public Dimension getSize() {
61 | Dimension dim = super.getSize();
62 | if (!layingOut)
63 | dim.width = Math.max(dim.width, getPreferredSize().width);
64 | return dim;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/Colors.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 |
22 | package main;
23 |
24 | import java.awt.Color;
25 | import java.awt.Graphics2D;
26 | import java.awt.Rectangle;
27 | import java.awt.image.BufferedImage;
28 | import java.util.ArrayList;
29 | import java.util.List;
30 |
31 | import javax.swing.ImageIcon;
32 |
33 | import org.gicentre.utils.colour.ColourTable;
34 |
35 | public class Colors {
36 |
37 | // swatch dimensions, small for control panel, large for gradient editor
38 | public static final int LARGE_WIDTH = 300;
39 | public static final int LARGE_HEIGHT = 20;
40 | public static final int SMALL_WIDTH = 95;
41 | public static final int SMALL_HEIGHT = 12;
42 |
43 | DesktopPane parent;
44 | SketchData data;
45 | Color[] colorList12 = {
46 | // Brewer for up to 12 classes
47 | new Color(166, 206, 227), new Color(31, 120, 180), new Color(178, 223, 138), new Color(51, 160, 44),
48 | new Color(251, 154, 153), new Color(227, 26, 28), new Color(253, 191, 111), new Color(255, 127, 0),
49 | new Color(202, 178, 214), new Color(106, 61, 154), new Color(255, 255, 153), new Color(177, 89, 40), };
50 | Color[] colorList9 = {
51 | // Brewer for up to 9 classes
52 | new Color(228, 26, 28),
53 | // new Color(55,126,184),
54 | new Color(26, 85, 210),
55 | // new Color(77,175,74),
56 | new Color(34, 188, 8),
57 | // new Color(152,78,163),
58 | new Color(176, 2, 207),
59 | // new Color(255,127,0),
60 | new Color(255, 105, 51), new Color(255, 255, 51), new Color(166, 86, 40), new Color(247, 129, 191),
61 | new Color(153, 153, 153), };
62 |
63 | public List coloursCont;
64 | public List colorRampList;
65 | public List largeRampList;
66 |
67 | private Color legendColor = Color.WHITE;
68 |
69 | public Colors(DesktopPane father) {
70 | parent = father;
71 |
72 | ColourTable bToP = new ColourTable();
73 | bToP.addContinuousColourRule((float) (0 / 1), 45, 0, 255);
74 | bToP.addContinuousColourRule((float) (1 / 1), 255, 0, 38);
75 |
76 | ColourTable bToG = new ColourTable();
77 | bToG.addContinuousColourRule((float) (0 / 1), Color.blue.getRGB());
78 | bToG.addContinuousColourRule((float) (1 / 1), Color.green.getRGB());
79 |
80 | ColourTable yToR = new ColourTable();
81 | yToR.addContinuousColourRule((float) (0 / 1), Color.yellow.getRGB());
82 | yToR.addContinuousColourRule((float) (1 / 1), Color.red.getRGB());
83 |
84 | ColourTable yToG = new ColourTable();
85 | yToG.addContinuousColourRule((float) (0 / 1), Color.yellow.getRGB());
86 | yToG.addContinuousColourRule((float) (1 / 1), Color.green.getRGB());
87 |
88 | ColourTable spectrum = new ColourTable();
89 | spectrum.addContinuousColourRule((float) (0), 5, 0, 206);
90 | spectrum.addContinuousColourRule((float) (0.1), 2, 96, 206);
91 | spectrum.addContinuousColourRule((float) (0.2), 10, 204, 203);
92 | spectrum.addContinuousColourRule((float) (0.3), 48, 205, 184);
93 | spectrum.addContinuousColourRule((float) (0.4), 103, 203, 168);
94 | spectrum.addContinuousColourRule((float) (0.5), 181, 232, 73);
95 | spectrum.addContinuousColourRule((float) (0.6), 255, 252, 0);
96 | spectrum.addContinuousColourRule((float) (0.7), 254, 207, 5);
97 | spectrum.addContinuousColourRule((float) (0.8), 253, 154, 0);
98 | spectrum.addContinuousColourRule((float) (0.9), 255, 77, 1);
99 | spectrum.addContinuousColourRule((float) (1.0), 255, 0, 0);
100 |
101 | coloursCont = new ArrayList();
102 | coloursCont.add(bToP);
103 | coloursCont.add(bToG);
104 | coloursCont.add(yToR);
105 | coloursCont.add(yToG);
106 | coloursCont.add(spectrum);
107 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.YL_GN, 0, 1));
108 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.YL_GN_BU, 0, 1));
109 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.GN_BU, 0, 1));
110 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.BU_GN, 0, 1));
111 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.PU_BU_GN, 0, 1));
112 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.PU_BU, 0, 1));
113 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.BU_PU, 0, 1));
114 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.RD_PU, 0, 1));
115 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.PU_RD, 0, 1));
116 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.OR_RD, 0, 1));
117 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.YL_OR_RD, 0, 1));
118 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.YL_OR_BR, 0, 1));
119 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.PURPLES, 0, 1));
120 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.BLUES, 0, 1));
121 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.GREENS, 0, 1));
122 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.ORANGES, 0, 1));
123 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.REDS, 0, 1));
124 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.GREYS, 0, 1));
125 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.PU_OR, 0, 1));
126 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.BR_B_G, 0, 1));
127 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.P_R_GN, 0, 1));
128 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.PI_Y_G, 0, 1));
129 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.RD_BU, 0, 1));
130 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.RD_GY, 0, 1));
131 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.RD_YL_BU, 0, 1));
132 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.SPECTRAL, 0, 1));
133 | coloursCont.add(ColourTable.getPresetColourTable(ColourTable.RD_YL_GN, 0, 1));
134 |
135 | colorRampList = createSwatchList(coloursCont, "small");
136 | largeRampList = createSwatchList(coloursCont, "large");
137 | }
138 |
139 | public List createSwatchList(List list, String size) {
140 | int w, h;
141 | if (size.equals("large")) {
142 | w = LARGE_WIDTH;
143 | h = LARGE_HEIGHT;
144 | } else if (size.equals("small")) {
145 | w = SMALL_WIDTH;
146 | h = SMALL_HEIGHT;
147 | } else {
148 | return null;
149 | }
150 | return createSwatchList(list, w, h);
151 | }
152 |
153 | public List createSwatchList(List list, int width, int height) {
154 | List icons = new ArrayList();
155 | for (int i = 0; i < list.size(); i++) {
156 | icons.add(createSwatch(list.get(i), width, height));
157 | }
158 | return icons;
159 | }
160 |
161 | public ImageIcon createSwatch(ColourTable colorTable, String size) {
162 | int w, h;
163 | if (size.equals("large")) {
164 | w = LARGE_WIDTH;
165 | h = LARGE_HEIGHT;
166 | } else if (size.equals("small")) {
167 | w = SMALL_WIDTH;
168 | h = SMALL_HEIGHT;
169 | } else {
170 | return null;
171 | }
172 | return createSwatch(colorTable, w, h);
173 | }
174 |
175 | public ImageIcon createSwatch(ColourTable colorTable, int width, int height) {
176 | BufferedImage swatch = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
177 | Graphics2D g = swatch.createGraphics();
178 | for (int i = 0; i < width; i++) {
179 | Rectangle rect = new Rectangle(i, 0, 1, height);
180 | String string = Integer.toHexString(colorTable.findColour((float) i / width));
181 | string = string.substring(2, string.length());
182 | Color color = Color.decode("#" + string);
183 | g.setPaint(color);
184 | g.fill(rect);
185 | }
186 | return new ImageIcon(swatch);
187 |
188 | }
189 |
190 | public Color getTagColor(String key) {
191 | data = parent.data;
192 | int tagSize = parent.tagList.size();
193 | int index = parent.tagList.indexOf(key);
194 | Color color;
195 | if (tagSize <= 9) {
196 | color = colorList9[index];
197 | } else if (tagSize <= 12) {
198 | color = colorList12[index];
199 | } else {
200 | if (index > colorList12.length - 1) {
201 | float num = (((float) index - 12) / ((float) tagSize - 12)) * 255;
202 | int rgbNum = 255 - (int) num;
203 | color = new Color(rgbNum, rgbNum, rgbNum);
204 | } else {
205 | color = colorList12[index];
206 | }
207 | }
208 | return (color);
209 | }
210 |
211 | public void setLegendColor(Color c) {
212 | legendColor = c;
213 | }
214 |
215 | public Color getLegendColor() {
216 | return legendColor;
217 | }
218 |
219 | }
220 |
--------------------------------------------------------------------------------
/src/main/Histo.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 |
22 | package main;
23 |
24 | import javax.swing.JPanel;
25 |
26 | @SuppressWarnings("serial")
27 | public class Histo extends JPanel {
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/Recorder.java:
--------------------------------------------------------------------------------
1 | /*
2 | DYNAMO Animation Tool
3 | Copyright (C) 2016 Glenn Xavier
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 |
18 | */
19 |
20 | package main;
21 |
22 | import java.awt.event.ActionEvent;
23 | import java.awt.event.ActionListener;
24 | import java.io.File;
25 | import java.io.IOException;
26 | import java.nio.file.Files;
27 | import java.nio.file.Path;
28 | import java.text.DecimalFormat;
29 | import java.util.Comparator;
30 |
31 | import javax.swing.JPanel;
32 |
33 | import net.miginfocom.swing.MigLayout;
34 |
35 | import javax.swing.JToggleButton;
36 | import javax.swing.JButton;
37 | import javax.swing.JCheckBox;
38 | import javax.swing.JLabel;
39 | import javax.swing.Timer;
40 |
41 | import org.joda.time.DateTime;
42 | import javax.swing.JComboBox;
43 |
44 |
45 | public class Recorder extends JPanel {
46 |
47 | /**
48 | *
49 | */
50 | private static final long serialVersionUID = 1L;
51 | DesktopPane parent;
52 | SketchData data;
53 | int timeDelay = 10;
54 | ActionListener time;
55 | Timer timer;
56 | DateTime dateTime;
57 | JLabel timeLabel;
58 | JCheckBox chkTemp;
59 | JButton btnSave;
60 |
61 | public Recorder(DesktopPane father) {
62 | parent = father;
63 | data = father.data;
64 | setLayout(new MigLayout("", "[grow][][]", "[][][]"));
65 | enableRecorder();
66 |
67 | // checkbox to store frames
68 | chkTemp = new JCheckBox("Store frames");
69 | add(chkTemp, "cell 0 0 2,alignx left");
70 |
71 | timeLabel = new JLabel("00.00s");
72 | add(timeLabel, "cell 1 0 2,alignx right");
73 |
74 | final JToggleButton tglbtnRecord = new JToggleButton("Record");
75 | add(tglbtnRecord, "cell 0 1");
76 | tglbtnRecord.addActionListener(new ActionListener() {
77 | public void actionPerformed(ActionEvent evt) {
78 | data.save = !data.save;
79 | if (data.save){
80 | timer.start();
81 | btnSave.setEnabled(false);
82 | } else {
83 | timer.stop();
84 | btnSave.setEnabled(true);
85 | }
86 | }
87 | });
88 |
89 | JButton btnStop = new JButton("Stop");
90 | add(btnStop, "cell 1 1");
91 | btnStop.addActionListener(new ActionListener() {
92 | public void actionPerformed(ActionEvent evt) {
93 | if (data.save){
94 | timer.stop();
95 | data.save = !data.save;
96 | tglbtnRecord.setSelected(false);
97 | btnSave.setEnabled(true);
98 | }
99 | }
100 | });
101 |
102 | btnSave = new JButton("Save");
103 | btnSave.setEnabled(false);
104 | add(btnSave, "cell 2 1");
105 |
106 | // Hidden
107 | JComboBox comboBox = new JComboBox();
108 | // add(comboBox, "flowx,cell 0 2 3 1,growx");
109 | comboBox.addItem("h264 Baseline");
110 | comboBox.setEnabled(false);
111 |
112 | // Hidden
113 | JComboBox comboBox_1 = new JComboBox();
114 | // add(comboBox_1, "flowx,cell 0 2 3 1,growx");
115 | comboBox_1.addItem("30 fps");
116 | comboBox_1.setEnabled(false);
117 |
118 | btnSave.addActionListener(new ActionListener() {
119 | public void actionPerformed(ActionEvent evt) {
120 | try {
121 | new SequenceEncoder(parent, parent.animationTitle + parent.exportCounter + ".mp4",
122 | 0, data.frameCounter,
123 | !chkTemp.isSelected());
124 | } catch (IOException e) {
125 | e.printStackTrace();
126 | }
127 |
128 | data.frameCounter = 0;
129 | timeLabel.setText("00.00s");
130 | }
131 | });
132 | }
133 |
134 | public void enableRecorder() {
135 | time = new ActionListener() {
136 | @Override
137 | public void actionPerformed(ActionEvent evt) {
138 | double frames = ((double) data.frameCounter) / 25d;
139 | timeLabel.setText(new DecimalFormat("00.00").format(frames) + "s");
140 | }
141 | };
142 | timer = new Timer(timeDelay, time);
143 | }
144 | public void discardRecorder() {
145 | timer = null;
146 | data.frameCounter = 0;
147 | timeLabel.setText("00.00s");
148 |
149 | // Delete temp folder
150 | if(!chkTemp.isSelected()) {
151 | try {
152 | Files.walk(Path.of("export/temp/"+ parent.animationTitle + parent.exportCounter))
153 | .sorted(Comparator.reverseOrder())
154 | .map(Path::toFile)
155 | .forEach(File::delete);
156 | } catch (IOException e) {
157 | e.printStackTrace();
158 | }
159 | }
160 |
161 | }
162 |
163 | }
--------------------------------------------------------------------------------
/src/main/SequenceEncoder.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 |
22 | package main;
23 |
24 | import java.awt.image.BufferedImage;
25 | import java.beans.PropertyChangeEvent;
26 | import java.beans.PropertyChangeListener;
27 | import java.io.File;
28 | import java.io.IOException;
29 | import java.nio.ByteBuffer;
30 | import java.nio.file.Files;
31 | import java.nio.file.Path;
32 | import java.util.ArrayList;
33 | import java.util.Arrays;
34 | import java.util.Comparator;
35 | import java.util.concurrent.CancellationException;
36 | import java.util.concurrent.ExecutionException;
37 |
38 | import javax.imageio.ImageIO;
39 | import javax.swing.ProgressMonitor;
40 | import javax.swing.SwingWorker;
41 |
42 | import org.jcodec.codecs.h264.H264Encoder;
43 | import org.jcodec.codecs.h264.H264Utils;
44 | import org.jcodec.common.NIOUtils;
45 | import org.jcodec.common.SeekableByteChannel;
46 | import org.jcodec.common.model.ColorSpace;
47 | import org.jcodec.common.model.Picture;
48 | import org.jcodec.containers.mp4.Brand;
49 | import org.jcodec.containers.mp4.MP4Packet;
50 | import org.jcodec.containers.mp4.TrackType;
51 | import org.jcodec.containers.mp4.muxer.FramesMP4MuxerTrack;
52 | import org.jcodec.containers.mp4.muxer.MP4Muxer;
53 | import org.jcodec.scale.AWTUtil;
54 | import org.jcodec.scale.RgbToYuv420;
55 |
56 | public class SequenceEncoder implements PropertyChangeListener {
57 | private SeekableByteChannel ch;
58 | private Picture toEncode;
59 | private RgbToYuv420 transform;
60 | private H264Encoder encoder;
61 | private ArrayList spsList;
62 | private ArrayList ppsList;
63 | private FramesMP4MuxerTrack outTrack;
64 | private ByteBuffer _out;
65 | private int frameNo;
66 | private MP4Muxer muxer;
67 | private ProgressMonitor progressMonitor;
68 | DesktopPane parent;
69 | private int previousExportCounter;
70 | Task operation;
71 | int start;
72 | int end;
73 | boolean deleteTemp;
74 |
75 | public SequenceEncoder(DesktopPane father, String name, int s, int e, boolean del) throws IOException {
76 | parent = father;
77 | File file = new File("export/"+name);
78 | start = s;
79 | end = e;
80 | deleteTemp = del;
81 | previousExportCounter = parent.exportCounter;
82 | this.ch = NIOUtils.writableFileChannel(file);
83 |
84 | // Transform to convert between RGB and YUV
85 | transform = new RgbToYuv420(0, 0);
86 |
87 | // Muxer that will store the encoded frames
88 | muxer = new MP4Muxer(ch, Brand.MP4);
89 |
90 | // Add video track to muxer
91 | outTrack = muxer.addTrackForCompressed(TrackType.VIDEO, 25);
92 |
93 | // Allocate a buffer big enough to hold output frames
94 | _out = ByteBuffer.allocate(1920 * 1080 * 6);
95 |
96 | // Create an instance of encoder
97 | encoder = new H264Encoder();
98 |
99 | // Encoder extra data ( SPS, PPS ) to be stored in a special place of
100 | // MP4
101 | spsList = new ArrayList();
102 | ppsList = new ArrayList();
103 |
104 | progressMonitor = new ProgressMonitor(parent, "Encoding Video...", "", 0, 100);
105 | progressMonitor.setProgress(0);
106 | operation = new Task(this);
107 | operation.addPropertyChangeListener(this);
108 | operation.execute();
109 |
110 | }
111 |
112 | class Task extends SwingWorker {
113 |
114 | SequenceEncoder encoder;
115 |
116 | public Task(SequenceEncoder se) {
117 | encoder = se;
118 | }
119 |
120 | @Override
121 | protected Void doInBackground() throws Exception {
122 | for (int i = start; i < end; i++) {
123 | BufferedImage bi = ImageIO.read(new File(
124 | String.format("export/temp/" + parent.animationTitle + parent.exportCounter + "/temp%08d.jpeg", i)));
125 | encoder.encodeImage(bi);
126 | setProgress((int) (100 * i) / end);
127 | }
128 | encoder.finish();
129 | setProgress(100);
130 | parent.exportCounter++;
131 | return null;
132 | }
133 |
134 | public void done() {
135 | try {
136 | @SuppressWarnings("unused")
137 | Void result = get();
138 | System.out.println("Video Encoding Completed");
139 |
140 | if(deleteTemp) {
141 | // Delete temp folder
142 | Files.walk(Path.of("export/temp/"+ parent.animationTitle + previousExportCounter))
143 | .sorted(Comparator.reverseOrder())
144 | .map(Path::toFile)
145 | .forEach(File::delete);
146 | }
147 | } catch (InterruptedException e) {
148 |
149 | } catch (CancellationException e) {
150 | System.out.println("Encoding Cancelled...\n");
151 | } catch (ExecutionException e) {
152 | System.out.println("Encoding Failed: " + e.getCause());
153 | } catch (IOException e) {
154 | System.out.println("Failed to clear \"temp\" folder...\n");
155 | e.printStackTrace();
156 | }
157 | }
158 | }
159 |
160 | public void encodeImage(BufferedImage bi) throws IOException {
161 | if (toEncode == null) {
162 | toEncode = Picture.create(bi.getWidth(), bi.getHeight(), ColorSpace.YUV420);
163 | }
164 |
165 | // Perform conversion
166 | for (int i = 0; i < 3; i++)
167 | Arrays.fill(toEncode.getData()[i], 0);
168 | transform.transform(AWTUtil.fromBufferedImage(bi), toEncode);
169 |
170 | // Encode image into H.264 frame, the result is stored in '_out' buffer
171 | _out.clear();
172 | ByteBuffer result = encoder.encodeFrame(_out, toEncode);
173 |
174 | // Based on the frame above form correct MP4 packet
175 | spsList.clear();
176 | ppsList.clear();
177 | H264Utils.encodeMOVPacket(result, spsList, ppsList);
178 |
179 | // Add packet to video track
180 | outTrack.addFrame(new MP4Packet(result, frameNo, 25, 1, frameNo, true, null, frameNo, 0));
181 |
182 | frameNo++;
183 | }
184 |
185 | public void finish() throws IOException {
186 | // Push saved SPS/PPS to a special storage in MP4
187 | outTrack.addSampleEntry(H264Utils.createMOVSampleEntry(spsList, ppsList));
188 |
189 | // Write MP4 header and finalize recording
190 | muxer.writeHeader();
191 | NIOUtils.closeQuietly(ch);
192 |
193 |
194 | }
195 |
196 | @Override
197 | public void propertyChange(PropertyChangeEvent evt) {
198 | if ("progress" == evt.getPropertyName()) {
199 | int progress = (Integer) evt.getNewValue();
200 | progressMonitor.setProgress(progress);
201 | }
202 | if (progressMonitor.isCanceled()) {
203 | operation.cancel(true);
204 | }
205 |
206 | }
207 | }
208 |
--------------------------------------------------------------------------------
/src/main/Sketch.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 |
22 | package main;
23 |
24 | import java.net.URL;
25 | import java.util.ArrayList;
26 | import java.util.List;
27 | import java.util.Map.Entry;
28 |
29 | import gui.ControlPanel;
30 | import utils.PointRecord;
31 | import utils.Track;
32 |
33 | import com.jogamp.nativewindow.WindowClosingProtocol.WindowClosingMode;
34 | import com.jogamp.opengl.GLProfile;
35 |
36 | import org.joda.time.DateTime;
37 | import org.joda.time.Hours;
38 | import org.joda.time.Minutes;
39 | import org.joda.time.Seconds;
40 |
41 | import processing.core.PApplet;
42 | import processing.core.PShape;
43 | import processing.opengl.PJOGL;
44 | import de.fhpotsdam.unfolding.UnfoldingMap;
45 | import de.fhpotsdam.unfolding.events.EventDispatcher;
46 | import de.fhpotsdam.unfolding.geo.Location;
47 | import de.fhpotsdam.unfolding.utils.MapUtils;
48 | import de.fhpotsdam.unfolding.utils.ScreenPosition;
49 |
50 | public class Sketch extends PApplet {
51 | // Connect processing sketch to the rest of the application
52 | private DesktopPane parent;
53 | private SketchData data;
54 | private ControlPanel controlPanel;
55 |
56 | //
57 | public void setParent(DesktopPane father) {
58 | parent = father;
59 | data = parent.data;
60 | controlPanel = parent.controlPanel;
61 | }
62 |
63 | public Legend legend;
64 | public UnfoldingMap map;
65 | //
66 | public boolean leftMapNeeded = false;
67 | public boolean rightMapNeeded = false;
68 | public UnfoldingMap leftMap;
69 | public UnfoldingMap rightMap;
70 |
71 | int colorMin;
72 | int colorMax;
73 | int colorMid;
74 |
75 | EventDispatcher eventDispatcher;
76 |
77 | // RUN/EXIT BEHAVIOURS -----------------
78 | public void run(int x, int y) {
79 | String[] processingArgs = {"--location="+x+","+y, "DynamoVis Animation"};
80 | PApplet.runSketch(processingArgs, this);
81 | }
82 | // Overriden to prevent System.exit(0) command, that
83 | // shuts down the whole java environment
84 | @Override
85 | public void exitActual() {
86 | // minimize the window if it doesn't get disposed
87 | getSurface().setVisible(false);
88 |
89 | // hide timeline and control panel
90 | parent.controlContainer.setVisible(false);
91 | parent.timelineContainer.setVisible(false);
92 |
93 | // get ready for another animation
94 | parent.sketch = null;
95 | parent.startup = true;
96 | parent.dataConfigPanel.SetComponentsEnabled(true);
97 |
98 | noLoop();
99 | }
100 | ////
101 |
102 | int w, h;
103 | public boolean isExiting = false;
104 | public void setSize(int w, int h) {
105 | this.w = w;
106 | this.h = h;
107 | }
108 | // setup is replaced by settings in Processing 3
109 | public void settings() {
110 | GLProfile.initSingleton();
111 | size(w, h, P3D);
112 |
113 | // Set window icon
114 | String iconFilename = DesktopPane.isMacOSX() ? "logo1024.png" : "logo32.png";
115 | URL res = parent.getClass().getClassLoader().getResource(iconFilename);
116 | if(res.getProtocol().equals("jar")) {
117 | PJOGL.setIcon(iconFilename); // jar file contains the resource in its root directory
118 | } else {
119 | PJOGL.setIcon(res.getPath()); // source compilation can find the resource in bin directory
120 | }
121 | }
122 |
123 | public void setup() {
124 | colorMode(HSB, 360, 100, 100);
125 | frameRate(60);
126 |
127 | // Closes only the sketch on exit
128 | if (getGraphics().isGL() && !DesktopPane.isMacOSX()) {
129 | final com.jogamp.newt.Window w = (com.jogamp.newt.Window) getSurface().getNative();
130 | w.setDefaultCloseOperation(WindowClosingMode.DISPOSE_ON_CLOSE);
131 | // w.setAlwaysOnTop(true);
132 | }
133 | // else {
134 | // // Not Tested
135 | // final JFrame w = (JFrame) getSurface().getNative();
136 | // w.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
137 | // }
138 |
139 | // NONOPENGL ICON SETUP
140 | // PImage icon = loadImage(parent.getClass().getResource("logo32.png").getPath());
141 | // surface.setIcon(icon);
142 |
143 | parent.dataPoints = null;
144 | println("Animation Dimensions: " + w + "x" + h);
145 | println("Polling Interval: " + data.dataInterval + " " + data.timeUnit);
146 |
147 | //
148 | leftMapNeeded = data.needLeftMap;
149 | rightMapNeeded = data.needRightMap;
150 | map = new UnfoldingMap(this, "0", 0, 0, w, h, false, false, data.provider);
151 |
152 | map.zoomAndPanToFit(data.locations);
153 | if(!leftMapNeeded && !rightMapNeeded) map.setTweening(true);
154 | eventDispatcher = MapUtils.createDefaultEventDispatcher(this, map);
155 | map.zoomAndPanToFit(data.locations); // sometimes the first attempt zooms too far and bugs out, so do it again
156 |
157 | // extra maps
158 | if(leftMapNeeded) leftMap = createWrappedMap(map, eventDispatcher, 1);
159 | if(rightMapNeeded) rightMap = createWrappedMap(map, eventDispatcher, 2);
160 |
161 | //
162 | legend = new Legend(this, data, parent, map);
163 | resetLegend();
164 | println();
165 | }
166 | /// extra map functions
167 | // https://github.com/tillnagel/unfolding/commit/46d03cf6ebc6e01a35dc0aede0a02b428b9cf68d
168 | public UnfoldingMap createWrappedMap(UnfoldingMap mainMap, EventDispatcher eventDispatcher, int id) {
169 | float x = id==1 ? -w : w;
170 | UnfoldingMap wrappedMap = new UnfoldingMap(this, Integer.toString(id), x, 0, w, h, false, false, data.provider);
171 | wrappedMap.zoomToLevel(mainMap.getZoomLevel());
172 | eventDispatcher.register(wrappedMap, "zoom", mainMap.getId());
173 | return wrappedMap;
174 | }
175 | public void updateMap(UnfoldingMap mainMap, UnfoldingMap nextMap, boolean left) {
176 | float degree = (left) ? -180 : 180;
177 |
178 | // Move next map
179 | ScreenPosition pos = mainMap.getScreenPosition(new Location(0, degree));
180 | nextMap.move(pos.x, 0);
181 | if (left) {
182 | nextMap.moveBy(-800, 0);
183 | }
184 |
185 | // Pan next map
186 | nextMap.panTo(new Location(0, 0));
187 | ScreenPosition map1RightPos = mainMap.getScreenPosition(new Location(0, degree));
188 | Location map1RightLocation = nextMap.getLocation(map1RightPos);
189 | float lonDiff = (-map1RightLocation.getLon()) - degree;
190 | nextMap.panTo(new Location(-map1RightLocation.getLat(), lonDiff));
191 |
192 | // Ensure next map is always over main map (push 1px)
193 | nextMap.panBy( (left ? 1 : -1), 0);
194 | }
195 | ////
196 |
197 | //
198 | public void draw() {
199 | background(0, 0, 35);
200 |
201 | if(leftMapNeeded) updateMap(map, leftMap, true);
202 | if(rightMapNeeded) updateMap(map, rightMap, false);
203 | if(!isExiting) {
204 | map.draw();
205 | if(leftMapNeeded) leftMap.draw();
206 | if(rightMapNeeded) rightMap.draw();
207 | }
208 |
209 | for (Entry entry : parent.trackList.entrySet()) {
210 | //
211 | String key = entry.getKey();
212 | Track track = entry.getValue();
213 |
214 | // if the data is not showing, skip draw the path
215 | if (!track.getVisibility()) continue;
216 |
217 | int color = parent.colors.getTagColor(key).getRGB();
218 | ArrayList points = track.getPoints();
219 |
220 | // TODO: Add brushedTag visualization here if we implement timeline features
221 |
222 | // Underlay
223 | if(data.ghost) {
224 | pushStyle();
225 | beginShape();
226 | noFill();
227 | stroke(data.ghostColor.getRGB(), data.ghostAlpha);
228 | strokeWeight(data.ghostWeight);
229 |
230 | for (int i = 0; i < points.size(); i++) {
231 | PointRecord marker = points.get(i);
232 | DateTime markerTime = marker.getTime();
233 | if (markerTime.isBefore(data.currentTime) || markerTime.isEqual(data.currentTime)) {
234 | ScreenPosition pos = map.getScreenPosition(marker.getLocation());
235 |
236 | vertex(pos.x, pos.y);
237 | }
238 | }
239 | endShape(); // draws underlay
240 | popStyle();
241 | }
242 |
243 | // Track visualizations
244 | if (data.strokeColorToggle || (data.strokeWeightToggle && data.strokeWeightSelection != null)) {
245 | pushStyle();
246 | beginShape();
247 | noFill();
248 | strokeWeight(4);
249 | strokeJoin(ROUND); // make line connections rounded
250 | for (int i = 0; i < points.size(); i++) {
251 | PointRecord marker = points.get(i);
252 | DateTime markerTime = marker.getTime();
253 | if (markerTime.isBefore(data.currentTime) || markerTime.isEqual(data.currentTime)) {
254 | ScreenPosition pos = map.getScreenPosition(marker.getLocation());
255 |
256 | int hours;
257 | if (data.timeUnit.equals("minutes")) {
258 | hours = Hours.hoursBetween(markerTime, data.currentTime).getHours();
259 | } else {
260 | hours = Minutes.minutesBetween(markerTime, data.currentTime).getMinutes();
261 | }
262 | float alpha = 255;
263 | if (data.falloff) {
264 | alpha = constrain(map(hours, 0, data.alphaMaxHours, 255, 0), 0, 255);
265 | }
266 |
267 | if (hours <= 24) {
268 | stroke(360, 100, 100, alpha);
269 | } else if (hours <= 48) {
270 | stroke(360, 100, 63, alpha);
271 | } else if (hours <= 72) {
272 | stroke(360, 100, 30, alpha);
273 | }
274 |
275 | if (alpha != 0) {
276 | if (data.strokeWeightToggle && data.strokeWeightSelection != null) {
277 | String strokeWeightVar = data.strokeWeightSelection;
278 | float strokeWeightValue = (Float) marker.getProperty(strokeWeightVar);
279 | float strokeWeight = map(strokeWeightValue, parent.attributes.getMin(strokeWeightVar),
280 | parent.attributes.getMax(strokeWeightVar), data.strokeWeightMin,
281 | data.strokeWeightMax);
282 | strokeWeight(strokeWeight);
283 | }
284 |
285 | if (data.strokeColorToggle) {
286 | String strokeColorVar = data.strokeColorSelection;
287 | if (strokeColorVar.equals(parent.attributes.getIndex())) {
288 | stroke(color, alpha);
289 | } else {
290 | float strokeColorValue = (Float) marker.getProperty(strokeColorVar);
291 | float strokeColorPercent = norm(strokeColorValue,
292 | parent.attributes.getMin(strokeColorVar),
293 | parent.attributes.getMax(strokeColorVar));
294 | int strokeColor = parent.colors.coloursCont.get(data.selectedLineSwatch)
295 | .findColour(strokeColorPercent);
296 | stroke(strokeColor, alpha);
297 | }
298 | vertex(pos.x, pos.y);
299 | }
300 | }
301 | }
302 | }
303 | endShape(); // draw tracks
304 | popStyle();
305 | }
306 |
307 | // Point or vector visualizations
308 | if(data.vectorToggle || data.pointColorToggle) {
309 | for (int i = 0; i < points.size(); i++) {
310 | PointRecord marker = points.get(i);
311 | DateTime markerTime = marker.getTime();
312 | if (markerTime.isBefore(data.currentTime) || markerTime.isEqual(data.currentTime)) {
313 | ScreenPosition pos = map.getScreenPosition(marker.getLocation());
314 |
315 | int hours;
316 | if (data.timeUnit.equals("minutes")) {
317 | hours = Hours.hoursBetween(markerTime, data.currentTime).getHours();
318 | } else {
319 | hours = Minutes.minutesBetween(markerTime, data.currentTime).getMinutes();
320 | }
321 | float alpha = 255;
322 | if (data.falloff) {
323 | alpha = constrain(map(hours, 0, data.alphaMaxHours, 255, 0), 0, 255);
324 | }
325 |
326 | if (hours <= 24) {
327 | fill(360, 100, 100, alpha);
328 | } else if (hours <= 48) {
329 | fill(360, 100, 63, alpha);
330 | } else if (hours <= 72) {
331 | fill(360, 100, 30, alpha);
332 | }
333 |
334 | if (alpha != 0) {
335 | if (data.pointColorToggle) {
336 | pushStyle();
337 | float size = 7;
338 | String pointColorVar = data.pointColorSelection;
339 | if (pointColorVar.equals(parent.attributes.getIndex())) {
340 | fill(color, alpha);
341 | } else {
342 | float pointColorValue = (Float) marker.getProperty(pointColorVar);
343 | float pointColorPercent = norm(pointColorValue,
344 | parent.attributes.getMin(pointColorVar),
345 | parent.attributes.getMax(pointColorVar));
346 | int strokeColor = parent.colors.coloursCont.get(data.selectedPointSwatch)
347 | .findColour(pointColorPercent);
348 | fill(strokeColor, alpha);
349 | }
350 | if (data.pointSizeToggle) {
351 | String pointSizeVar = data.pointSizeSelection;
352 | float pointSizeValue = (Float) marker.getProperty(pointSizeVar);
353 | float pointSize = map(pointSizeValue, parent.attributes.getMin(pointSizeVar),
354 | parent.attributes.getMax(pointSizeVar), data.pointSizeMin,
355 | data.pointSizeMax);
356 | size = pointSize;
357 | }
358 | ellipse(pos.x, pos.y, size, size);
359 | popStyle();
360 | }
361 |
362 | if (data.vectorToggle) {
363 | pushStyle();
364 | String vectorFieldVar = data.vectorFieldSelection;
365 | float radius = (Float) marker.getProperty(vectorFieldVar);
366 | float length = 10;
367 | if (data.vectorLengthToggle) {
368 | length = map(radius, parent.attributes.getMin(vectorFieldVar),
369 | parent.attributes.getMax(vectorFieldVar), data.vectorLengthMin,
370 | data.vectorLengthMax);
371 | }
372 | float heading = (Float) marker.getProperty(data.headingFieldSelection);
373 | float x = cos(radians(heading)) * length;
374 | float y = sin(radians(heading)) * length;
375 | if (data.vectorColorToggle) {
376 | String vectorColorVar = data.vectorColorSelection;
377 | if (vectorColorVar.equals(parent.attributes.getIndex())) {
378 | stroke(color, alpha);
379 | } else {
380 | float vectorColorValue = (Float) marker.getProperty(vectorColorVar);
381 | float vectorColorPercent = norm(vectorColorValue,
382 | parent.attributes.getMin(vectorColorVar),
383 | parent.attributes.getMax(vectorColorVar));
384 | int vectorColor = parent.colors.coloursCont.get(data.selectedVectorSwatch)
385 | .findColour(vectorColorPercent);
386 | stroke(vectorColor, alpha);
387 | }
388 | } else {
389 | stroke(0, 0, 100, alpha);
390 | }
391 | strokeWeight(2);
392 | line(pos.x, pos.y, pos.x + x, pos.y + y);
393 | popStyle();
394 | }
395 | }
396 | }
397 | }
398 | }
399 | }
400 |
401 | // advance time every x frames
402 | if (!data.pause && !data.mouse && frameCount % data.speed == 0) {
403 |
404 | if (data.currentTime.isBefore(data.endTime.plusMinutes(1))) {
405 | if (data.timeUnit.equals("minutes")) {
406 | data.currentTime = data.currentTime.plusMinutes(data.dataInterval);
407 | } else if (data.timeUnit.equals("seconds")) {
408 | data.currentTime = data.currentTime.plusSeconds(data.dataInterval);
409 | }
410 | }
411 |
412 | if (data.timeUnit.equals("minutes")) {
413 | data.seek = Minutes.minutesBetween(data.startTime, data.currentTime).getMinutes();
414 | } else if (data.timeUnit.equals("seconds")) {
415 | data.seek = Seconds.secondsBetween(data.startTime, data.currentTime).getSeconds();
416 | }
417 |
418 | data.seek = data.seek / data.dataInterval;
419 | controlPanel.seek.setValue(data.seek);
420 |
421 | if (data.currentTime.isAfter(data.endTime) && data.loop) {
422 | data.currentTime = data.startTime;
423 | }
424 | }
425 |
426 | if(!isExiting) {
427 | legend.display();
428 | legend.drag(mouseX, mouseY);
429 | }
430 |
431 | // Export
432 | if (data.save) {
433 | String file = String.format("export/temp/" + parent.animationTitle + parent.exportCounter + "/temp%08d.jpeg",
434 | data.frameCounter);
435 | saveFrame(file);
436 | data.frameCounter++;
437 | }
438 |
439 | // Display approproate text if the animation window is terminated but the window itself is lingering
440 | if (isExiting) {
441 | textFont(legend.font2);
442 | background(20);
443 | fill(245);
444 | textAlign(CENTER, CENTER);
445 | text("\"" + parent.animationTitle + "\" animation was terminated.\nFeel free to close this window.", width/2, height/2);
446 |
447 | exitActual();
448 | }
449 | }
450 |
451 | //
452 | public void resetLegend() {
453 | legend.setLocation(0, height - 40);
454 | }
455 |
456 | public void keyPressed() {
457 | switch (key) {
458 | case 'z':
459 | zoomIn();
460 | break;
461 | case 'x':
462 | zoomOut();
463 | break;
464 | case 'c':
465 | zoomAndPan(data.locations);
466 | break;
467 | }
468 | }
469 |
470 | //
471 | public void zoomIn() {
472 | map.zoomIn();
473 | if(leftMap != null) leftMap.zoomIn();
474 | if(rightMap != null) rightMap.zoomIn();
475 | }
476 | public void zoomOut() {
477 | map.zoomOut();
478 | if(leftMap != null) leftMap.zoomOut();
479 | if(rightMap != null) rightMap.zoomOut();
480 | }
481 | public void zoomAndPan(List locations) {
482 | map.zoomAndPanToFit(locations);
483 | if(leftMap != null) leftMap.zoomAndPanToFit(locations);
484 | if(rightMap != null) rightMap.zoomAndPanToFit(locations);
485 | }
486 |
487 | public void register() {
488 | eventDispatcher.register(map, "pan", map.getId());
489 | }
490 |
491 | public void unregister() {
492 | eventDispatcher.unregister(map, "pan", map.getId());
493 | }
494 |
495 | public void mousePressed() {
496 | legend.clicked(mouseX, mouseY);
497 | }
498 |
499 | public void mouseReleased() {
500 | legend.stopDragging();
501 | }
502 |
503 | public void mouseMoved() {
504 |
505 | }
506 |
507 |
508 | }
509 |
--------------------------------------------------------------------------------
/src/main/SketchData.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 |
22 | package main;
23 |
24 | import utils.PointRecord;
25 | import utils.Track;
26 |
27 | import java.awt.Color;
28 | import java.awt.Rectangle;
29 | import java.util.ArrayList;
30 | import java.util.HashMap;
31 | import java.util.Hashtable;
32 | import java.util.List;
33 | import java.util.Map;
34 | import java.util.Map.Entry;
35 |
36 | import javax.swing.JCheckBox;
37 |
38 | import org.joda.time.DateTime;
39 |
40 | import de.fhpotsdam.unfolding.geo.Location;
41 | import de.fhpotsdam.unfolding.providers.AbstractMapProvider;
42 | import de.fhpotsdam.unfolding.utils.GeoUtils;
43 | import de.fhpotsdam.unfolding.utils.ScreenPosition;
44 |
45 | public class SketchData {
46 |
47 | public ArrayList Times = null;
48 | public ArrayList All_the_Times = new ArrayList();
49 | public Hashtable> Times_hash = null;
50 | public Location[] mapExtent;
51 | public List locations;
52 | public HashMap> fieldMinMax;
53 |
54 | public DateTime startTime;
55 | public DateTime endTime;
56 | public DateTime currentTime;
57 |
58 | public DateTime user_end_time;
59 | public DateTime user_start_time;
60 |
61 | // setting for boundary visualization
62 | public ArrayList Bdy_hull = new ArrayList(); // storing all the points that forming the
63 | // convex hull
64 | public boolean Bdy_Viz_Enable;
65 | public Color Bdy_Viz_Color = new Color(255, 255, 255, 255);
66 | public Color Bdy_Viz_Stroke_Color = Color.RED;
67 | public int Bdy_Viz_Stroke_Weight = 5;
68 | public boolean Bdy_Viz_Panel_Close = false;
69 | public boolean Bdy_Viz_Changes = false;
70 | public boolean init_setting = true;
71 | public int boundaryStartYear;
72 | public int boundaryEndYear;
73 | public int boundaryStartMonth;
74 | public int boundaryEndMonth;
75 | public int boundaryStartDate;
76 | public int boundaryEndDate;
77 | public boolean boundarySelect = true;
78 | public boolean drawBoundary;
79 | public int totalTime;
80 | public int dataInterval;
81 | public String timeUnit;
82 | public boolean needRightMap = false;
83 | public boolean needLeftMap = false;
84 |
85 |
86 | // setting for enable the time selection of the time line with boundary
87 | // visualization
88 | public JCheckBox enable_check = new JCheckBox("Enable");
89 |
90 | public int seek;
91 | public int alphaMaxHours;
92 | public int speed;
93 |
94 | public boolean falloff;
95 | public boolean pause = true;
96 | public boolean mouse = false;
97 | public boolean loop;
98 | public boolean strokeWeightToggle;
99 | public boolean pointColorToggle;
100 | public boolean pointSizeToggle;
101 | public boolean strokeColorToggle;
102 | public boolean vectorToggle;
103 | public boolean vectorLengthToggle;
104 | public boolean vectorColorToggle;
105 | public boolean boundaryColorToggle;
106 |
107 | public String strokeWeightSelection;
108 | public String pointColorSelection;
109 | public String pointSizeSelection;
110 | public String strokeColorSelection;
111 | public String selectedColorUnit;
112 | public String selectedStrokeWeightUnit;
113 | public String vectorFieldSelection;
114 | public String headingFieldSelection;
115 | public String vectorColorSelection;
116 | public String boundaryColorSelection;
117 |
118 | public int strokeWeightMin = 1;
119 | public int strokeWeightMax = 10;
120 | public int pointSizeMin = 1;
121 | public int pointSizeMax = 10;
122 | public int vectorLengthMin = 5;
123 | public int vectorLengthMax = 20;
124 |
125 | public boolean ghost;
126 | public Color ghostColor = Color.WHITE;
127 | public int ghostAlpha;
128 | public int ghostWeight;
129 |
130 | // Settings for boundary visit (Activity Space Panel)
131 | public boolean drawChart = false; // commented out: no longer needed
132 | public boolean boundary; // checking whether need to map the boundary
133 | public boolean drawBuffer = false; // checking whether generate buffer file
134 | public boolean highlight_all; // no longer needed
135 | public boolean highlight_fly; // checking whether visualize on the fly boundary visit
136 | public boolean includeFilteredPts = false;; // Allow user to select if filtered points are mapped
137 | public Color boundaryColor = Color.BLACK; // stroke color for convex hull boundary
138 | public Color highlightColor = Color.WHITE; // point highlight color
139 | public int highlightAlpha; // opacity for point color
140 | public int boundaryAlpha; // opacity for boundary color
141 | public int highlightWeight; // stroke weight for point
142 | public int boundaryWeight = 2; // stroke weight for boundary
143 | public int numSect; // sector number for boundary
144 | public boolean bvFile = false; // whether user selected generating buffer file
145 | public ArrayList visitedPoints = new ArrayList(); // int array for indicating if the point visit
146 | // the boundary
147 | public Hashtable hullPos; // use for tracking index of points that visit boundary
148 | public double boundaryDist = 5; // buffer size
149 | public int confidenceInterval = 100; // confidence interval for filtering points
150 | public ArrayList hull = new ArrayList(); // storing all the points that forming the convex
151 | // hull
152 | public ArrayList selectedPoints; //
153 | public String selectedID; // selected tag from the dropdown
154 | public ArrayList numVisit = new ArrayList();; // storing the number of buffer visits
155 | public ArrayList finalSectorName = new ArrayList(); // storing the sector name
156 | public int finalnumSect = 0;
157 | public boolean updateConfidenceInterval = false;
158 | public boolean updateSelectedID = true;
159 | public ArrayList clonePt = new ArrayList();
160 | public Hashtable> filteredPts = new Hashtable>();
161 | public int filteredPoints = 0;
162 | public int currentNumOfPoints = 0;
163 | public int pointsNeedRemove;
164 | // End Boundary setting
165 |
166 | public Location mapCenter;
167 |
168 | public boolean legendLocked = true;
169 | public boolean save = false;
170 | public int frameCounter = 0;
171 |
172 | public AbstractMapProvider provider;
173 | public PointRecord points;
174 |
175 | public int selectedLineSwatch;
176 | public int selectedBoundarySwatch;
177 | public int selectedPointSwatch;
178 | public int selectedVectorSwatch;
179 |
180 | public Map fieldColors = new HashMap();
181 | public String brushedTag;
182 |
183 | // public int[] visitBoundary;
184 | // public String[] sector;
185 |
186 | // time Box Variables
187 | public int timeBoxStartYear;
188 | public int timeBoxStartMonth;
189 | public int timeBoxEndYear;
190 | public int timeBoxEndMonth;
191 | public boolean labelMonth = false; // for labeling cubes
192 | public boolean timeBoxBdyHighlight = false; // highlight interactions in 3D
193 | public boolean stbclose = false;
194 | public boolean boxvisible = false;
195 |
196 | public boolean resetBox = false;
197 | public boolean staticBox = false;// make static box
198 | public Rectangle boundingBox = null;
199 | Map bounds = new HashMap();// All the bounding boxes for each track
200 | public ScreenPosition coords;
201 |
202 | // boundary interaction variable
203 | public boolean overbound1 = false; // test if in other boundary
204 | public boolean overbound2 = false;
205 | public boolean highlight_interaction_boundary = false;// highlight
206 | public boolean pointInteract = false; // test if current point is interacting
207 | public boolean noInteraction = true;// the two tags do not interact true
208 | public boolean tagChange = false;
209 |
210 | // Interactions variables
211 | public boolean multipleAnimals;// boolean for if there is data for multiple animals or not
212 | public String id1; // ID value of first animal selected to highlight interactions
213 | public String id2; // ID value of second animal selected to highlight interactions
214 | public String[] selectedIDs;// array of two selected IDs
215 | public Track track1;// track of first animal selected to highlight interactions
216 | public Track track2;// track of second animal selected to highlight interactions
217 | public float highlightSize = 15;// size of highlighted points for when animals interacting
218 | public float xpos;// x position of current point
219 | public float ypos;// y position of current point
220 | public boolean highlightOnFly = false;// checkbox user option. Highlights circular buffer when interacting
221 | public boolean highlightAllInteractions = false;// checkbox user option. Highlights all points where interacting
222 | public double bufferDist;// buffer distance tolerance (user selection)
223 | public double bufferTime;// buffer time tolerance (user selection)
224 | public boolean interactionsGenerated = false;// if all user selections are up to date, interactionsGenerated == true
225 | public boolean upToDate = false;// is false if user has changed selections since last pressing Generate Buffer
226 | // button
227 | public ArrayList interactingPoints;// boolean array of all all points, true if interacting, false if
228 | // otherwise
229 | public float holdAlpha;
230 | //
231 |
232 | //
233 | // public Layer layer;
234 | public boolean layerOpt = false;
235 | public boolean onetime = false;
236 | public String geoJson;
237 |
238 | public void processFeatureList(HashMap data) {
239 |
240 | locations = new ArrayList();
241 |
242 | for (Entry entry : data.entrySet()) {
243 | Track track = entry.getValue();
244 |
245 | if(track.requiresLeftMap) needLeftMap = true;
246 | if(track.requiresRightMap) needRightMap = true;
247 |
248 | for (PointRecord point : track.getPoints()) {
249 | locations.add(point.getLocation());
250 | }
251 | }
252 | mapExtent = GeoUtils.getBoundingBox(locations);
253 | System.out.println("Setting Map Extent to: " + mapExtent[0] + " " + mapExtent[1]);
254 |
255 | currentTime = startTime;
256 |
257 | System.gc();
258 | }
259 | }
260 |
--------------------------------------------------------------------------------
/src/utils/Attributes.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 | package utils;
22 |
23 | import java.util.ArrayList;
24 |
25 | public class Attributes {
26 |
27 | private ArrayList fields = new ArrayList();
28 | private String index;
29 |
30 | public void addField(Field field) {
31 | this.fields.add(field);
32 | }
33 |
34 | public ArrayList getSelectedFields() {
35 | ArrayList selectedFields = new ArrayList();
36 | for (Field field : fields) {
37 | if (field.getSelected()) {
38 | selectedFields.add(field);
39 | }
40 | }
41 | return selectedFields;
42 | }
43 |
44 | public ArrayList getSelectedFieldNames() {
45 | ArrayList names = new ArrayList();
46 | for (Field field : this.getSelectedFields()) {
47 | names.add(field.getAlias());
48 | }
49 | return names;
50 | }
51 |
52 | public ArrayList getFields() {
53 | return this.fields;
54 | }
55 |
56 | public boolean checkIfFieldExists(String s) {
57 | for (Field field : fields) {
58 | if (field.getName() == s) {
59 | return true;
60 | }
61 | }
62 | return false;
63 | }
64 |
65 | public ArrayList getAliasList() {
66 | ArrayList list = new ArrayList();
67 | for (Field field : fields) {
68 | String s = field.getAlias();
69 | list.add(s);
70 | }
71 | return list;
72 | }
73 |
74 | public String getName(String alias) {
75 | for (Field field : fields) {
76 | if (field.getAlias() == alias) {
77 | return field.getName();
78 | }
79 | }
80 | return null;
81 | }
82 |
83 | public String getAlias(String name) {
84 | for (Field field : fields) {
85 | if (field.getName() == name) {
86 | return field.getAlias();
87 | }
88 | }
89 | return null;
90 | }
91 |
92 | public void setIndex(String name) {
93 | this.index = name;
94 | }
95 |
96 | public String getIndex() {
97 | return this.index;
98 | }
99 |
100 | public String getIndexAlias() {
101 | return getAlias(this.index);
102 | }
103 |
104 | public String getUnit(String s) {
105 | String unit = null;
106 | for (Field field : fields) {
107 | if (field.getName() == s) {
108 | unit = field.getUnit();
109 | }
110 | }
111 | return unit;
112 | }
113 |
114 | public float getMin(String s) {
115 | float min = 0;
116 | for (Field field : fields) {
117 | if (field.getName() == s) {
118 | min = field.getMin();
119 | }
120 | }
121 | return min;
122 | }
123 |
124 | public float getMax(String s) {
125 | float max = 0;
126 | for (Field field : fields) {
127 | if (field.getName() == s) {
128 | max = field.getMax();
129 | }
130 | }
131 | return max;
132 | }
133 |
134 | }
135 |
--------------------------------------------------------------------------------
/src/utils/Field.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 |
22 | package utils;
23 |
24 | public class Field {
25 |
26 | private String name;
27 | private String alias;
28 | private String unit = null;
29 | private float min;
30 | private float max;
31 | private boolean selected;
32 |
33 | public Field(String n) {
34 | setName(n);
35 | }
36 |
37 | public Field(String n, String a, String u, float min, float max, boolean selected) {
38 | setName(n);
39 | setAlias(a);
40 | setUnit(u);
41 | setMin(min);
42 | setMax(max);
43 | setSelected(selected);
44 | }
45 |
46 | public void setSelected(boolean s) {
47 | this.selected = s;
48 | }
49 |
50 | public boolean getSelected() {
51 | return this.selected;
52 | }
53 |
54 | public void setName(String n) {
55 | this.name = n;
56 | }
57 |
58 | public String getName() {
59 | return this.name;
60 | }
61 |
62 | public void setAlias(String a) {
63 | this.alias = a;
64 | }
65 |
66 | public String getAlias() {
67 | return this.alias;
68 | }
69 |
70 | public void setUnit(String u) {
71 | this.unit = u;
72 | }
73 |
74 | public String getUnit() {
75 | return this.unit;
76 | }
77 |
78 | public void setMin(float m) {
79 | this.min = m;
80 | }
81 |
82 | public float getMin() {
83 | return this.min;
84 | }
85 |
86 | public void setMax(float m) {
87 | this.max = m;
88 | }
89 |
90 | public float getMax() {
91 | return this.max;
92 | }
93 |
94 | public String printInfo() {
95 | return getName() + " " + getAlias() + " " + getUnit() + " " + getMin() + " " + getMax() + " " + getSelected();
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/utils/PointRecord.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 |
22 | package utils;
23 |
24 | import java.util.HashMap;
25 |
26 | import org.joda.time.DateTime;
27 |
28 | import de.fhpotsdam.unfolding.geo.Location;
29 |
30 | public class PointRecord {
31 |
32 | // public static final Comparator POLAR_ORDER = null;
33 | private Location location;
34 | private int sectorNum;
35 | private String tag;
36 | private DateTime timestamp;
37 | private boolean buff;
38 | private HashMap properties = new HashMap();
39 |
40 | // a flag for the edge of map condition
41 | @SuppressWarnings("unused")
42 | private boolean altered = false;
43 |
44 | /*
45 | * buffer_size_space takes in two points and the selected buffer value to
46 | * calculate if the distance between two points is within buffer
47 | */
48 | public boolean buffer_size_space(Location pt_one, Location pt_two, double buffer) {
49 | double distance = Math.sqrt(Math.pow(pt_one.x - pt_two.x, 2) + Math.pow(pt_one.y - pt_two.y, 2));
50 | if (distance <= buffer)
51 | return true;
52 | return false;
53 | }
54 |
55 | public void calculateDistance(double radius, double x, double y, double a, double b, double c) {
56 | // Finding the distance of line from center.
57 | double dist = (Math.abs(a * x + b * y + c)) / Math.sqrt(a * a + b * b);
58 | // Checking if the distance is less than,
59 | // greater than or equal to radius.
60 | this.buff = (radius > dist || radius == dist);
61 | }
62 |
63 | public void setBuff(boolean b) {
64 | this.buff = b;
65 | }
66 |
67 | public boolean getBuff() {
68 | return this.buff;
69 | }
70 |
71 | public void setSectorNum(int num) {
72 | this.sectorNum = num;
73 | }
74 |
75 | public int getSectorNum() {
76 | return this.sectorNum;
77 | }
78 |
79 | // public boolean getBuffer(){
80 | // return this.buff.b;
81 | // }
82 | //
83 | // public void setBuffer(boolean b){
84 | // this.buff.b = b;
85 | // }
86 |
87 | public Location getLocation() {
88 | return this.location;
89 | }
90 |
91 | public void setLocation(float x, float y) {
92 | this.location = new Location(x, y);
93 | }
94 | // wrapping around the edge of map
95 | public void adjustNegativeLongitudes() {
96 | if(this.location.y < 0) { this.location.y += 360; altered = true; }
97 | }
98 | public void adjustPositiveLongitudes() {
99 | if(this.location.y > 0) { this.location.y -= 360; altered = true; }
100 | }
101 |
102 | public void setID(String id) {
103 | this.tag = id;
104 | }
105 |
106 | public String getID() {
107 | return this.tag;
108 | }
109 |
110 | public void setTime(DateTime time) {
111 | this.timestamp = time;
112 | }
113 |
114 | public DateTime getTime() {
115 | return this.timestamp;
116 | }
117 |
118 | public int getYear() {
119 | return this.timestamp.getYear();
120 | }
121 |
122 | public int getMonth() {
123 | return this.timestamp.getMonthOfYear();
124 | }
125 |
126 | public int getDay() {
127 | return this.timestamp.getDayOfMonth();
128 | }
129 |
130 | public HashMap getProperties() {
131 | return this.properties;
132 | }
133 |
134 | public Object getProperty(String key) {
135 | return this.properties.get(key);
136 | }
137 |
138 | public Object addProperty(String key, Object value) {
139 | return this.properties.put(key, value);
140 | }
141 |
142 | public void removeProperty(String key) {
143 | this.properties.remove(key);
144 | }
145 |
146 | }
147 |
--------------------------------------------------------------------------------
/src/utils/Track.java:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | DynamoVis Animation Tool
4 | Copyright (C) 2016 Glenn Xavier
5 | UPDATED: 2021 Mert Toka
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see .
19 |
20 | */
21 |
22 | package utils;
23 |
24 | import java.util.ArrayList;
25 | import java.util.Collections;
26 | import java.util.HashMap;
27 | import java.util.Hashtable;
28 | import java.util.Map.Entry;
29 |
30 | import org.apache.commons.math3.stat.Frequency;
31 | import org.joda.time.DateTime;
32 | import org.joda.time.Seconds;
33 | import main.SketchData;
34 |
35 | public class Track {
36 |
37 | private int interval;
38 | private String tag;
39 | private DateTime startDate;
40 | private DateTime endDate;
41 | private boolean visible;
42 | public SketchData data;
43 |
44 | public boolean requiresLeftMap = false;
45 | public boolean requiresRightMap = false;
46 |
47 | private ArrayList trackPoints = new ArrayList();
48 | private ArrayList trackProperties = new ArrayList();
49 |
50 | public ArrayList temp = new ArrayList();
51 |
52 | public void addPoint(PointRecord point) {
53 | this.trackPoints.add(point);
54 | HashMap props = point.getProperties();
55 | for (Entry entry : props.entrySet()) {
56 | String property = entry.getKey();
57 | if (!trackProperties.contains(property)) {
58 | this.trackProperties.add(property);
59 | }
60 | }
61 | }
62 |
63 | public ArrayList getPoints() {
64 | return this.trackPoints;
65 | }
66 |
67 | public ArrayList getProperties() {
68 | return this.trackProperties;
69 | }
70 |
71 | public void setStartDate(DateTime d) {
72 | this.startDate = d;
73 | }
74 |
75 | public DateTime getStartDate() {
76 | return this.startDate;
77 | }
78 |
79 | public void setEndDate(DateTime d) {
80 | this.endDate = d;
81 | }
82 |
83 | public DateTime getEndDate() {
84 | return this.endDate;
85 | }
86 |
87 | public void setInterval(int i) {
88 | this.interval = i;
89 | }
90 |
91 | public int getInterval() {
92 | return this.interval;
93 | }
94 |
95 | public void setTag(String t) {
96 | this.tag = t;
97 | }
98 |
99 | public String getTag() {
100 | return this.tag;
101 | }
102 |
103 | public void setVisibility(boolean b) {
104 | this.visible = b;
105 | }
106 |
107 | public boolean getVisibility() {
108 | return this.visible;
109 | }
110 |
111 | // get_gilter_times by Kin (Nathan) Chan
112 | public Hashtable> get_filter_times() {
113 | // ArrayList temp_times = new ArrayList();
114 | Hashtable> temp_hash = new Hashtable>();
115 | for (PointRecord point1 : trackPoints) {
116 | if (temp_hash.containsKey(point1.getYear())) {
117 | ArrayList temp_times = temp_hash.get(point1.getYear());
118 | int temp_month = point1.getMonth();
119 | if (!temp_times.contains(temp_month)) {
120 | temp_times.add(temp_month);
121 | Collections.sort(temp_times);
122 | temp_hash.replace(point1.getYear(), temp_times);
123 | }
124 |
125 | } else {
126 | temp_hash.put(point1.getYear(), new ArrayList(point1.getMonth()));
127 | }
128 | }
129 | return temp_hash;
130 | }
131 |
132 | public ArrayList gettheTimes() {
133 | for (PointRecord point1 : trackPoints) {
134 | DateTime temptime = point1.getTime();
135 | temp.add(temptime);
136 | }
137 |
138 | return temp;
139 |
140 | }
141 |
142 | public void calculateTimes() {
143 |
144 | ArrayList col = new ArrayList();
145 | Frequency f = new Frequency();
146 |
147 | for (PointRecord point : trackPoints) {
148 | DateTime time = point.getTime();
149 | col.add(time);
150 | }
151 |
152 | Collections.sort(col);
153 | setStartDate(Collections.min(col));
154 | setEndDate(Collections.max(col));
155 |
156 | for (int i = 0; i < col.size() - 1; i++) {
157 | // round up to nearest whole minute
158 | long seconds = Seconds.secondsBetween(col.get(i), col.get(i + 1)).getSeconds();
159 | long minutes = (long) Math.round((float) seconds / 60);
160 |
161 | f.addValue(minutes);
162 | }
163 |
164 | Long intervalLong = (Long) f.getMode().get(0);
165 | Integer interval = intervalLong != null ? intervalLong.intValue() : null;
166 |
167 | this.setInterval(interval);
168 | }
169 |
170 | public void checkEdgeOfMap() {
171 | boolean closeToRightEdge = false;
172 | boolean pastRightEdge = false;
173 | boolean closeToLeftEdge = false;
174 | boolean pastLeftEdge = false;
175 | float lonCentroid = 0;
176 |
177 | // check if close to edge
178 | for (PointRecord point : trackPoints) {
179 | float y = point.getLocation().y;
180 |
181 | if(y > 175) closeToRightEdge = true;
182 | if(y > 180) pastRightEdge = true;
183 | if(y < -175) closeToLeftEdge = true;
184 | if(y < -180) pastLeftEdge = true;
185 |
186 | lonCentroid += y;
187 | }
188 | lonCentroid /= trackPoints.size();
189 |
190 | // if close to edge
191 | if((closeToLeftEdge && closeToRightEdge) || pastLeftEdge || pastRightEdge) {
192 | if(lonCentroid > 0) {
193 | requiresRightMap = true;
194 | }
195 | else {
196 | requiresLeftMap = true;
197 | }
198 |
199 | // adjust points
200 | if(closeToLeftEdge && closeToRightEdge)
201 | for (PointRecord point : trackPoints) {
202 | if(lonCentroid > 0) {
203 | point.adjustNegativeLongitudes();
204 | }
205 | else {
206 | point.adjustPositiveLongitudes();
207 | }
208 | }
209 | }
210 | }
211 |
212 | }
213 |
--------------------------------------------------------------------------------