Compare commits

...

164 Commits

Author SHA1 Message Date
3a931d59d5 Merge branch 'release/2.16.1' 2022-06-12 20:58:31 +02:00
e53764cd7b update version numbers 2022-06-12 13:10:15 +02:00
3f7bdc7e28 simplify and speedup txlog parsing 2022-06-12 11:40:23 +02:00
8d94b517c1 fix file type detection for SCV files 2022-05-17 16:40:56 +02:00
d5e50a06b2 correct used eclipse version in update site generation
Merge branch 'release/2.16.0'
2022-05-16 22:28:00 +02:00
fda4c64ac7 Merge branch 'release/2.16.0' 2022-05-16 21:16:31 +02:00
8dcfc061cb Merge branch 'release/2.16.0' into develop 2022-05-16 21:16:31 +02:00
79a5343cde update version numbers 2022-05-16 21:13:00 +02:00
c9c6db8e4c update target platform to release 21-12 2022-05-16 21:07:32 +02:00
e629bdc5bc add LZ4 (de)compressor to target platform and add as input format 2022-05-16 20:34:23 +02:00
8522627081 align adoc format and fix issues 2022-01-09 14:30:48 +01:00
d7f6d9b879 add second style for documentation 2022-01-09 14:02:05 +01:00
8f48abf0ae cleanup package structure 2022-01-09 13:57:49 +01:00
fbec708522 fix geometry of file browser 2022-01-09 13:54:58 +01:00
5c59fb0676 Merge branch 'feature/integrated_jre' into develop 2022-01-09 13:30:00 +01:00
2a9c5ff6a5 add justj runtime 2022-01-09 13:29:10 +01:00
9fe7a83dfa update target definition to 2021-09 2022-01-09 12:13:01 +01:00
eb4e2301c1 fix minimum required execution environment 2022-01-09 11:59:33 +01:00
a6aa9859ea update maven plugin versions 2022-01-09 11:52:25 +01:00
1866ae17a9 add JavaSE-15 execution environment 2022-01-09 11:12:17 +01:00
6987985e36 fix maven build 2022-01-09 08:57:45 +01:00
f81f84d60e cleanup of settings and add non-linux bundles to help feature 2022-01-09 08:44:59 +01:00
fd8e2ea751 finishing touches on help system 2022-01-08 19:26:22 +01:00
2d11e39653 Merge branch 'feature/custom_scrollbar' into develop 2022-01-08 19:17:15 +01:00
ab419a743f Merge branch 'feature/help_system' into develop 2022-01-08 19:16:15 +01:00
fc64fa781a fix adoc syntax 2022-01-08 18:31:42 +01:00
c474ca33d8 use internal help browser 2022-01-08 18:31:27 +01:00
8119c1a4f3 direct generation of help plugin 2022-01-08 17:36:52 +01:00
5f84194145 first working version of help with dummy input 2022-01-08 17:24:26 +01:00
7dbcffe95d fix layout for auto-hiding scrollbar (e.g. GTK) 2022-01-07 21:25:01 +01:00
20934a9f47 fix behavior of ZoomBar used by WaveformCanvas 2022-01-07 19:42:27 +01:00
24890f9bbb change behavior with a clear distinction
If no modifier key is used the zoombar acts as a scroll bar. If ctrl is
used it modifies the zoom level, shift is a speed modifier
2022-01-06 19:15:31 +01:00
bd0629301b add next increment - basically working 2022-01-06 17:48:40 +01:00
71da420d86 checkpoint development 2022-01-05 21:51:57 +01:00
f9be6758e2 implement scrollbar adapter and first version of zooming scrollbar 2022-01-03 21:46:40 +01:00
93a8c067fc add sliuder variant 2022-01-03 14:15:59 +01:00
5a372d0f90 add first elements 2022-01-02 15:51:52 +01:00
806000c4cc add missing icon 2021-12-14 21:16:11 +01:00
539e5de813 Merge branch 'release/2.15.1' 2021-12-02 16:55:18 +01:00
c32d46cdc0 Merge branch 'release/2.15.1' into develop 2021-12-02 16:55:18 +01:00
5736279e8d update version numbers 2021-12-02 16:55:07 +01:00
e3f4dc6616 fix loading of corrupted uncompressed SCV files 2021-12-02 16:47:12 +01:00
a64e06ff7a Merge branch 'master' into develop 2021-11-28 12:01:29 +01:00
a42b786835 fixe some naming 2021-11-28 11:39:51 +01:00
e76000d87b fix path for gh-pages checkout 2021-11-27 17:16:56 +01:00
60ead71029 Merge branch 'release/2.15.0' into develop 2021-11-27 16:49:01 +01:00
4c48fda5ad Merge branch 'release/2.15.0' 2021-11-27 16:49:01 +01:00
6a591f2dbc add gh-pages deployment steps 2021-11-27 16:48:09 +01:00
86c30ad948 update version numbers 2021-11-27 15:39:07 +01:00
0ae055b486 Merge branch 'feature/continous_zoom' into develop 2021-11-27 15:22:44 +01:00
efcd4f5ab8 update tool bar actions and icons 2021-11-27 15:21:17 +01:00
232d2d4275 move zomm/navigate toolbar to view 2021-11-27 14:31:39 +01:00
44f96e5383 cleanup imports 2021-11-27 14:04:25 +01:00
44812310b0 implement continous zoom and removed zoom level status control 2021-11-27 14:04:06 +01:00
6ef91bb5e7 Merge branch 'release/2.14.2' 2021-11-18 14:31:09 +01:00
aa459b0ea6 Merge branch 'release/2.14.2' into develop 2021-11-18 14:31:09 +01:00
a2adf66618 update version numbers 2021-11-18 14:30:54 +01:00
3405e90df9 fix behavior of help window 2021-11-18 14:24:08 +01:00
9a59947e67 fix handling of key short cuts 2021-11-18 12:55:23 +01:00
9384d3278c remove hierarchy in poms 2021-11-18 08:41:52 +01:00
1af3171b2e cleanup imports 2021-11-16 14:15:33 +01:00
03fd9e154b Merge branch 'master' into develop 2021-11-16 14:13:22 +01:00
3572f683e3 add zoom levels 2021-11-16 14:12:10 +01:00
524ffb189c fix MT race condition 2021-11-16 14:11:30 +01:00
7fac6c8f74 Merge branch 'release/2.14.1' into develop 2021-11-16 11:32:41 +01:00
037c645075 Merge branch 'release/2.14.1' 2021-11-16 11:32:41 +01:00
2f9bd29dc8 update version numbers 2021-11-16 11:32:34 +01:00
92662c546a fix zoom level calculation 2021-11-16 11:28:32 +01:00
efa6544623 cleanup 2021-11-16 11:27:58 +01:00
52cf9daeec unify time printing (#69) 2021-11-16 09:37:50 +01:00
4a315722b1 add help browser window instead of dialog 2021-11-16 09:33:09 +01:00
a52efd1a12 Merge branch 'master' into develop 2021-11-15 22:25:12 +01:00
535df30ada Merge branch 'release/2.14.0' into develop 2021-11-15 21:38:51 +01:00
bad34dd1d1 Merge branch 'release/2.14.0' 2021-11-15 21:38:51 +01:00
5ac7f05f57 Merge branch 'master' of https://git.minres.com/VP-Tools/SCViewer 2021-11-15 21:37:51 +01:00
8353b59a27 update version numbers for release
This release fixes the following tickets:
* #62: Instead of or in addition to the Restore Default Zoom button, add
Full Zoom Out button.
* #64: Load multiple trace files and enable the possibility to view
signals from different files in a single window.
* partial #66: key shortcuts for actions like zoom in/out, go to
next/prev event etc
* #70: add full zoom and zoom between markers (once we had markers)
* #75: marker is often hiding events underneath for highlighting and
getting transaction details
* #82: Implement help for keyboard shortcuts
2021-11-15 21:29:08 +01:00
2c6ca6c376 update version number to 2.14 2021-11-15 21:25:05 +01:00
f4b03cb0e6 extend zoom handling (#70) and hide tx property panes (#58) 2021-11-15 21:23:13 +01:00
c7858997c0 update README.md 2021-11-15 15:18:56 +01:00
bd99ab3992 corrected parent path im poms 2021-11-15 15:14:04 +01:00
66f365d38d externalize string in HelpDialog class 2021-11-15 15:14:04 +01:00
59987f262d update key bindings 2021-11-15 15:14:04 +01:00
452a28362e fix help link 2021-11-15 15:14:04 +01:00
d6805f383b add help dialog 2021-11-15 15:14:04 +01:00
076611eec7 allow multiple loading of same format 2021-11-15 15:14:04 +01:00
e0fa55e2c0 corrected parent path im poms 2021-11-15 14:32:55 +01:00
9ea1994228 update key bindings 2021-11-15 14:16:46 +01:00
36f628c365 add help dialog 2021-11-15 13:07:58 +01:00
ff87e72510 allow multiple loading of same format 2021-11-15 10:52:59 +01:00
aef1e29a53 Merge branch 'release/2.13.2' into develop 2021-07-11 14:22:41 +02:00
1ebf9ba382 update version numbers 2021-07-11 13:47:48 +02:00
929408d08c fix missing gzip txlog file filter in file dialog 2021-07-11 13:47:27 +02:00
f57fb93525 fix reload issues 2021-07-11 13:46:35 +02:00
788065e456 Merge branch 'release/2.13.1' 2021-03-25 21:09:49 +00:00
22b46e0525 fix fit zoom level calculation 2021-03-25 21:07:05 +00:00
b75018239a Merge branch 'master' into develop
Conflicts:
	features/com.minres.scviewer.database.feature/pom.xml
	features/com.minres.scviewer.e4.feature/pom.xml
	features/com.minres.scviewer.e4.platform.feature/pom.xml
	features/com.minres.scviewer.feature/pom.xml
	features/com.minres.scviewer.ui.feature/pom.xml
	plugins/com.minres.scviewer.database.sqlite/pom.xml
	plugins/com.minres.scviewer.database.text/pom.xml
	plugins/com.minres.scviewer.database.ui.swt/pom.xml
	plugins/com.minres.scviewer.database.vcd/pom.xml
	plugins/com.minres.scviewer.database/pom.xml
	plugins/com.minres.scviewer.e4.application/META-INF/MANIFEST.MF
	plugins/com.minres.scviewer.e4.application/pom.xml
	plugins/com.minres.scviewer.ui/pom.xml
	pom.xml
	products/com.minres.scviewer.e4.product/pom.xml
	products/com.minres.scviewer.e4.product/scviewer.product
	releng/com.minres.scviewer.target/pom.xml
	releng/com.minres.scviewer.updateSite/pom.xml
	tests/com.minres.scviewer.database.test/pom.xml
2021-03-25 20:46:30 +00:00
598bb8eec7 Merge remote-tracking branch 'origin/master' 2021-03-25 20:33:25 +00:00
869265fc13 add gzip files to file dialog filter 2021-03-25 20:27:55 +00:00
5ad813527a fix CLI handling 2021-03-25 20:27:55 +00:00
73f8d3d50a fix full name display of generators 2021-03-25 20:27:55 +00:00
da1701195d update version numbers 2021-03-25 20:27:55 +00:00
9b6334509e update version numbers 2021-03-25 20:27:54 +00:00
ac4acc34a4 fix warning and left-overs 2021-03-25 20:27:54 +00:00
b6963f38d6 move interface to primitive types 2021-03-25 20:27:54 +00:00
182a036ade some more refactoring 2021-03-25 20:27:53 +00:00
97f2182290 adapt painter 2021-03-25 20:27:53 +00:00
1986a8c9c3 add explicit event list 2021-03-25 20:27:53 +00:00
6905d96329 add TreeMap facade 2021-03-25 20:27:52 +00:00
818f786b1d add dispose check in case view is closed while loading db 2021-03-25 20:27:52 +00:00
2948c1bd33 update version numbers 2021-03-25 20:22:15 +00:00
78faab404c apply UI fixes
* wrong arrow target of transaction
* wrong zomm factor calculation for zoom fit
* streams and waveforms not visible if at root level
2021-03-25 20:18:50 +00:00
64b10970a8 add gzip files to file dialog filter 2021-03-02 21:55:52 +01:00
6ab8fd232e fix CLI handling 2021-03-02 21:55:52 +01:00
f337a94112 fix full name display of generators 2021-03-02 21:55:52 +01:00
0135631a3e update version numbers 2021-03-02 21:55:52 +01:00
d0e1e8801f update version numbers 2021-03-02 21:55:52 +01:00
d1b3a91979 fix warning and left-overs 2021-03-02 21:55:52 +01:00
45c1396e0e move interface to primitive types 2021-03-02 21:55:51 +01:00
b7301733f0 some more refactoring 2021-03-02 21:55:51 +01:00
5df91dbaa8 adapt painter 2021-03-02 21:55:51 +01:00
68918689e7 add explicit event list 2021-03-02 21:55:51 +01:00
c41dd646da add TreeMap facade 2021-03-02 21:55:51 +01:00
a077389b83 add dispose check in case view is closed while loading db 2021-03-02 21:55:51 +01:00
caa37375c0 add gzip files to file dialog filter 2021-03-02 21:42:54 +01:00
3daea8ab43 fix CLI handling 2021-03-02 19:32:21 +01:00
c5d77af0d0 fix full name display of generators 2021-03-02 19:32:09 +01:00
7f7fdf09f4 update version numbers 2021-02-27 19:13:28 +00:00
7aba6a2ecb update version numbers 2021-02-27 19:13:17 +00:00
012395b933 Merge branch 'feature/eclipse_collections' into develop 2021-02-27 18:47:31 +00:00
787e3accc0 fix warning and left-overs 2021-02-27 14:00:29 +00:00
b778940c83 move interface to primitive types 2021-02-27 13:59:00 +00:00
71297c4e5a some more refactoring 2021-02-27 13:47:37 +00:00
1d2395e00d adapt painter 2021-02-27 13:33:15 +00:00
b69e1886b9 add explicit event list 2021-02-27 13:27:51 +00:00
d65803a4b7 add TreeMap facade 2021-02-26 11:57:54 +00:00
0e49a68e09 add dispose check in case view is closed while loading db 2021-02-24 08:46:19 +00:00
7af5593fd4 Merge branch 'release/2.12.2' into develop 2021-02-24 07:05:00 +00:00
25545dac51 Merge branch 'release/2.12.2' 2021-02-24 07:04:59 +00:00
df77af64ca update version numbers 2021-02-24 07:04:47 +00:00
e264ab2cbe fix name display in waveform view (#6) 2021-02-24 06:56:28 +00:00
8c17ed4146 Merge branch 'release/2.12.1' into develop 2021-02-18 08:19:17 +00:00
4ee2e8bc68 Merge branch 'release/2.12.1' 2021-02-18 08:19:16 +00:00
bdcba613d5 fix version numbers 2021-02-18 08:18:47 +00:00
049de0ddaf add VM arguments for Java > 9 2021-02-18 08:14:12 +00:00
6be3f378d4 renmove deprecated newInstance call 2021-02-18 06:32:14 +00:00
6d8aa33fc9 update language level 2021-02-18 06:26:42 +00:00
b37ba9f2f1 Merge branch 'master' into develop 2021-02-17 21:15:33 +00:00
799f083a74 fix hierarchy display 2021-02-17 21:14:28 +00:00
156abe63cd fix display bug 2021-02-17 20:27:58 +00:00
d38016a03f fix display bug 2021-02-17 20:24:25 +00:00
5604c3ee5e Merge branch 'release/2.12.0' 2021-01-15 16:50:33 +01:00
5adeae15a9 change name of generated product artifacts 2021-01-15 15:52:28 +01:00
bca94ceb9d fix stream row calculation 2021-01-15 15:51:59 +01:00
a42f086339 set max heap to 2GB by default 2021-01-14 23:56:04 +01:00
888edf32be remove ITxGenerator interface 2021-01-14 23:55:47 +01:00
ee5536f1b5 update version numbers 2021-01-14 23:51:18 +01:00
59859e5d90 cache some more infos for stream 2021-01-14 23:36:29 +01:00
5bae086712 fix (Sonarlint) warnings 2021-01-14 23:36:07 +01:00
16de83616a adapt ui to database API 2021-01-14 23:14:22 +01:00
6530362b89 refactor tests 2021-01-14 23:14:05 +01:00
0372e03abb minor database API change 2021-01-14 23:13:11 +01:00
26e8ea8a51 change design browser icons 2021-01-14 21:57:27 +01:00
efd042dd22 fix duplicate version numbers 2021-01-12 20:28:51 +01:00
d06642d51f Merge branch 'release/2.11.2' into develop 2021-01-12 20:25:46 +01:00
249 changed files with 8486 additions and 2334 deletions

3
.gitignore vendored
View File

@ -8,4 +8,5 @@ SCViewer.xcf
SCViewer_1.png SCViewer_1.png
copyrightLog.txt copyrightLog.txt
/workspace /workspace
?*.launch ?*.launch
/.settings/

View File

@ -12,7 +12,8 @@
<booleanAttribute key="M2_UPDATE_SNAPSHOTS" value="false"/> <booleanAttribute key="M2_UPDATE_SNAPSHOTS" value="false"/>
<stringAttribute key="M2_USER_SETTINGS" value=""/> <stringAttribute key="M2_USER_SETTINGS" value=""/>
<booleanAttribute key="M2_WORKSPACE_RESOLUTION" value="true"/> <booleanAttribute key="M2_WORKSPACE_RESOLUTION" value="true"/>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_ATTR_USE_ARGFILE" value="false"/>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_CLASSPATH_ONLY_JAR" value="false"/>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/> <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.launching.macosx.MacOSXType/AdoptOpenJDK 8 [1.8.0_232]"/>
<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${project_loc:com.minres.scviewer.parent}"/> <stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${project_loc:com.minres.scviewer.parent}"/>
</launchConfiguration> </launchConfiguration>

View File

@ -1,4 +0,0 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

View File

@ -18,14 +18,55 @@ The viewer has the following features
- sqlite based - sqlite based
- visualization of transaction relations - visualization of transaction relations
To build the plugins the Eclipse SDK or PDE can be used. In both cases the Groovy To build the plugins the Eclipse SDK or PDE can be used.
eclipse plugin (http://groovy.codehaus.org/Eclipse+Plugin or Market) has to be
installed. Key Shortcuts
=============
Legend:
* Left Mouse Button: LMB
* Middle Mouse Button: MMB
* Mouse Scroll wheel: MScrl
* Context any means Name List, Value List or Waveform
| Input | Modifier | Context | Action |
|------------|----------|----------|-----------------------------------|
| LMB click | | any | select |
| LMB click | Shift | Waveform | move selected marker to position |
| LMB click | Control | Waveform | move cursor to position |
| LMB drag | | Waveform | zoom to range |
| MMB click | | Waveform | move selected marker to position |
| MScrl | | any | scroll window up/down |
| MScrl | Shift | any | scroll window left/right |
| MScrl | Control | Waveform | zoom in/out |
| Key left | | Waveform | scroll window to the left (slow) |
| Key right | | Waveform | scroll window to the right (slow) |
| Key left | Shift | Waveform | scroll window to the left (fast) |
| Key right | Shift | Waveform | scroll window to the right (fast) |
| Key up | | Waveform | move selection up |
| Key down | | Waveform | move selection down |
| Key up | Control | Waveform | move selected track up |
| Key down | Control | Waveform | move selected track down |
| Key + | Control | Waveform | zoom in |
| Key - | Control | Waveform | zoom out |
| Key Pos1 | | Waveform | jump to selected marker |
| Key End | | Waveform | jump to cursor |
| Key Del | | any | delete selected entries |
| LMB click | | ZoomBar | increment/decrement 1 page |
| LMB drag | | ZoomBar | drag both markers (pan) |
| LMB drag | Control | ZoomBar | drag one marker (zoom) |
| MMB drag | | ZoomBar | drag one marker (zoom) |
| xMB dclick | | ZoomBar | pan to position |
| MScrl | | ZoomBar | scroll window left/right |
| MScrl | Shift | ZoomBar | scroll window left/right double speed |
| MScrl | Control | ZoomBar | zoom in/out |
| Key left | | ZoomBar | scroll window to the left (slow) |
| Key right | | ZoomBar | scroll window to the right (slow) |
| Key up | | ZoomBar | scroll window to the left (slow) |
| Key down | | ZoomBar | scroll window to the right (slow) |
| Key PgUp | | ZoomBar | scroll window to the left (fast) |
| Key PgDown | | ZoomBar | scroll window to the right (fast) |
| Key Pos1 | | ZoomBar | scroll to begin |
| Key End | | ZoomBar | scroll to end |
TODO
====
- add more tests
- move to feature based product to allow automatic updates
- improve graphics
- catch-up e3 plugin to functionality of e4 product
- add calculated traces

View File

@ -0,0 +1 @@
/target/

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.minres.scviewer.doc</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
</buildSpec>
<natures>
</natures>
</projectDescription>

View File

@ -0,0 +1,168 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>com.minres.scviewer.doc</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<parent>
<groupId>com.minres.scviewer</groupId>
<artifactId>com.minres.scviewer.parent</artifactId>
<version>2.16.1</version>
<relativePath>../..</relativePath>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<asciidoctor.maven.plugin.version>2.0.0</asciidoctor.maven.plugin.version>
<asciidoctorj.pdf.version>1.6.2</asciidoctorj.pdf.version>
<help.plugin.target.dir>../../plugins/com.minres.scviewer.e4.application.help</help.plugin.target.dir>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>${asciidoctor.maven.plugin.version}</version>
<dependencies>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj-pdf</artifactId>
<version>${asciidoctorj.pdf.version}</version>
</dependency>
</dependencies>
<configuration>
<sourceDirectory>src/asciidoc</sourceDirectory>
<sourceDocumentName>SCViewerHelp.adoc</sourceDocumentName>
<headerFooter>true</headerFooter>
</configuration>
<executions>
<execution>
<id>output-html</id>
<phase>generate-resources</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<sourceHighlighter>coderay</sourceHighlighter>
<backend>html</backend>
<attributes>
<toc />
<linkcss>false</linkcss>
</attributes>
</configuration>
</execution>
<execution>
<id>output-docbook</id>
<phase>generate-resources</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>docbook</backend>
</configuration>
</execution>
<execution>
<id>output-pdf</id>
<phase>generate-resources</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>pdf</backend>
<sourceHighlighter>coderay</sourceHighlighter>
<attributes>
<icons>font</icons>
<pagenums />
<toc />
<idprefix />
<idseparator>-</idseparator>
</attributes>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>copy-asciidoc-resources</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>target/generated-docs/</directory>
<includes>
<include>SCViewerHelp.xml</include>
<include>**/*.jpg</include>
<include>**/*.png</include>
<include>**/*.svg</include>
</includes>
</resource>
</resources>
<outputDirectory>src/docbkx</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.agilejava.docbkx</groupId>
<artifactId>docbkx-maven-plugin</artifactId>
<version>2.0.17</version>
<executions>
<execution>
<!-- <phase>generate-sources</phase> -->
<phase>generate-resources</phase>
<goals>
<goal>generate-eclipse</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.docbook</groupId>
<artifactId>docbook-xml</artifactId>
<version>4.4</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<configuration>
<sourceDirectory>src/docbkx</sourceDirectory>
<targetDirectory>${help.plugin.target.dir}</targetDirectory>
<preProcess>
<copy todir="${help.plugin.target.dir}/images">
<fileset dir="src/docbkx/images" />
</copy>
<copy todir="${help.plugin.target.dir}/css">
<fileset dir="src/docbkx/css" />
</copy>
</preProcess>
<imgSrcPath>./</imgSrcPath>
<useExtensions>1</useExtensions>
<highlightSource>1</highlightSource>
<highlightDefaultLanguage>java</highlightDefaultLanguage>
<calloutsExtension>1</calloutsExtension>
<paperType>A4</paperType>
<!--<fop1Extensions>1</fop1Extensions>
<foCustomization>${basedir}/conf/customization-fopdf.xsl</foCustomization>-->
<!-- This copies content (images, etc) for the HTML version -->
<!-- Any parameters specific to HTML version go here -->
<htmlStylesheet>css/narrow_style.css</htmlStylesheet>
<!-- <includes>titlepage/titlepage.templates.xml</includes> -->
<includes>SCViewerHelp.xml</includes>
<chunkedOutput>true</chunkedOutput>
<xincludeSupported>true</xincludeSupported>
<!-- <foCustomization>src/test/resources/docbook-fo.xsl</foCustomization> -->
<eclipsePluginId>com.minres.scviewer.e4.application.help</eclipsePluginId>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,25 @@
[#_introduction]
== Introduction
[#_overview]
=== SCViewer overview
SCViewer is composed of a set of eclipse plugins to display VCD and transaction streams
created by the SystemC VCD trace implementation and the SystemC Verification Library (SCV).
For further description of the SCV please refer to
http://www.accellera.org/activities/committees/systemc-verification.
[#_features]
=== SCViewer features
Features include:
* support of VCD files (compressed and uncompressed)
** real numbers
** showing vectors and real numbers as analog (step-wise & continuous)
* various value representations of bit vectors
* support of SCV transaction recordings in various formats
** text log files (compressed and uncompressed)
** sqlite based
** visualization of transaction relations

View File

@ -0,0 +1,55 @@
[#_reference]
== Reference
In this section you will find detailed descriptions of all GUI and menu elements of the SCViewer including their functions and keyboard shortcuts.
[#_keybindings]
=== Key Shortcuts
Legend:
* Left Mouse Button: LMB
* Middle Mouse Button: MMB
* Mouse Scroll wheel: MScrl
* Context any means Name List, Value List or Waveform
[cols="1,1,1,4",options="header"]
|===
| Input | Modifier | Context | Action
| LMB click | | any | select
| LMB click | Shift | Waveform | move selected marker to position
| LMB click | Control | Waveform | move cursor to position
| LMB drag | | Waveform | zoom to range
| MMB click | | Waveform | move selected marker to position
| MScrl | | any | scroll window up/down
| MScrl | Shift | any | scroll window left/right
| Key left | | Waveform | scroll window to the left (slow)
| Key right | | Waveform | scroll window to the right (slow)
| Key left | Shift | Waveform | scroll window to the left (fast)
| Key right | Shift | Waveform | scroll window to the right (fast)
| Key up | | Waveform | move selection up
| Key down | | Waveform | move selection down
| Key up | Control | Waveform | move selected track up
| Key down | Control | Waveform | move selected track down
| Key + | Control | Waveform | zoom in
| Key - | Control | Waveform | zoom out
| Key Pos1 | | Waveform | jump to selected marker
| Key End | | Waveform | jump to cursor
| Key Del | | any | delete selected entries
| LMB click | | ZoomBar | increment/decrement 1 page
| LMB drag | | ZoomBar | drag both markers (pan)
| LMB drag | Control | ZoomBar | drag one marker (zoom)
| MMB drag | | ZoomBar | drag one marker (zoom)
| xMB dclick | | ZoomBar | pan to position
| MScrl | | ZoomBar | scroll window left/right
| MScrl | Shift | ZoomBar | scroll window left/right double speed
| MScrl | Control | ZoomBar | zoom in/out
| Key left | | ZoomBar | scroll window to the left (slow)
| Key right | | ZoomBar | scroll window to the right (slow)
| Key up | | ZoomBar | scroll window to the left (slow)
| Key down | | ZoomBar | scroll window to the right (slow)
| Key PgUp | | ZoomBar | scroll window to the left (fast)
| Key PgDown | | ZoomBar | scroll window to the right (fast)
| Key Pos1 | | ZoomBar | scroll to begin
| Key End | | ZoomBar | scroll to end
|===

View File

@ -0,0 +1,39 @@
[#_start]
= SCViewer User Guide
:title-logo-image: image:Minres_logo_docs.png[width=750, align="right"]
:doctype: book
:source-highlighter: coderay
:coderay-linenums-mode: inline
:coderay-css: class
:listing-caption: Listing
:icons: font
//add table-of-contents (toc) and set its depth
:toc:
:toclevels: 3
:data-uri:
:sectnums:
:toc-title: Contents
:homepage: https://www.minres.com/
:keywords:
:title-page:
:xrefstyle: short
:table-caption: Table
:figure-caption: Figure
:appendix-caption: Appendix
:section-refsig: Chapter
//set directories
:imagesdir: ./images
:iconsdir: ./icons
:stylesdir: ./styles
:scriptsdir: ./js
:pdf-themesdir: ./themes
:pdf-theme: mnrs-doc
:pdf-fontsdir: ./fonts
// unset toc, otherwise it appears in table cells -> known bug, should be fixed in later versions!
:toc!:
include::Overview.adoc[]
include::Reference.adoc[]

View File

@ -0,0 +1,93 @@
Copyright (c) 2009-2011 by Accademia di Belle Arti di Urbino and students of MA course of Visual design. Some rights reserved.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -0,0 +1,55 @@
page:
layout: portrait
margin: [2.3cm, 2cm, 2cm, 2.2cm]
size: A4
base:
font-color: #000000
font-color-mnrs-grey: #6a747c
font-color-mnrs-blue: #197788
font-family: titillium
font-size: 12
line-height-length: 16
line-height: $base-line-height-length / $base-font-size
align: justify
vertical-spacing: $base-line-height-length
heading:
font-color: $base-font-color-mnrs-grey
font-size: $base-font-size * 1.25
font-style: bold
line-height: $base-line-height * 1.2
margin-bottom: $vertical-spacing
link:
font-color: $base_font-color-mnrs-blue
outline-list:
indent: $base-font-size * 1.5
footer:
height: $base-line-height-length * 3.0
font-color: $base-font-color-mnrs-grey
font-size: $base-font-size * 0.9
line-height: 1
recto:
left:
content: '{description} v{revision}, &#169; 2021 MINRES'
right:
content: '{page-number}'
verso:
left:
content: $footer_recto_right_content
right:
content: $footer_recto_left_content
table:
border_color: $base-font-color
border_width: 0.1
title-page:
align: right
font-color: $base-font-color-mnrs-grey
font-size: $base-font-size * 1.80
font-style: bold
font:
fallbacks: titilliumtext22l002-webfont.ttf
catalog:
titillium:
normal: titilliumtext22l002-webfont.ttf
bold: titilliumtext22l005-webfont.ttf
italic: TitilliumWeb-Italic.ttf
bold_italic: TitilliumWeb-BoldItalic.ttf

View File

@ -0,0 +1 @@
/SCViewerHelp.xml

View File

@ -0,0 +1,124 @@
P.Code {
display: block;
text-align: left;
text-indent: 0.00pt;
margin-top: 0.000000pt;
margin-bottom: 0.000000pt;
margin-right: 0.000000pt;
margin-left: 1.5em;
font-size: 100%;
font-weight: medium;
font-style: Regular;
color: #4444CC;
text-decoration: none;
vertical-align: baseline;
text-transform: none;
font-family: "Courier New";
}
H6.CaptionFigColumn {
display: block;
text-align: left;
text-indent: 0.000000pt;
margin-top: 0.3em;
margin-bottom: 1.1em;
margin-right: 0.000000pt;
margin-left: 0.000000pt;
font-size: 90%;
font-weight: medium;
font-style: Italic;
color: #000000;
text-decoration: none;
vertical-align: baseline;
text-transform: none;
font-family: "Arial";
}
P.Note {
display: block;
text-align: left;
text-indent: 0pt;
margin-top: 1.95em;
margin-bottom: 1.95em;
margin-right: 0.000000pt;
margin-left: 3.0em;
font-size: 110%;
font-weight: medium;
font-style: Italic;
color: #000000;
text-decoration: none;
vertical-align: baseline;
text-transform: none;
font-family: "Arial";
}
EM.UILabel {
font-weight: Bold;
font-style: Regular;
text-decoration: none;
vertical-align: baseline;
text-transform: none;
}
EM.CodeName {
font-weight: Bold;
font-style: Regular;
text-decoration: none;
vertical-align: baseline;
text-transform: none;
font-family:"Courier New";
}
body, html { border: 0px }
/* following font face declarations need to be removed for DBCS */
body, h1, h2, h3, h4, h5, h6, p, table, td, caption, th, ul, ol, dl, li, dd, dt {font: message-box; color: #000000}
pre { font-family: Courier, monospace}
/* end font face declarations */
/* following font size declarations should be OK for DBCS */
body, h1, h2, h3, h4, h5, h6, p, table, td, caption, th, ul, ol, dl, li, dd, dt {font: message-box; }
pre { font-size: 100% }
code,samp { font-size: 100%; }
/* end font size declarations */
body { background: #FFFFFF}
h1 { font-size: 180%; font-weight: medium; margin-top: 0.28em; margin-bottom: 0.05em; color: Highlight }
h2 { font-size: 140%; font-weight: bold; margin-top: 0.22em; margin-bottom: 3; color: Highlight }
h3 { font-size: 110%; font-weight: bold; margin-top: 0.18em; margin-bottom: 3 }
h4 { font-size: 100%; font-weight: bold; margin-top: 0.2em; margin-bottom: 3; font-style: italic }
p { margin-top: 1.0em; margin-bottom: 1.0em }
pre { margin-left: 6; font-size: 90% }
a:link { color: #0000FF }
a:hover { color: #000080 }
a:visited { text-decoration: underline }
ul { margin-top: 0;
margin-bottom: 1.0em;
margin-left : 1.0em;
padding-left: 0;
}
li { margin-top: 0;
margin-bottom: 0;
padding-left: 0;
margin-left: 0;
}
li p { margin-top: 0; margin-bottom: 0 }
ol { margin-top: 0;
margin-bottom: 10;
padding-left: 0;
margin-left: 1.4em }
dl { margin-top: 0; margin-bottom: 10 }
dt { margin-top: 0; margin-bottom: 0; font-weight: bold }
dd { margin-top: 0; margin-bottom: 0 }
strong { font-weight: bold}
em { font-style: italic}
var { font-style: italic}
div.revision { border-left-style: solid; border-left-width: thin;
border-left-color: #7B68EE; padding-left:5 }
th { font-weight: bold }
.figure-contents .mediaobject img {
width: 100%;
heigth: auto;
}

View File

@ -0,0 +1,108 @@
P.Code {
display: block;
text-align: left;
text-indent: 0.00pt;
margin-top: 0.000000pt;
margin-bottom: 0.000000pt;
margin-right: 0.000000pt;
margin-left: 15pt;
font-weight: normal;
font-style: normal;
color: #4444CC;
text-decoration: none;
vertical-align: baseline;
text-transform: none;
font-family: "Courier New", Courier, monospace;
}
H6.CaptionFigColumn {
display: block;
text-align: left;
text-indent: 0.000000pt;
margin-top: 3.000000pt;
margin-bottom: 11.000000pt;
margin-right: 0.000000pt;
margin-left: 0.000000pt;
font-size: 75%;
font-weight: bold;
font-style: Italic;
color: #000000;
text-decoration: none;
vertical-align: baseline;
text-transform: none;
}
P.Note {
display: block;
text-align: left;
text-indent: 0pt;
margin-top: 19.500000pt;
margin-bottom: 19.500000pt;
margin-right: 0.000000pt;
margin-left: 30pt;
font-size: 110%;
font-weight: normal;
font-style: Italic;
color: #000000;
text-decoration: none;
vertical-align: baseline;
text-transform: none;
}
EM.UILabel {
font-weight: Bold;
font-style: normal;
text-decoration: none;
vertical-align: baseline;
text-transform: none;
}
EM.CodeName {
font-weight: Bold;
font-style: normal;
text-decoration: none;
vertical-align: baseline;
text-transform: none;
font-family: "Courier New", Courier, monospace;
}
UL.NavList {
margin-left: 1.5em;
padding-left: 0px;
list-style-type: none;
}
body, html { border: 0px }
/* following font face declarations need to be removed for DBCS */
body, h1, h2, h3, h4, h5, h6, p, table, td, caption, th, ul, ol, dl, li, dd, dt {font-family: Arial, Helvetica, sans-serif; color: #000000}
pre, code { font-family: "Courier New", Courier, monospace;}
/* end font face declarations */
@media print {
html { font-size: 12pt }
}
body { font-size: 83%; background: #FFFFFF; margin-bottom: 1em }
h1 { font-size: 180%; margin-top: 5px; margin-bottom: 1px }
h2 { font-size: 140%; margin-top: 25px; margin-bottom: 3px }
h3 { font-size: 110%; margin-top: 20px; margin-bottom: 3px }
h4 { font-size: 100%; margin-top: 20px; margin-bottom: 3px; font-style: italic }
p { margin-top: 10px; margin-bottom: 10px }
pre { font-size: 93%; margin-left: 6; color: #4444CC }
code { font-size: 93%; }
table { font-size: 100% } /* needed for quirks mode */
a:link { color: #0000FF }
a:hover { color: #000080 }
a:visited { text-decoration: underline }
ul { margin-top: 10px; margin-bottom: 10px; }
li { margin-top: 5px; margin-bottom: 5px; }
li p { margin-top: 5px; margin-bottom: 5px; }
ol { margin-top: 10px; margin-bottom: 10px; }
dl { margin-top: 10px; margin-bottom: 10px; }
dt { margin-top: 5px; margin-bottom: 5px; font-weight: bold; }
dd { margin-top: 5px; margin-bottom: 5px; }
strong { font-weight: bold}
em { font-style: italic}
var { font-style: italic}
div.revision { border-left-style: solid; border-left-width: thin;
border-left-color: #7B68EE; padding-left:5 }
th { font-weight: bold }

View File

@ -0,0 +1 @@
/*.png

View File

@ -27,12 +27,12 @@ http://www.eclipse.org/legal/epl-v10.html
</url> </url>
<requires> <requires>
<import plugin="org.codehaus.groovy" version="2.5.8" match="greaterOrEqual"/>
<import plugin="org.eclipse.osgi.services" version="3.4.0" match="greaterOrEqual"/> <import plugin="org.eclipse.osgi.services" version="3.4.0" match="greaterOrEqual"/>
<import plugin="com.google.guava" version="15.0.0" match="greaterOrEqual"/> <import plugin="com.google.guava" version="15.0.0" match="greaterOrEqual"/>
<import plugin="org.eclipse.osgi"/> <import plugin="org.eclipse.osgi"/>
<import plugin="com.minres.scviewer.database" version="1.0.0" match="greaterOrEqual"/> <import plugin="com.minres.scviewer.database" version="1.0.0" match="greaterOrEqual"/>
<import plugin="org.eclipse.core.runtime"/> <import plugin="org.eclipse.core.runtime"/>
<import feature="org.eclipse.collections.feature" version="10.4.0.v20200820-2049"/>
</requires> </requires>
<plugin <plugin

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.minres.scviewer</groupId> <groupId>com.minres.scviewer</groupId>
<artifactId>com.minres.scviewer.parent</artifactId> <artifactId>com.minres.scviewer.parent</artifactId>
<version>2.11.2-SNAPSHOT</version> <version>2.16.1</version>
<relativePath>../..</relativePath> <relativePath>../..</relativePath>
</parent> </parent>
<version>3.0.0-SNAPSHOT</version> <version>3.0.0-SNAPSHOT</version>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.minres.scviewer</groupId> <groupId>com.minres.scviewer</groupId>
<artifactId>com.minres.scviewer.parent</artifactId> <artifactId>com.minres.scviewer.parent</artifactId>
<version>2.11.2-SNAPSHOT</version> <version>2.16.1</version>
<relativePath>../..</relativePath> <relativePath>../..</relativePath>
</parent> </parent>
<version>1.1.0-SNAPSHOT</version> <version>1.1.0-SNAPSHOT</version>

View File

@ -0,0 +1 @@
/target/

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.minres.scviewer.e4.help.feature</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.pde.FeatureBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.FeatureNature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1 @@
bin.includes = feature.xml

View File

@ -0,0 +1,207 @@
<?xml version="1.0" encoding="UTF-8"?>
<feature
id="com.minres.scviewer.e4.help.feature"
label="Feature"
version="1.0.0.qualifier"
provider-name="MINRES Technologies GmbH">
<description url="http://www.example.com/description">
[Enter Feature Description here.]
</description>
<copyright url="http://www.example.com/copyright">
[Enter Copyright Description here.]
</copyright>
<license url="http://www.example.com/license">
[Enter License Description here.]
</license>
<plugin
id="org.eclipse.help"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.help.webapp"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.help.base"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.apache.lucene.core"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.apache.lucene.analyzers-common"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.apache.lucene.analyzers-smartcn"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.core.net"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.equinox.security"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.equinox.security.linux.x86_64"
os="linux"
arch="x86_64"
download-size="0"
install-size="0"
version="0.0.0"
fragment="true"/>
<plugin
id="javax.el"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="javax.servlet"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="javax.servlet.jsp"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.equinox.http.jetty"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.equinox.http.registry"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.equinox.http.servlet"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.equinox.jsp.jasper"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.equinox.jsp.jasper.registry"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.apache.jasper.glassfish"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.jetty.http"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.jetty.io"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.jetty.security"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.jetty.server"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.jetty.servlet"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.jetty.util"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="com.minres.scviewer.e4.application.help"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="org.eclipse.equinox.security.win32.x86_64"
os="win32"
arch="x86_64"
download-size="0"
install-size="0"
version="0.0.0"
fragment="true"
unpack="false"/>
</feature>

View File

@ -0,0 +1,12 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>com.minres.scviewer.e4.help.feature</artifactId>
<packaging>eclipse-feature</packaging>
<parent>
<groupId>com.minres.scviewer</groupId>
<artifactId>com.minres.scviewer.parent</artifactId>
<version>2.16.1</version>
<relativePath>../..</relativePath>
</parent>
<version>1.0.0-SNAPSHOT</version>
</project>

View File

@ -29,6 +29,10 @@
id="org.eclipse.emf.common" id="org.eclipse.emf.common"
version="0.0.0"/> version="0.0.0"/>
<includes
id="org.eclipse.collections.feature"
version="0.0.0"/>
<requires> <requires>
<import plugin="org.eclipse.core.expressions" version="3.2.0" match="compatible"/> <import plugin="org.eclipse.core.expressions" version="3.2.0" match="compatible"/>
<import plugin="org.eclipse.core.filesystem" version="1.3.0" match="compatible"/> <import plugin="org.eclipse.core.filesystem" version="1.3.0" match="compatible"/>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.minres.scviewer</groupId> <groupId>com.minres.scviewer</groupId>
<artifactId>com.minres.scviewer.parent</artifactId> <artifactId>com.minres.scviewer.parent</artifactId>
<version>2.11.2-SNAPSHOT</version> <version>2.16.1</version>
<relativePath>../..</relativePath> <relativePath>../..</relativePath>
</parent> </parent>
<version>1.0.0-SNAPSHOT</version> <version>1.0.0-SNAPSHOT</version>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.minres.scviewer</groupId> <groupId>com.minres.scviewer</groupId>
<artifactId>com.minres.scviewer.parent</artifactId> <artifactId>com.minres.scviewer.parent</artifactId>
<version>2.11.2-SNAPSHOT</version> <version>2.16.1</version>
<relativePath>../..</relativePath> <relativePath>../..</relativePath>
</parent> </parent>
<version>1.1.0-SNAPSHOT</version> <version>1.1.0-SNAPSHOT</version>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.minres.scviewer</groupId> <groupId>com.minres.scviewer</groupId>
<artifactId>com.minres.scviewer.parent</artifactId> <artifactId>com.minres.scviewer.parent</artifactId>
<version>2.11.2-SNAPSHOT</version> <version>2.16.1</version>
<relativePath>../..</relativePath> <relativePath>../..</relativePath>
</parent> </parent>
<version>1.1.0-SNAPSHOT</version> <version>1.1.0-SNAPSHOT</version>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<classpath> <classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/> <classpathentry kind="src" path="src"/>
<classpathentry exported="true" kind="lib" path="sqlite-jdbc-3.8.7.jar"/> <classpathentry exported="true" kind="lib" path="sqlite-jdbc-3.8.7.jar"/>

View File

@ -1,8 +1,10 @@
eclipse.preferences.version=1 eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
org.eclipse.jdt.core.compiler.compliance=1.8 org.eclipse.jdt.core.compiler.compliance=11
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=11

View File

@ -4,7 +4,7 @@ Bundle-Name: SQLite transaction database
Bundle-SymbolicName: com.minres.scviewer.database.sqlite Bundle-SymbolicName: com.minres.scviewer.database.sqlite
Bundle-Version: 1.1.0.qualifier Bundle-Version: 1.1.0.qualifier
Bundle-Vendor: MINRES Technologies GmbH Bundle-Vendor: MINRES Technologies GmbH
Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-RequiredExecutionEnvironment: JavaSE-11
Require-Bundle: com.minres.scviewer.database;bundle-version="1.0.0" Require-Bundle: com.minres.scviewer.database;bundle-version="1.0.0"
Bundle-ClassPath: .,sqlite-jdbc-3.8.7.jar Bundle-ClassPath: .,sqlite-jdbc-3.8.7.jar
Service-Component: OSGI-INF/component.xml Service-Component: OSGI-INF/component.xml

View File

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.minres.scviewer</groupId> <groupId>com.minres.scviewer</groupId>
<artifactId>com.minres.scviewer.parent</artifactId> <artifactId>com.minres.scviewer.parent</artifactId>
<version>2.11.2-SNAPSHOT</version> <version>2.16.1</version>
<relativePath>../..</relativePath> <relativePath>../..</relativePath>
</parent> </parent>
<packaging>eclipse-plugin</packaging> <packaging>eclipse-plugin</packaging>

View File

@ -14,12 +14,13 @@ import java.sql.SQLException;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.TreeMap;
import com.minres.scviewer.database.EventEntry;
import com.minres.scviewer.database.EventKind; import com.minres.scviewer.database.EventKind;
import com.minres.scviewer.database.HierNode; import com.minres.scviewer.database.HierNode;
import com.minres.scviewer.database.IEvent; import com.minres.scviewer.database.IEvent;
import com.minres.scviewer.database.IEventList;
import com.minres.scviewer.database.EventList;
import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.RelationType; import com.minres.scviewer.database.RelationType;
import com.minres.scviewer.database.RelationTypeFactory; import com.minres.scviewer.database.RelationTypeFactory;
@ -35,18 +36,18 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
private Integer maxConcurrency; private Integer maxConcurrency;
private TreeMap<Long, IEvent[]> events; private IEventList events;
private List<RelationType> usedRelationsList; private List<RelationType> usedRelationsList;
public AbstractTxStream(IDatabase database, String name, long streamId) { protected AbstractTxStream(IDatabase database, String name, long streamId) {
super(name); super(name);
this.database=database; this.database=database;
this.streamId=streamId; this.streamId=streamId;
} }
@Override @Override
public int getWidth() { public int getRowCount() {
if(maxConcurrency==null){ if(maxConcurrency==null){
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("SELECT MAX(concurrencyLevel) as concurrencyLevel FROM ScvTx where stream="); sb.append("SELECT MAX(concurrencyLevel) as concurrencyLevel FROM ScvTx where stream=");
@ -71,9 +72,9 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
} }
@Override @Override
public NavigableMap<Long, IEvent[]> getEvents(){ public IEventList getEvents(){
if(events==null){ if(events==null){
events=new TreeMap<>(); events=new EventList();
for(Entry<Integer, ITx> entry:getTransactions().entrySet()){ for(Entry<Integer, ITx> entry:getTransactions().entrySet()){
putEvent(new TxEvent(EventKind.BEGIN, entry.getValue())); putEvent(new TxEvent(EventKind.BEGIN, entry.getValue()));
putEvent(new TxEvent(EventKind.END, entry.getValue())); putEvent(new TxEvent(EventKind.END, entry.getValue()));
@ -83,22 +84,13 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
} }
private void putEvent(TxEvent ev){ private void putEvent(TxEvent ev){
Long time = ev.getTime(); events.put(ev.getTime(), ev);
if(events.containsKey(time)) {
IEvent[] oldV = events.get(time);
IEvent[] newV = new IEvent[oldV.length+1];
System.arraycopy(oldV, 0, newV, 0, oldV.length);
newV[oldV.length]=ev;
events.put(time, newV);
} else {
events.put(time, new IEvent[] {ev});
}
} }
protected abstract Map<Integer, ITx> getTransactions(); protected abstract Map<Integer, ITx> getTransactions();
@Override @Override
public IEvent[] getEventsAtTime(Long time) { public IEvent[] getEventsAtTime(long time) {
return getEvents().get(time); return getEvents().get(time);
} }
@ -113,12 +105,12 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
} }
@Override @Override
public IEvent[] getEventsBeforeTime(Long time) { public IEvent[] getEventsBeforeTime(long time) {
Entry<Long, IEvent[]> e = events.floorEntry(time); EventEntry e = events.floorEntry(time);
if(e==null) if(e==null)
return new IEvent[]{}; return new IEvent[]{};
else else
return events.floorEntry(time).getValue(); return events.floorEntry(time).events;
} }
@Override @Override
@ -126,4 +118,11 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
return WaveformType.TRANSACTION; return WaveformType.TRANSACTION;
} }
/**
* Calculate concurrency.
*/
public void calculateConcurrency() {
}
} }

View File

@ -48,7 +48,7 @@ public class SQLiteDbLoader implements IWaveformDbLoader {
protected PropertyChangeSupport pcs = new PropertyChangeSupport(this); protected PropertyChangeSupport pcs = new PropertyChangeSupport(this);
@Override @Override
public Long getMaxTime() { public long getMaxTime() {
SQLiteDatabaseSelectHandler<ScvTxEvent> handler = new SQLiteDatabaseSelectHandler<>(ScvTxEvent.class, SQLiteDatabaseSelectHandler<ScvTxEvent> handler = new SQLiteDatabaseSelectHandler<>(ScvTxEvent.class,
database, "time = (SELECT MAX(time) FROM ScvTxEvent)"); database, "time = (SELECT MAX(time) FROM ScvTxEvent)");
try { try {
@ -56,7 +56,7 @@ public class SQLiteDbLoader implements IWaveformDbLoader {
if(!event.isEmpty()) if(!event.isEmpty())
return event.get(0).getTime()*scvSimProps.getTime_resolution(); return event.get(0).getTime()*scvSimProps.getTime_resolution();
} catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException } catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException
| InvocationTargetException | SQLException | IntrospectionException e) { | InvocationTargetException | SQLException | IntrospectionException | NoSuchMethodException e) {
e.printStackTrace(); e.printStackTrace();
} }
return 0L; return 0L;
@ -73,33 +73,32 @@ public class SQLiteDbLoader implements IWaveformDbLoader {
streams.add(stream); streams.add(stream);
} }
} catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException } catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException
| InvocationTargetException | SQLException | IntrospectionException e) { | InvocationTargetException | SQLException | IntrospectionException | NoSuchMethodException e) {
} }
return streams; return streams;
} }
@Override // @Override
public boolean canLoad(File inputFile) { // public boolean canLoad(File inputFile) {
if (!inputFile.isDirectory() && inputFile.exists()) { // if (!inputFile.isDirectory() && inputFile.exists()) {
try(InputStream stream = new FileInputStream(inputFile)){ // try(InputStream stream = new FileInputStream(inputFile)){
byte[] buffer = new byte[x.length]; // byte[] buffer = new byte[x.length];
int readCnt = stream.read(buffer, 0, x.length); // int readCnt = stream.read(buffer, 0, x.length);
if (readCnt == x.length) { // if (readCnt == x.length) {
for (int i = 0; i < x.length; i++) // for (int i = 0; i < x.length; i++)
if (buffer[i] != x[i]) // if (buffer[i] != x[i])
return false; // return false;
} // }
return true; // return true;
} catch (Exception e) { // } catch (Exception e) {
return false; // return false;
} // }
} // }
return false; // return false;
} // }
@Override @Override
public void load(IWaveformDb db, File file) throws InputFormatException { public void load(IWaveformDb db, File file) throws InputFormatException {
dispose();
database=new SQLiteDatabase(file.getAbsolutePath(), db); database=new SQLiteDatabase(file.getAbsolutePath(), db);
database.setData("TIMERESOLUTION", 1L); database.setData("TIMERESOLUTION", 1L);
SQLiteDatabaseSelectHandler<ScvSimProps> handler = new SQLiteDatabaseSelectHandler<>(ScvSimProps.class, database); SQLiteDatabaseSelectHandler<ScvSimProps> handler = new SQLiteDatabaseSelectHandler<>(ScvSimProps.class, database);
@ -110,7 +109,7 @@ public class SQLiteDbLoader implements IWaveformDbLoader {
} }
pcs.firePropertyChange(IWaveformDbLoader.LOADING_FINISHED, null, null); pcs.firePropertyChange(IWaveformDbLoader.LOADING_FINISHED, null, null);
} catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException } catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException
| InvocationTargetException | SQLException | IntrospectionException e) { | InvocationTargetException | SQLException | IntrospectionException | NoSuchMethodException e) {
throw new InputFormatException(e.toString()); throw new InputFormatException(e.toString());
} }
} }

View File

@ -28,7 +28,6 @@ import com.minres.scviewer.database.sqlite.tables.ScvTxEvent;
import com.minres.scviewer.database.sqlite.tables.ScvTxRelation; import com.minres.scviewer.database.sqlite.tables.ScvTxRelation;
import com.minres.scviewer.database.tx.ITx; import com.minres.scviewer.database.tx.ITx;
import com.minres.scviewer.database.tx.ITxAttribute; import com.minres.scviewer.database.tx.ITxAttribute;
import com.minres.scviewer.database.tx.ITxGenerator;
import com.minres.scviewer.database.tx.ITxRelation; import com.minres.scviewer.database.tx.ITxRelation;
public class Tx implements ITx { public class Tx implements ITx {
@ -38,8 +37,8 @@ public class Tx implements ITx {
private TxGenerator trGenerator; private TxGenerator trGenerator;
private ScvTx scvTx; private ScvTx scvTx;
private List<ITxAttribute> attributes; private List<ITxAttribute> attributes;
private Long begin; private long begin=-1;
private Long end; private long end=-1;
private List<ITxRelation> incoming; private List<ITxRelation> incoming;
private List<ITxRelation> outgoing; private List<ITxRelation> outgoing;
@ -51,7 +50,7 @@ public class Tx implements ITx {
} }
@Override @Override
public Long getId() { public long getId() {
return (long) scvTx.getId(); return (long) scvTx.getId();
} }
@ -61,18 +60,17 @@ public class Tx implements ITx {
} }
@Override @Override
public ITxGenerator getGenerator() { public IWaveform getGenerator() {
return trGenerator; return trGenerator;
} }
@Override int getConcurrencyIndex() {
public int getConcurrencyIndex() {
return scvTx.getConcurrencyLevel(); return scvTx.getConcurrencyLevel();
} }
@Override @Override
public Long getBeginTime() { public long getBeginTime() {
if(begin==null){ if(begin<0){
SQLiteDatabaseSelectHandler<ScvTxEvent> handler = new SQLiteDatabaseSelectHandler<>(ScvTxEvent.class, SQLiteDatabaseSelectHandler<ScvTxEvent> handler = new SQLiteDatabaseSelectHandler<>(ScvTxEvent.class,
database, "tx="+scvTx.getId()+" AND type="+ AssociationType.BEGIN.ordinal()); database, "tx="+scvTx.getId()+" AND type="+ AssociationType.BEGIN.ordinal());
try { try {
@ -80,15 +78,15 @@ public class Tx implements ITx {
begin= scvEvent.getTime()*(Long)database.getData("TIMERESOLUTION"); begin= scvEvent.getTime()*(Long)database.getData("TIMERESOLUTION");
} }
} catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException } catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException
| InvocationTargetException | SQLException | IntrospectionException e) { | InvocationTargetException | SQLException | IntrospectionException | NoSuchMethodException e) {
} }
} }
return begin; return begin;
} }
@Override @Override
public Long getEndTime() { public long getEndTime() {
if(end==null){ if(end<0){
SQLiteDatabaseSelectHandler<ScvTxEvent> handler = new SQLiteDatabaseSelectHandler<>(ScvTxEvent.class, SQLiteDatabaseSelectHandler<ScvTxEvent> handler = new SQLiteDatabaseSelectHandler<>(ScvTxEvent.class,
database, "tx="+scvTx.getId()+" AND type="+ AssociationType.END.ordinal()); database, "tx="+scvTx.getId()+" AND type="+ AssociationType.END.ordinal());
try { try {
@ -96,7 +94,7 @@ public class Tx implements ITx {
end = scvEvent.getTime()*(Long)database.getData("TIMERESOLUTION"); end = scvEvent.getTime()*(Long)database.getData("TIMERESOLUTION");
} }
} catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException } catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException
| InvocationTargetException | SQLException | IntrospectionException e) { | InvocationTargetException | SQLException | IntrospectionException | NoSuchMethodException e) {
} }
} }
return end; return end;
@ -114,7 +112,7 @@ public class Tx implements ITx {
} }
} catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException } catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException
| InvocationTargetException | SQLException | IntrospectionException e) { | InvocationTargetException | SQLException | IntrospectionException | NoSuchMethodException e) {
} }
} }
return attributes; return attributes;
@ -131,7 +129,7 @@ public class Tx implements ITx {
incoming.add(createRelation(scvRelation, false)); incoming.add(createRelation(scvRelation, false));
} }
} catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException } catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException
| InvocationTargetException | SQLException | IntrospectionException e) { | InvocationTargetException | SQLException | IntrospectionException | NoSuchMethodException e) {
} }
} }
return incoming; return incoming;
@ -148,7 +146,7 @@ public class Tx implements ITx {
outgoing.add(createRelation(scvRelation, true)); outgoing.add(createRelation(scvRelation, true));
} }
} catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException } catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException
| InvocationTargetException | SQLException | IntrospectionException e) { | InvocationTargetException | SQLException | IntrospectionException | NoSuchMethodException e) {
} }
} }
return outgoing; return outgoing;
@ -171,7 +169,7 @@ public class Tx implements ITx {
else else
return new TxRelation(trStream.getRelationType(rel.getName()), that, this); return new TxRelation(trStream.getRelationType(rel.getName()), that, this);
} catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException } catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException
| InvocationTargetException | SQLException | IntrospectionException e) { | InvocationTargetException | SQLException | IntrospectionException | NoSuchMethodException e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -180,11 +178,11 @@ public class Tx implements ITx {
@Override @Override
public int compareTo(ITx o) { public int compareTo(ITx o) {
int res = this.getBeginTime().compareTo(o.getBeginTime()); int res = Long.compare(this.getBeginTime(), o.getBeginTime());
if(res!=0) if(res!=0)
return res; return res;
else else
return this.getId().compareTo(o.getId()); return Long.compare(this.getId(), o.getId());
} }
@Override @Override

View File

@ -28,7 +28,7 @@ public class TxEvent implements ITxEvent {
} }
@Override @Override
public Long getTime() { public long getTime() {
return type==EventKind.BEGIN?tx.getBeginTime():tx.getEndTime(); return type==EventKind.BEGIN?tx.getBeginTime():tx.getEndTime();
} }
@ -56,4 +56,10 @@ public class TxEvent implements ITxEvent {
public WaveformType getType() { public WaveformType getType() {
return WaveformType.TRANSACTION; return WaveformType.TRANSACTION;
} }
@Override
public int getRowIndex() {
return ((Tx)tx).getConcurrencyIndex();
}
} }

View File

@ -22,9 +22,8 @@ import com.minres.scviewer.database.sqlite.db.SQLiteDatabaseSelectHandler;
import com.minres.scviewer.database.sqlite.tables.ScvGenerator; import com.minres.scviewer.database.sqlite.tables.ScvGenerator;
import com.minres.scviewer.database.sqlite.tables.ScvTx; import com.minres.scviewer.database.sqlite.tables.ScvTx;
import com.minres.scviewer.database.tx.ITx; import com.minres.scviewer.database.tx.ITx;
import com.minres.scviewer.database.tx.ITxGenerator;
public class TxGenerator extends AbstractTxStream implements ITxGenerator { public class TxGenerator extends AbstractTxStream {
private TxStream stream; private TxStream stream;
@ -40,15 +39,10 @@ public class TxGenerator extends AbstractTxStream implements ITxGenerator {
} }
@Override @Override
public Long getId() { public long getId() {
return (long) scvGenerator.getId(); return (long) scvGenerator.getId();
} }
@Override
public IWaveform getStream() {
return stream;
}
@Override @Override
public String getName() { public String getName() {
return scvGenerator.getName(); return scvGenerator.getName();
@ -56,7 +50,7 @@ public class TxGenerator extends AbstractTxStream implements ITxGenerator {
@Override @Override
public boolean isSame(IWaveform other) { public boolean isSame(IWaveform other) {
return(other instanceof TxGenerator && this.getId().equals(other.getId())); return(other instanceof TxGenerator && this.getId() == other.getId());
} }
@Override @Override
@ -75,7 +69,7 @@ public class TxGenerator extends AbstractTxStream implements ITxGenerator {
transactions.put(scvTx.getId(), new Tx(database, (TxStream) stream, this, scvTx)); transactions.put(scvTx.getId(), new Tx(database, (TxStream) stream, this, scvTx));
} }
} catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException } catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException
| InvocationTargetException | SQLException | IntrospectionException e) { | InvocationTargetException | SQLException | IntrospectionException | NoSuchMethodException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }

View File

@ -26,7 +26,6 @@ import com.minres.scviewer.database.sqlite.tables.ScvGenerator;
import com.minres.scviewer.database.sqlite.tables.ScvStream; import com.minres.scviewer.database.sqlite.tables.ScvStream;
import com.minres.scviewer.database.sqlite.tables.ScvTx; import com.minres.scviewer.database.sqlite.tables.ScvTx;
import com.minres.scviewer.database.tx.ITx; import com.minres.scviewer.database.tx.ITx;
import com.minres.scviewer.database.tx.ITxGenerator;
public class TxStream extends AbstractTxStream { public class TxStream extends AbstractTxStream {
@ -50,11 +49,11 @@ public class TxStream extends AbstractTxStream {
} }
@Override @Override
public Long getId() { public long getId() {
return (long) scvStream.getId(); return (long) scvStream.getId();
} }
public List<ITxGenerator> getGenerators() { public List<IWaveform> getGenerators() {
if(generators==null){ if(generators==null){
SQLiteDatabaseSelectHandler<ScvGenerator> handler = new SQLiteDatabaseSelectHandler<>( SQLiteDatabaseSelectHandler<ScvGenerator> handler = new SQLiteDatabaseSelectHandler<>(
ScvGenerator.class, database, "stream="+scvStream.getId()); ScvGenerator.class, database, "stream="+scvStream.getId());
@ -64,7 +63,7 @@ public class TxStream extends AbstractTxStream {
generators.put(scvGenerator.getId(), new TxGenerator(database, this, scvGenerator)); generators.put(scvGenerator.getId(), new TxGenerator(database, this, scvGenerator));
} }
} catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException } catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException
| InvocationTargetException | SQLException | IntrospectionException e) { | InvocationTargetException | SQLException | IntrospectionException | NoSuchMethodException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
@ -82,7 +81,7 @@ public class TxStream extends AbstractTxStream {
transactions.put(scvTx.getId(), new Tx(database, this, generators.get(scvTx.getGenerator()), scvTx)); transactions.put(scvTx.getId(), new Tx(database, this, generators.get(scvTx.getGenerator()), scvTx));
} }
} catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException } catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException
| InvocationTargetException | SQLException | IntrospectionException e) { | InvocationTargetException | SQLException | IntrospectionException | NoSuchMethodException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
@ -90,13 +89,13 @@ public class TxStream extends AbstractTxStream {
} }
@Override @Override
public IEvent[] getEventsAtTime(Long time) { public IEvent[] getEventsAtTime(long time) {
return getEvents().get(time); return getEvents().get(time);
} }
@Override @Override
public boolean isSame(IWaveform other) { public boolean isSame(IWaveform other) {
return(other instanceof TxStream && this.getId().equals(other.getId())); return(other instanceof TxStream && this.getId() == other.getId());
} }
@Override @Override

View File

@ -75,10 +75,11 @@ public class SQLiteDatabaseSelectHandler<T> extends AbstractDatabaseHandler<T> {
* @throws IllegalAccessException * @throws IllegalAccessException
* @throws IntrospectionException * @throws IntrospectionException
* @throws InvocationTargetException * @throws InvocationTargetException
* @throws NoSuchMethodException
*/ */
public synchronized List<T> selectObjects() throws SQLException, public synchronized List<T> selectObjects() throws SQLException,
InstantiationException, IllegalAccessException, InstantiationException, IllegalAccessException,
IntrospectionException, InvocationTargetException { IntrospectionException, InvocationTargetException, IllegalArgumentException, NoSuchMethodException, SecurityException {
Connection connection = null; Connection connection = null;
Statement statement = null; Statement statement = null;
@ -113,17 +114,18 @@ public class SQLiteDatabaseSelectHandler<T> extends AbstractDatabaseHandler<T> {
* @throws IllegalAccessException * @throws IllegalAccessException
* @throws IntrospectionException * @throws IntrospectionException
* @throws InvocationTargetException * @throws InvocationTargetException
* @throws NoSuchMethodException
*/ */
private List<T> createObjects(ResultSet resultSet) private List<T> createObjects(ResultSet resultSet)
throws SQLException, InstantiationException, throws SQLException, InstantiationException,
IllegalAccessException, IntrospectionException, IllegalAccessException, IntrospectionException,
InvocationTargetException { InvocationTargetException, IllegalArgumentException, NoSuchMethodException, SecurityException {
List<T> list = new ArrayList<>(); List<T> list = new ArrayList<>();
while (resultSet.next()) { while (resultSet.next()) {
T instance = type.newInstance(); T instance = type.getDeclaredConstructor().newInstance();
for (Field field : type.getDeclaredFields()) { for (Field field : type.getDeclaredFields()) {

View File

@ -1,17 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<classpath> <classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/>
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src/"/>
<classpathentry exported="true" kind="lib" path="lib/mapdb-3.0.7.jar" sourcepath="lib/mapdb-3.0.7-sources.jar"> <classpathentry exported="true" kind="lib" path="lib/mapdb-3.0.7.jar" sourcepath="lib/mapdb-3.0.7-sources.jar">
<attributes> <attributes>
<attribute name="javadoc_location" value="jar:platform:/resource/com.minres.scviewer.database.text/lib/mapdb-3.0.7-javadoc.jar!/"/> <attribute name="javadoc_location" value="jar:platform:/resource/com.minres.scviewer.database.text/lib/mapdb-3.0.7-javadoc.jar!/"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="src" path="src"/>
<classpathentry exported="true" kind="lib" path="lib/kotlin-stdlib-1.2.42.jar"/> <classpathentry exported="true" kind="lib" path="lib/kotlin-stdlib-1.2.42.jar"/>
<classpathentry exported="true" kind="lib" path="lib/lz4-1.3.0.jar"/> <classpathentry exported="true" kind="lib" path="lib/lz4-1.3.0.jar"/>
<classpathentry exported="true" kind="lib" path="lib/elsa-3.0.0-M5.jar"/> <classpathentry exported="true" kind="lib" path="lib/elsa-3.0.0-M5.jar"/>

View File

@ -1,9 +1,11 @@
eclipse.preferences.version=1 eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
org.eclipse.jdt.core.compiler.compliance=1.8 org.eclipse.jdt.core.compiler.compliance=11
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=11

View File

@ -2,14 +2,15 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2 Bundle-ManifestVersion: 2
Bundle-Name: Textual transaction database Bundle-Name: Textual transaction database
Bundle-SymbolicName: com.minres.scviewer.database.text Bundle-SymbolicName: com.minres.scviewer.database.text
Bundle-Version: 3.0.0.qualifier Bundle-Version: 4.0.1.qualifier
Bundle-Vendor: MINRES Technologies GmbH Bundle-Vendor: MINRES Technologies GmbH
Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-RequiredExecutionEnvironment: JavaSE-11
Import-Package: org.osgi.framework;version="1.3.0" Import-Package: org.osgi.framework;version="1.3.0"
Require-Bundle: com.minres.scviewer.database, Require-Bundle: com.minres.scviewer.database,
org.eclipse.osgi.services;bundle-version="3.4.0", org.eclipse.osgi.services;bundle-version="3.4.0",
com.google.guava;bundle-version="15.0.0", com.google.guava;bundle-version="15.0.0",
org.eclipse.collections;bundle-version="10.4.0" org.eclipse.collections;bundle-version="10.4.0",
org.apache.commons.compress;bundle-version="1.20.0"
Service-Component: OSGI-INF/component.xml Service-Component: OSGI-INF/component.xml
Bundle-ActivationPolicy: lazy Bundle-ActivationPolicy: lazy
Automatic-Module-Name: com.minres.scviewer.database.text Automatic-Module-Name: com.minres.scviewer.database.text

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="TextDbLoader"> <scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="TextDbLoaderFactory">
<implementation class="com.minres.scviewer.database.text.TextDbLoader"/> <implementation class="com.minres.scviewer.database.text.TextDbLoaderFactory"/>
<service> <service>
<provide interface="com.minres.scviewer.database.IWaveformDbLoader"/> <provide interface="com.minres.scviewer.database.IWaveformDbLoaderFactory"/>
</service> </service>
</scr:component> </scr:component>

View File

@ -2,11 +2,11 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>com.minres.scviewer.database.text</artifactId> <artifactId>com.minres.scviewer.database.text</artifactId>
<version>3.0.0-SNAPSHOT</version> <version>4.0.1-SNAPSHOT</version>
<parent> <parent>
<groupId>com.minres.scviewer</groupId> <groupId>com.minres.scviewer</groupId>
<artifactId>com.minres.scviewer.parent</artifactId> <artifactId>com.minres.scviewer.parent</artifactId>
<version>2.11.2-SNAPSHOT</version> <version>2.16.1</version>
<relativePath>../..</relativePath> <relativePath>../..</relativePath>
</parent> </parent>
<packaging>eclipse-plugin</packaging> <packaging>eclipse-plugin</packaging>

View File

@ -12,16 +12,16 @@
package com.minres.scviewer.database.text; package com.minres.scviewer.database.text;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.HashMap;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.TreeMap;
import com.minres.scviewer.database.EventKind; import com.minres.scviewer.database.EventEntry;
import com.minres.scviewer.database.EventList;
import com.minres.scviewer.database.HierNode; import com.minres.scviewer.database.HierNode;
import com.minres.scviewer.database.IEvent; import com.minres.scviewer.database.IEvent;
import com.minres.scviewer.database.IEventList;
import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.WaveformType; import com.minres.scviewer.database.WaveformType;
import com.minres.scviewer.database.tx.ITx;
import com.minres.scviewer.database.tx.ITxEvent; import com.minres.scviewer.database.tx.ITxEvent;
/** /**
@ -29,6 +29,8 @@ import com.minres.scviewer.database.tx.ITxEvent;
*/ */
abstract class AbstractTxStream extends HierNode implements IWaveform { abstract class AbstractTxStream extends HierNode implements IWaveform {
private final String fullName;
/** The id. */ /** The id. */
private Long id; private Long id;
@ -36,10 +38,10 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
protected TextDbLoader loader; protected TextDbLoader loader;
/** The events. */ /** The events. */
TreeMap<Long, IEvent[]> events = new TreeMap<>(); IEventList events = new EventList();
/** The concurrency calculated. */ /** The max concurrency. */
boolean concurrencyCalculated = false; private int rowCount = -1;
/** /**
* Instantiates a new abstract tx stream. * Instantiates a new abstract tx stream.
@ -48,26 +50,29 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
* @param id the id * @param id the id
* @param name the name * @param name the name
*/ */
public AbstractTxStream(TextDbLoader loader, Long id, String name) { protected AbstractTxStream(TextDbLoader loader, Long id, String name) {
super(name); super(name);
fullName=name;
this.loader = loader; this.loader = loader;
this.id = id; this.id = id;
} }
/**
* Gets the full hierarchical name.
*
* @return the full name
*/
@Override
public String getFullName() {
return fullName;
}
/** /**
* Adds the event. * Adds the event.
* *
* @param evt the evt * @param evt the evt
*/ */
public void addEvent(ITxEvent evt) { public void addEvent(ITxEvent evt) {
if (!events.containsKey(evt.getTime())) events.put(evt.getTime(), evt);
events.put(evt.getTime(), new IEvent[] { evt });
else {
IEvent[] evts = events.get(evt.getTime());
IEvent[] newEvts = Arrays.copyOf(evts, evts.length + 1);
newEvts[evts.length] = evt;
events.put(evt.getTime(), newEvts);
}
} }
/** /**
@ -76,9 +81,7 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
* @return the events * @return the events
*/ */
@Override @Override
public NavigableMap<Long, IEvent[]> getEvents() { public IEventList getEvents() {
if (!concurrencyCalculated)
calculateConcurrency();
return events; return events;
} }
@ -89,9 +92,7 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
* @return the events at time * @return the events at time
*/ */
@Override @Override
public IEvent[] getEventsAtTime(Long time) { public IEvent[] getEventsAtTime(long time) {
if (!concurrencyCalculated)
calculateConcurrency();
return events.get(time); return events.get(time);
} }
@ -102,14 +103,12 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
* @return the events before time * @return the events before time
*/ */
@Override @Override
public IEvent[] getEventsBeforeTime(Long time) { public IEvent[] getEventsBeforeTime(long time) {
if (!concurrencyCalculated) EventEntry e = events.floorEntry(time);
calculateConcurrency();
Entry<Long, IEvent[]> e = events.floorEntry(time);
if (e == null) if (e == null)
return new IEvent[] {}; return new IEvent[] {};
else else
return events.floorEntry(time).getValue(); return events.floorEntry(time).events;
} }
/** /**
@ -128,32 +127,63 @@ abstract class AbstractTxStream extends HierNode implements IWaveform {
* @return the id * @return the id
*/ */
@Override @Override
public Long getId() { public long getId() {
return id; return id;
} }
/**
* Gets the width.
*
* @return the width
*/
@Override
public int getRowCount() {
if (rowCount<0)
calculateConcurrency();
return rowCount;
}
/** /**
* Calculate concurrency. * Calculate concurrency.
*/ */
synchronized void calculateConcurrency() { void calculateConcurrency() {
if (concurrencyCalculated) if (rowCount>=0)
return; return;
ArrayList<Long> rowendtime = new ArrayList<>(); ArrayList<Long> rowEndTime = new ArrayList<>();
events.entrySet().stream().forEach(entry -> { HashMap<Long, Integer> rowByTxId = new HashMap<>();
IEvent[] values = entry.getValue(); for(EventEntry entry: events) {
Arrays.asList(values).stream().filter(e -> e.getKind() == EventKind.BEGIN).forEach(evt -> { for(IEvent evt:entry.events) {
Tx tx = (Tx) ((TxEvent) evt).getTransaction(); TxEvent txEvt = (TxEvent) evt;
ITx tx = txEvt.getTransaction();
int rowIdx = 0; int rowIdx = 0;
for (; rowIdx < rowendtime.size() && rowendtime.get(rowIdx) > tx.getBeginTime(); rowIdx++) switch(evt.getKind()) {
; case END:
if (rowendtime.size() <= rowIdx) Long txId = txEvt.getTransaction().getId();
rowendtime.add(tx.getEndTime()); txEvt.setConcurrencyIndex(rowByTxId.get(txId));
else rowByTxId.remove(txId);
rowendtime.set(rowIdx, tx.getEndTime()); break;
tx.setConcurrencyIndex(rowIdx); case SINGLE:
}); for (; rowIdx < rowEndTime.size() && rowEndTime.get(rowIdx)>tx.getBeginTime(); rowIdx++);
}); if (rowEndTime.size() <= rowIdx)
concurrencyCalculated = true; rowEndTime.add(tx.getEndTime());
else
rowEndTime.set(rowIdx, tx.getEndTime());
((TxEvent) evt).setConcurrencyIndex(rowIdx);
break;
case BEGIN:
for (; rowIdx < rowEndTime.size() && rowEndTime.get(rowIdx)>tx.getBeginTime(); rowIdx++);
if (rowEndTime.size() <= rowIdx)
rowEndTime.add(tx.getEndTime());
else
rowEndTime.set(rowIdx, tx.getEndTime());
((TxEvent) evt).setConcurrencyIndex(rowIdx);
rowByTxId.put(tx.getId(), rowIdx);
break;
}
}
}
rowCount=rowEndTime.size()>0?rowEndTime.size():1;
getChildNodes().parallelStream().forEach(c -> ((TxGenerator)c).calculateConcurrency());
} }
} }

View File

@ -13,6 +13,7 @@ package com.minres.scviewer.database.text;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport; import java.beans.PropertyChangeSupport;
import java.io.BufferedInputStream;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -28,14 +29,14 @@ import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import org.apache.commons.compress.compressors.lz4.FramedLZ4CompressorInputStream;
import org.eclipse.collections.impl.map.mutable.UnifiedMap; import org.eclipse.collections.impl.map.mutable.UnifiedMap;
import org.mapdb.DB; import org.mapdb.DB;
import org.mapdb.DB.HashMapMaker;
import org.mapdb.DB.TreeMapSink;
import org.mapdb.DBMaker; import org.mapdb.DBMaker;
import org.mapdb.HTreeMap; import org.mapdb.HTreeMap;
import org.mapdb.Serializer; import org.mapdb.Serializer;
@ -57,13 +58,15 @@ import com.minres.scviewer.database.tx.ITx;
*/ */
public class TextDbLoader implements IWaveformDbLoader { public class TextDbLoader implements IWaveformDbLoader {
enum FileType { NONE, PLAIN, GZIP, LZ4};
/** the file size limit of a zipped txlog where the loader starts to use a file mapped database */ /** the file size limit of a zipped txlog where the loader starts to use a file mapped database */
private static final long MEMMAP_LIMIT=256l*1024l*1024l; private static final long MEMMAP_LIMIT=256l*1024l*1024l;
private static final long MAPDB_INITIAL_ALLOC = 512l*1024l*1024l; private static final long MAPDB_INITIAL_ALLOC = 512l*1024l*1024l;
private static final long MAPDB_INCREMENTAL_ALLOC = 128l*1024l*1024l; private static final long MAPDB_INCREMENTAL_ALLOC = 128l*1024l*1024l;
/** The max time. */ /** The max time. */
private Long maxTime = 0L; private Long maxTime = 0L;
@ -106,18 +109,59 @@ public class TextDbLoader implements IWaveformDbLoader {
/** The Constant x. */ /** The Constant x. */
static final byte[] x = "scv_tr_stream".getBytes(); static final byte[] x = "scv_tr_stream".getBytes();
/**
* Adds the property change listener.
*
* @param l the l
*/
@Override
public void addPropertyChangeListener(PropertyChangeListener l) {
pcs.addPropertyChangeListener(l);
}
/**
* Removes the property change listener.
*
* @param l the l
*/
@Override
public void removePropertyChangeListener(PropertyChangeListener l) {
pcs.removePropertyChangeListener(l);
}
/** /**
* Gets the max time. * Gets the max time.
* *
* @return the max time * @return the max time
*/ */
@Override @Override
public Long getMaxTime() { public long getMaxTime() {
return maxTime; return maxTime;
} }
/**
* Gets the transaction.
*
* @param txId the tx id
* @return the transaction
*/
public ITx getTransaction(long txId) {
if (txCache.containsKey(txId))
return txCache.get(txId);
if(transactions.containsKey(txId)) {
Tx tx = new Tx(this, transactions.get(txId));
txCache.put(txId, tx);
return tx;
} else {
throw new IllegalArgumentException();
}
}
public ScvTx getScvTx(long id) { public ScvTx getScvTx(long id) {
return transactions.get(id); if(transactions.containsKey(id))
return transactions.get(id);
else
throw new IllegalArgumentException();
} }
/** /**
@ -127,33 +171,45 @@ public class TextDbLoader implements IWaveformDbLoader {
*/ */
@Override @Override
public Collection<IWaveform> getAllWaves() { public Collection<IWaveform> getAllWaves() {
return new ArrayList<>(txStreams.values()); ArrayList<IWaveform> ret = new ArrayList<>(txStreams.values());
ret.addAll(txGenerators.values());
return ret;
} }
/** /**
* Can load. * Gets the all relation types.
* *
* @param inputFile the input file * @return the all relation types
* @return true, if successful
*/ */
@Override public Collection<RelationType> getAllRelationTypes() {
public boolean canLoad(File inputFile) { return relationTypes.values();
if (!inputFile.isDirectory() && inputFile.exists()) { }
boolean gzipped = isGzipped(inputFile);
try(InputStream stream = gzipped ? new GZIPInputStream(new FileInputStream(inputFile)) : new FileInputStream(inputFile)){ /**
byte[] buffer = new byte[x.length]; * Checks if is gzipped.
int readCnt = stream.read(buffer, 0, x.length); *
if (readCnt == x.length) { * @param f the f
for (int i = 0; i < x.length; i++) * @return true, if is gzipped
if (buffer[i] != x[i]) */
return false; static FileType getFileType(File f) {
} try (InputStream is = new FileInputStream(f)) {
return true; byte[] signature = new byte[4];
} catch (Exception e) { int nread = is.read(signature); // read the gzip signature
return false; if(nread >= 2 &&
} signature[0] == (byte) 0x1f &&
signature[1] == (byte) 0x8b)
return FileType.GZIP;
else if(nread>=4 &&
signature[0] == (byte) 0x04 &&
signature[1] == (byte) 0x22 &&
signature[2] == (byte) 0x4d &&
signature[3] == (byte) 0x18)
return FileType.LZ4;
else
return FileType.PLAIN;
} catch (IOException e) {
return FileType.NONE;
} }
return false;
} }
/** /**
@ -168,8 +224,8 @@ public class TextDbLoader implements IWaveformDbLoader {
@Override @Override
public void load(IWaveformDb db, File file) throws InputFormatException { public void load(IWaveformDb db, File file) throws InputFormatException {
dispose(); dispose();
boolean gzipped = isGzipped(file); FileType fType = getFileType(file);
if (file.length() < MEMMAP_LIMIT * (gzipped ? 1 : 10) if (file.length() < MEMMAP_LIMIT * (fType!=FileType.PLAIN ? 1 : 10)
|| "memory".equals(System.getProperty("ScvBackingDB", "file"))) || "memory".equals(System.getProperty("ScvBackingDB", "file")))
mapDb = DBMaker.memoryDirectDB().make(); mapDb = DBMaker.memoryDirectDB().make();
else { else {
@ -187,29 +243,17 @@ public class TextDbLoader implements IWaveformDbLoader {
} }
TextDbParser parser = new TextDbParser(this); TextDbParser parser = new TextDbParser(this);
try { try {
// parser.txSink = mapDb.treeMap("transactions", Serializer.LONG, Serializer.JAVA).createFromSink();
parser.txSink = mapDb.hashMap("transactions", Serializer.LONG, Serializer.JAVA).create(); parser.txSink = mapDb.hashMap("transactions", Serializer.LONG, Serializer.JAVA).create();
parser.parseInput(gzipped ? new GZIPInputStream(new FileInputStream(file)) : new FileInputStream(file)); InputStream is = new BufferedInputStream(new FileInputStream(file));
// transactions = parser.txSink.create(); parser.parseInput(fType==FileType.GZIP ? new GZIPInputStream(is) : fType==FileType.LZ4? new FramedLZ4CompressorInputStream(is) : is);
transactions = parser.txSink;
} catch (IllegalArgumentException | ArrayIndexOutOfBoundsException e) { } catch (IllegalArgumentException | ArrayIndexOutOfBoundsException e) {
} catch (Exception e) { } catch (Exception e) {
throw new InputFormatException(e.toString()); throw new InputFormatException(e.toString());
} finally {
transactions = parser.txSink;
} }
for (TxStream stream : txStreams.values()) { txStreams.values().parallelStream().forEach(TxStream::calculateConcurrency);
Thread t = new Thread() {
@Override
public void run() {
try {
stream.calculateConcurrency();
} catch (Exception e) {
/* don't let exceptions bubble up */ }
}
};
threads.add(t);
t.start();
}
} }
/** /**
@ -231,31 +275,6 @@ public class TextDbLoader implements IWaveformDbLoader {
} }
} }
/**
* Checks if is gzipped.
*
* @param f the f
* @return true, if is gzipped
*/
private static boolean isGzipped(File f) {
try (InputStream is = new FileInputStream(f)) {
byte[] signature = new byte[2];
int nread = is.read(signature); // read the gzip signature
return nread == 2 && signature[0] == (byte) 0x1f && signature[1] == (byte) 0x8b;
} catch (IOException e) {
return false;
}
}
/**
* Gets the all relation types.
*
* @return the all relation types
*/
public Collection<RelationType> getAllRelationTypes() {
return relationTypes.values();
}
/** /**
* The Class TextDbParser. * The Class TextDbParser.
*/ */
@ -312,15 +331,22 @@ public class TextDbLoader implements IWaveformDbLoader {
* @throws IOException Signals that an I/O exception has occurred. * @throws IOException Signals that an I/O exception has occurred.
* @throws InputFormatException Signals that the input format is wrong * @throws InputFormatException Signals that the input format is wrong
*/ */
void parseInput(InputStream inputStream) throws IOException, InputFormatException { void parseInput(InputStream inputStream) throws InputFormatException {
reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); try {
String curLine = reader.readLine(); reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
String nextLine = null; String curLine = reader.readLine();
while ((nextLine = reader.readLine()) != null && curLine != null) { String nextLine = null;
curLine = parseLine(curLine, nextLine); while ((nextLine = reader.readLine()) != null && curLine != null) {
} curLine = parseLine(curLine, nextLine, false);
if (curLine != null) }
parseLine(curLine, nextLine); if (curLine != null)
parseLine(curLine, nextLine, true);
for(Entry<Long, ScvTx> e: transactionById.entrySet()) {
ScvTx scvTx = e.getValue();
scvTx.endTime=loader.maxTime;
txSink.put(e.getKey(), scvTx);
}
} catch(IOException e) {}
} }
/** /**
@ -352,87 +378,87 @@ public class TextDbLoader implements IWaveformDbLoader {
* @throws IOException Signals that an I/O exception has occurred. * @throws IOException Signals that an I/O exception has occurred.
* @throws InputFormatException Signals that the input format is wrong * @throws InputFormatException Signals that the input format is wrong
*/ */
private String parseLine(String curLine, String nextLine) throws IOException, InputFormatException { private String parseLine(String curLine, String nextLine, boolean last) throws IOException, InputFormatException {
String[] tokens = curLine.split("\\s+"); if(curLine.charAt(0)=='t') {
if ("tx_record_attribute".equals(tokens[0])) { String[] tokens = curLine.split(" ");
Long id = Long.parseLong(tokens[1]); //if ("tx_record_attribute".equals(tokens[0]) && tokens.length>4) {
String name = tokens[2].substring(1, tokens[2].length()-1); if (curLine.charAt(5)=='c' && tokens.length>4) {
DataType type = DataType.valueOf(tokens[3]); Long id = Long.parseLong(tokens[1]);
String remaining = tokens.length > 5 ? String.join(" ", Arrays.copyOfRange(tokens, 5, tokens.length)) : ""; String name = tokens[2].substring(1, tokens[2].length()-1);
TxAttributeType attrType = getAttrType(name, type, AssociationType.RECORD); DataType type = DataType.valueOf(tokens[3]);
transactionById.get(id).attributes.add(new TxAttribute(attrType, getAttrString(attrType, remaining))); String remaining = tokens.length > 5 ? String.join(" ", Arrays.copyOfRange(tokens, 5, tokens.length)) : "";
} else if ("tx_begin".equals(tokens[0])) { TxAttributeType attrType = getAttrType(name, type, AssociationType.RECORD);
Long id = Long.parseLong(tokens[1]); transactionById.get(id).attributes.add(new TxAttribute(attrType, getAttrString(attrType, remaining)));
Long genId = Long.parseLong(tokens[2]); //} else if ("tx_begin".equals(tokens[0]) && tokens.length>4) {
TxGenerator gen = loader.txGenerators.get(genId); } else if (curLine.charAt(3)=='b' && tokens.length>4) {
ScvTx scvTx = new ScvTx(id, gen.stream.getId(), genId, Long id = Long.parseLong(tokens[1]);
Long.parseLong(tokens[3]) * stringToScale(tokens[4])); Long genId = Long.parseLong(tokens[2]);
loader.maxTime = loader.maxTime > scvTx.beginTime ? loader.maxTime : scvTx.beginTime; TxGenerator gen = loader.txGenerators.get(genId);
TxStream stream = loader.txStreams.get(gen.stream.getId()); ScvTx scvTx = new ScvTx(id, gen.stream.getId(), genId,
stream.setConcurrency(stream.getConcurrency() + 1); Long.parseLong(tokens[3]) * stringToScale(tokens[4]));
if (nextLine != null && nextLine.charAt(0) == 'a') { loader.maxTime = loader.maxTime > scvTx.beginTime ? loader.maxTime : scvTx.beginTime;
int idx = 0; if (nextLine != null && nextLine.charAt(0) == 'a') {
while (nextLine != null && nextLine.charAt(0) == 'a') { int idx = 0;
String[] attrTokens = nextLine.split("\\s+"); while (nextLine != null && nextLine.charAt(0) == 'a') {
TxAttributeType attrType = gen.beginAttrs.get(idx); String[] attrTokens = nextLine.split("\\s+");
TxAttribute attr = new TxAttribute(attrType, getAttrString(attrType, attrTokens[1])); TxAttributeType attrType = gen.beginAttrs.get(idx);
scvTx.attributes.add(attr); TxAttribute attr = new TxAttribute(attrType, getAttrString(attrType, attrTokens[1]));
idx++; scvTx.attributes.add(attr);
nextLine = reader.readLine(); idx++;
nextLine = reader.readLine();
}
} }
} transactionById.put(id, scvTx);
transactionById.put(id, scvTx); //} else if ("tx_end".equals(tokens[0]) && tokens.length>4) {
} else if ("tx_end".equals(tokens[0])) { } else if (curLine.charAt(3)=='e' && tokens.length>4) {
Long id = Long.parseLong(tokens[1]); Long id = Long.parseLong(tokens[1]);
ScvTx scvTx = transactionById.get(id); ScvTx scvTx = transactionById.get(id);
assert Long.parseLong(tokens[2]) == scvTx.generatorId; assert Long.parseLong(tokens[2]) == scvTx.generatorId;
scvTx.endTime = Long.parseLong(tokens[3]) * stringToScale(tokens[4]); scvTx.endTime = Long.parseLong(tokens[3]) * stringToScale(tokens[4]);
loader.maxTime = loader.maxTime > scvTx.endTime ? loader.maxTime : scvTx.endTime; loader.maxTime = loader.maxTime > scvTx.endTime ? loader.maxTime : scvTx.endTime;
TxGenerator gen = loader.txGenerators.get(scvTx.generatorId); TxGenerator gen = loader.txGenerators.get(scvTx.generatorId);
TxStream stream = loader.txStreams.get(gen.stream.getId()); TxStream stream = loader.txStreams.get(gen.stream.getId());
if (scvTx.beginTime == scvTx.endTime) { if (scvTx.beginTime == scvTx.endTime) {
TxEvent evt = new TxEvent(loader, EventKind.SINGLE, id, scvTx.beginTime); stream.addEvent(new TxEvent(loader, EventKind.SINGLE, id, scvTx.beginTime));
stream.addEvent(evt); gen.addEvent(new TxEvent(loader, EventKind.SINGLE, id, scvTx.beginTime));
gen.addEvent(evt); } else {
} else { stream.addEvent(new TxEvent(loader, EventKind.BEGIN, id, scvTx.beginTime));
TxEvent begEvt = new TxEvent(loader, EventKind.BEGIN, id, scvTx.beginTime); gen.addEvent(new TxEvent(loader, EventKind.BEGIN, id, scvTx.beginTime));
stream.addEvent(begEvt); stream.addEvent(new TxEvent(loader, EventKind.END, id, scvTx.endTime));
gen.addEvent(begEvt); gen.addEvent(new TxEvent(loader, EventKind.END, id, scvTx.endTime));
TxEvent endEvt = new TxEvent(loader, EventKind.END, id, scvTx.endTime);
stream.addEvent(endEvt);
gen.addEvent(endEvt);
}
stream.setConcurrency(stream.getConcurrency() - 1);
if (nextLine != null && nextLine.charAt(0) == 'a') {
int idx = 0;
while (nextLine != null && nextLine.charAt(0) == 'a') {
String[] attrTokens = nextLine.split("\\s+");
TxAttributeType attrType = gen.endAttrs.get(idx);
TxAttribute attr = new TxAttribute(attrType, getAttrString(attrType, attrTokens[1]));
scvTx.attributes.add(attr);
idx++;
nextLine = reader.readLine();
} }
if (nextLine != null && nextLine.charAt(0) == 'a') {
int idx = 0;
while (nextLine != null && nextLine.charAt(0) == 'a') {
String[] attrTokens = nextLine.split("\\s+");
TxAttributeType attrType = gen.endAttrs.get(idx);
TxAttribute attr = new TxAttribute(attrType, getAttrString(attrType, attrTokens[1]));
scvTx.attributes.add(attr);
idx++;
nextLine = reader.readLine();
}
}
txSink.put(scvTx.getId(), scvTx);
transactionById.remove(id);
//} else if ("tx_relation".equals(tokens[0]) && tokens.length>3) {
} else if (curLine.charAt(5)=='l' && tokens.length>3) {
Long tr2 = Long.parseLong(tokens[2]);
Long tr1 = Long.parseLong(tokens[3]);
String relType = tokens[1].substring(1, tokens[1].length() - 1);
if (!loader.relationTypes.containsKey(relType))
loader.relationTypes.put(relType, RelationTypeFactory.create(relType));
ScvRelation rel = new ScvRelation(loader.relationTypes.get(relType), tr1, tr2);
loader.relationsOut.put(tr1, rel);
loader.relationsIn.put(tr2, rel);
} }
txSink.put(scvTx.getId(), scvTx); } else if (curLine.length()>13 && "scv_tr_stream".equals(curLine.substring(0, 13))) {
transactionById.remove(id);
} else if ("tx_relation".equals(tokens[0])) {
Long tr2 = Long.parseLong(tokens[2]);
Long tr1 = Long.parseLong(tokens[3]);
String relType = tokens[1].substring(1, tokens[1].length() - 1);
if (!loader.relationTypes.containsKey(relType))
loader.relationTypes.put(relType, RelationTypeFactory.create(relType));
ScvRelation rel = new ScvRelation(loader.relationTypes.get(relType), tr1, tr2);
loader.relationsOut.put(tr1, rel);
loader.relationsIn.put(tr2, rel);
} else if ("scv_tr_stream".equals(tokens[0])) {
Matcher matcher = scv_tr_stream.matcher(curLine); Matcher matcher = scv_tr_stream.matcher(curLine);
if (matcher.matches()) { if (matcher.matches()) {
Long id = Long.parseLong(matcher.group(1)); Long id = Long.parseLong(matcher.group(1));
TxStream stream = new TxStream(loader, id, matcher.group(2), matcher.group(3)); TxStream stream = new TxStream(loader, id, matcher.group(2), matcher.group(3));
add(id, stream); add(id, stream);
} }
} else if ("scv_tr_generator".equals(tokens[0])) { } else if (curLine.length()>16 && "scv_tr_generator".equals(curLine.substring(0, 16))) {
Matcher matcher = scv_tr_generator.matcher(curLine); Matcher matcher = scv_tr_generator.matcher(curLine);
if ((matcher.matches())) { if ((matcher.matches())) {
Long id = Long.parseLong(matcher.group(1)); Long id = Long.parseLong(matcher.group(1));
@ -440,23 +466,23 @@ public class TextDbLoader implements IWaveformDbLoader {
generator = new TxGenerator(loader, id, matcher.group(2), stream); generator = new TxGenerator(loader, id, matcher.group(2), stream);
add(id, generator); add(id, generator);
} }
} else if ("begin_attribute".equals(tokens[0])) { } else if (curLine.length()>15 && "begin_attribute".equals(curLine.substring(0, 15))) {
Matcher matcher = begin_attribute.matcher(curLine); Matcher matcher = begin_attribute.matcher(curLine);
if ((matcher.matches())) { if ((matcher.matches())) {
TxAttributeType attrType = getAttrType(matcher.group(2), DataType.valueOf(matcher.group(3)), TxAttributeType attrType = getAttrType(matcher.group(2), DataType.valueOf(matcher.group(3)),
AssociationType.BEGIN); AssociationType.BEGIN);
generator.beginAttrs.add(attrType); generator.beginAttrs.add(attrType);
} }
} else if ("end_attribute".equals(tokens[0])) { } else if (curLine.length()>13 && "end_attribute".equals(curLine.substring(0, 13))) {
Matcher matcher = end_attribute.matcher(curLine); Matcher matcher = end_attribute.matcher(curLine);
if ((matcher.matches())) { if ((matcher.matches())) {
TxAttributeType attrType = getAttrType(matcher.group(2), DataType.valueOf(matcher.group(3)), TxAttributeType attrType = getAttrType(matcher.group(2), DataType.valueOf(matcher.group(3)),
AssociationType.END); AssociationType.END);
generator.endAttrs.add(attrType); generator.endAttrs.add(attrType);
} }
} else if (")".equals(tokens[0])) { } else if (curLine.charAt(0) == ')') {
generator = null; generator = null;
} else } else if(!last)
throw new InputFormatException("Don't know what to do with: '" + curLine + "'"); throw new InputFormatException("Don't know what to do with: '" + curLine + "'");
return nextLine; return nextLine;
} }
@ -521,38 +547,4 @@ public class TextDbLoader implements IWaveformDbLoader {
} }
/**
* Gets the transaction.
*
* @param txId the tx id
* @return the transaction
*/
public ITx getTransaction(long txId) {
if (txCache.containsKey(txId))
return txCache.get(txId);
Tx tx = new Tx(this, txId);
txCache.put(txId, tx);
return tx;
}
/**
* Adds the property change listener.
*
* @param l the l
*/
@Override
public void addPropertyChangeListener(PropertyChangeListener l) {
pcs.addPropertyChangeListener(l);
}
/**
* Removes the property change listener.
*
* @param l the l
*/
@Override
public void removePropertyChangeListener(PropertyChangeListener l) {
pcs.removePropertyChangeListener(l);
}
} }

View File

@ -0,0 +1,77 @@
/*******************************************************************************
* Copyright (c) 2012 IT Just working.
* Copyright (c) 2020 MINRES Technologies GmbH
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IT Just working - initial API and implementation
*******************************************************************************/
package com.minres.scviewer.database.text;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;
import org.apache.commons.compress.compressors.lz4.FramedLZ4CompressorInputStream;
import com.minres.scviewer.database.IWaveformDbLoader;
import com.minres.scviewer.database.IWaveformDbLoaderFactory;
import com.minres.scviewer.database.text.TextDbLoader.FileType;
/**
* The Class TextDbLoader.
*/
public class TextDbLoaderFactory implements IWaveformDbLoaderFactory {
/** The Constant x. */
static final byte[] x = "scv_tr_stream".getBytes();
/**
* Checks if f is gzipped.
*
* @param f the f
* @return true, if is gzipped
*/
private static boolean isGzipped(File f) {
try (InputStream is = new FileInputStream(f)) {
byte[] signature = new byte[2];
int nread = is.read(signature); // read the gzip signature
return nread == 2 && signature[0] == (byte) 0x1f && signature[1] == (byte) 0x8b;
} catch (IOException e) {
return false;
}
}
/**
* Can load.
*
* @param inputFile the input file
* @return true, if successful
*/
@Override
public boolean canLoad(File inputFile) {
FileType fType = TextDbLoader.getFileType(inputFile);
try (InputStream is = new FileInputStream(inputFile)) {
InputStream plainIs = fType==FileType.GZIP ? new GZIPInputStream(is) : fType==FileType.LZ4? new FramedLZ4CompressorInputStream(is) : is;
byte[] buffer = new byte[x.length];
int readCnt = plainIs.read(buffer, 0, x.length);
if (readCnt == x.length) {
for (int i = 0; i < x.length; i++)
if (buffer[i] != x[i]) return false;
}
return true;
} catch (IOException e) {}
return false;
}
@Override
public IWaveformDbLoader getLoader() {
return new TextDbLoader();
}
}

View File

@ -19,7 +19,6 @@ import java.util.stream.Collectors;
import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.tx.ITx; import com.minres.scviewer.database.tx.ITx;
import com.minres.scviewer.database.tx.ITxAttribute; import com.minres.scviewer.database.tx.ITxAttribute;
import com.minres.scviewer.database.tx.ITxGenerator;
import com.minres.scviewer.database.tx.ITxRelation; import com.minres.scviewer.database.tx.ITxRelation;
/** /**
@ -29,9 +28,15 @@ class Tx implements ITx {
/** The loader. */ /** The loader. */
private final TextDbLoader loader; private final TextDbLoader loader;
private ScvTx scvTx =null;
/** The id. */ /** The id. */
private long id; private final long id;
private final long generatorId;
private final long streamId;
/** The begin time. */ /** The begin time. */
long beginTime = -1; long beginTime = -1;
@ -39,9 +44,6 @@ class Tx implements ITx {
/** The end time. */ /** The end time. */
long endTime = -1; long endTime = -1;
/** The concurrency index. */
private int concurrencyIndex;
/** /**
* Instantiates a new tx. * Instantiates a new tx.
* *
@ -51,6 +53,10 @@ class Tx implements ITx {
public Tx(TextDbLoader loader, ScvTx scvTx) { public Tx(TextDbLoader loader, ScvTx scvTx) {
this.loader = loader; this.loader = loader;
id = scvTx.id; id = scvTx.id;
generatorId=scvTx.generatorId;
streamId=scvTx.streamId;
beginTime=scvTx.beginTime;
endTime=scvTx.endTime;
} }
/** /**
@ -59,9 +65,11 @@ class Tx implements ITx {
* @param loader the loader * @param loader the loader
* @param txId the tx id * @param txId the tx id
*/ */
public Tx(TextDbLoader loader, long txId) { public Tx(TextDbLoader loader, long id, long generatorId, long streamId) {
this.loader = loader; this.loader = loader;
id = txId; this.id = id;
this.generatorId=generatorId;
this.streamId = streamId;
} }
/** /**
@ -94,11 +102,11 @@ class Tx implements ITx {
*/ */
@Override @Override
public int compareTo(ITx o) { public int compareTo(ITx o) {
int res = getBeginTime().compareTo(o.getBeginTime()); int res = Long.compare(getBeginTime(), o.getBeginTime());
if (res != 0) if (res != 0)
return res; return res;
else else
return getId().compareTo(o.getId()); return Long.compare(getId(), o.getId());
} }
/** /**
@ -113,7 +121,7 @@ class Tx implements ITx {
return true; return true;
if (obj == null || getClass() != obj.getClass()) if (obj == null || getClass() != obj.getClass())
return false; return false;
return this.loader.getScvTx(id).equals(((Tx) obj).loader.getScvTx(id)); return this.getScvTx().equals(((Tx) obj).getScvTx());
} }
/** /**
@ -123,7 +131,7 @@ class Tx implements ITx {
*/ */
@Override @Override
public int hashCode() { public int hashCode() {
return loader.getScvTx(id).hashCode(); return getScvTx().hashCode();
} }
/** /**
@ -142,8 +150,8 @@ class Tx implements ITx {
* @return the id * @return the id
*/ */
@Override @Override
public Long getId() { public long getId() {
return loader.getScvTx(id).id; return getScvTx().id;
} }
/** /**
@ -153,7 +161,7 @@ class Tx implements ITx {
*/ */
@Override @Override
public IWaveform getStream() { public IWaveform getStream() {
return loader.txStreams.get(loader.getScvTx(id).streamId); return loader.txStreams.get(streamId);
} }
/** /**
@ -162,8 +170,8 @@ class Tx implements ITx {
* @return the generator * @return the generator
*/ */
@Override @Override
public ITxGenerator getGenerator() { public IWaveform getGenerator() {
return loader.txGenerators.get(loader.getScvTx(id).generatorId); return loader.txGenerators.get(generatorId);
} }
/** /**
@ -172,9 +180,12 @@ class Tx implements ITx {
* @return the begin time * @return the begin time
*/ */
@Override @Override
public Long getBeginTime() { public long getBeginTime() {
if (beginTime < 0) if (beginTime < 0) {
beginTime = loader.getScvTx(id).beginTime; ScvTx tx = scvTx==null?loader.getScvTx(id):getScvTx();
beginTime = tx.beginTime;
endTime = tx.endTime;
}
return beginTime; return beginTime;
} }
@ -184,9 +195,12 @@ class Tx implements ITx {
* @return the end time * @return the end time
*/ */
@Override @Override
public Long getEndTime() { public long getEndTime() {
if (endTime < 0) if (endTime < 0) {
endTime = loader.getScvTx(id).endTime; ScvTx tx = scvTx==null?loader.getScvTx(id):getScvTx();
beginTime = tx.beginTime;
endTime = tx.endTime;
}
return endTime; return endTime;
} }
@ -196,26 +210,7 @@ class Tx implements ITx {
* @param time the new end time * @param time the new end time
*/ */
void setEndTime(Long time) { void setEndTime(Long time) {
loader.getScvTx(id).endTime = time; getScvTx().endTime = time;
}
/**
* Gets the concurrency index.
*
* @return the concurrency index
*/
@Override
public int getConcurrencyIndex() {
return concurrencyIndex;
}
/**
* Sets the concurrency index.
*
* @param idx the new concurrency index
*/
void setConcurrencyIndex(int idx) {
concurrencyIndex = idx;
} }
/** /**
@ -225,7 +220,12 @@ class Tx implements ITx {
*/ */
@Override @Override
public List<ITxAttribute> getAttributes() { public List<ITxAttribute> getAttributes() {
return loader.getScvTx(id).attributes; return getScvTx().attributes;
} }
private ScvTx getScvTx() {
if(scvTx==null)
scvTx=loader.getScvTx(id);
return scvTx;
}
} }

View File

@ -32,6 +32,7 @@ class TxEvent implements ITxEvent {
/** The time. */ /** The time. */
final long time; final long time;
private int concurrencyIdx=-1;
/** /**
* Instantiates a new tx event. * Instantiates a new tx event.
* *
@ -94,7 +95,7 @@ class TxEvent implements ITxEvent {
* @return the time * @return the time
*/ */
@Override @Override
public Long getTime() { public long getTime() {
return time; return time;
} }
@ -107,4 +108,13 @@ class TxEvent implements ITxEvent {
public ITx getTransaction() { public ITx getTransaction() {
return loader.getTransaction(transaction); return loader.getTransaction(transaction);
} }
@Override
public int getRowIndex() {
return concurrencyIdx;
}
public void setConcurrencyIndex(int idx) {
concurrencyIdx=idx;
}
} }

View File

@ -15,12 +15,11 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.tx.ITxGenerator;
/** /**
* The Class TxGenerator. * The Class TxGenerator.
*/ */
class TxGenerator extends AbstractTxStream implements ITxGenerator { class TxGenerator extends AbstractTxStream {
/** The stream. */ /** The stream. */
TxStream stream; TxStream stream;
@ -45,16 +44,6 @@ class TxGenerator extends AbstractTxStream implements ITxGenerator {
stream.addChild(this); stream.addChild(this);
} }
/**
* Gets the stream.
*
* @return the stream
*/
@Override
public IWaveform getStream() {
return stream;
}
/** /**
* Checks if is same. * Checks if is same.
* *
@ -63,7 +52,7 @@ class TxGenerator extends AbstractTxStream implements ITxGenerator {
*/ */
@Override @Override
public boolean isSame(IWaveform other) { public boolean isSame(IWaveform other) {
return (other instanceof TxGenerator && this.getId().equals(other.getId())); return (other instanceof TxGenerator && this.getId()==other.getId());
} }
/** /**
@ -93,14 +82,15 @@ class TxGenerator extends AbstractTxStream implements ITxGenerator {
public String getKind() { public String getKind() {
return stream.getKind(); return stream.getKind();
} }
/** /**
* Gets the width. * Gets the full hierarchical name.
* *
* @return the width * @return the full name
*/ */
@Override @Override
public int getWidth() { public String getFullName() {
return stream.getWidth(); return ((AbstractTxStream)parent).getFullName()+"."+name;
} }
} }

View File

@ -42,7 +42,7 @@ class TxStream extends AbstractTxStream {
*/ */
@Override @Override
public boolean isSame(IWaveform other) { public boolean isSame(IWaveform other) {
return (other instanceof TxStream && this.getId().equals(other.getId())); return (other instanceof TxStream && this.getId() == other.getId());
} }
/** /**
@ -55,40 +55,4 @@ class TxStream extends AbstractTxStream {
return kind; return kind;
} }
/** The max concurrency. */
private int maxConcurrency = 0;
/** The concurrency. */
private int concurrency = 0;
/**
* Sets the concurrency.
*
* @param concurrency the new concurrency
*/
void setConcurrency(int concurrency) {
this.concurrency = concurrency;
if (concurrency > maxConcurrency)
maxConcurrency = concurrency;
}
/**
* Gets the concurrency.
*
* @return the concurrency
*/
int getConcurrency() {
return this.concurrency;
}
/**
* Gets the width.
*
* @return the width
*/
@Override
public int getWidth() {
return maxConcurrency;
}
} }

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<classpath> <classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/> <classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="target/classes"/> <classpathentry kind="output" path="target/classes"/>

View File

@ -9,8 +9,8 @@ org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nul
org.eclipse.jdt.core.compiler.annotation.nullable.secondary= org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
org.eclipse.jdt.core.compiler.compliance=1.8 org.eclipse.jdt.core.compiler.compliance=11
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
@ -21,6 +21,7 @@ org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
@ -66,6 +67,7 @@ org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=igno
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
@ -98,5 +100,5 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.compiler.source=11

View File

@ -2,9 +2,9 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2 Bundle-ManifestVersion: 2
Bundle-Name: SWT database widget Bundle-Name: SWT database widget
Bundle-SymbolicName: com.minres.scviewer.database.ui.swt Bundle-SymbolicName: com.minres.scviewer.database.ui.swt
Bundle-Version: 3.0.0.qualifier Bundle-Version: 4.0.0.qualifier
Bundle-Vendor: MINRES Technologies GmbH Bundle-Vendor: MINRES Technologies GmbH
Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-RequiredExecutionEnvironment: JavaSE-11
Require-Bundle: org.eclipse.swt;bundle-version="3.103.1", Require-Bundle: org.eclipse.swt;bundle-version="3.103.1",
com.minres.scviewer.database;bundle-version="1.0.0", com.minres.scviewer.database;bundle-version="1.0.0",
com.google.guava;bundle-version="15.0.0", com.google.guava;bundle-version="15.0.0",

View File

@ -5,8 +5,8 @@
<parent> <parent>
<groupId>com.minres.scviewer</groupId> <groupId>com.minres.scviewer</groupId>
<artifactId>com.minres.scviewer.parent</artifactId> <artifactId>com.minres.scviewer.parent</artifactId>
<version>2.11.2-SNAPSHOT</version> <version>2.16.1</version>
<relativePath>../..</relativePath> <relativePath>../..</relativePath>
</parent> </parent>
<version>3.0.0-SNAPSHOT</version> <version>4.0.0-SNAPSHOT</version>
</project> </project>

View File

@ -27,10 +27,14 @@ import com.minres.scviewer.database.tx.ITx;
public interface IWaveformView extends PropertyChangeListener, ISelectionProvider{ public interface IWaveformView extends PropertyChangeListener, ISelectionProvider{
String CURSOR_PROPERTY = "cursor_time"; static final String CURSOR_PROPERTY = "cursor_time";
String MARKER_PROPERTY = "marker_time"; static final String MARKER_PROPERTY = "marker_time";
static final int CURSOR_POS = 0;
static final int MARKER_POS = 1;
public static final RelationType NEXT_PREV_IN_STREAM = RelationTypeFactory.create("Prev/Next in stream"); public static final RelationType NEXT_PREV_IN_STREAM = RelationTypeFactory.create("Prev/Next in stream");
public void addSelectionChangedListener(ISelectionChangedListener listener); public void addSelectionChangedListener(ISelectionChangedListener listener);
@ -75,23 +79,17 @@ public interface IWaveformView extends PropertyChangeListener, ISelectionProvide
public void setHighliteRelation(RelationType relationType); public void setHighliteRelation(RelationType relationType);
public long getMaxTime();
public void setMaxTime(long maxTime); public void setMaxTime(long maxTime);
public void setZoomLevel(int scale);
public int getZoomLevel();
public void setCursorTime(long time); public void setCursorTime(long time);
public void setMarkerTime(long time, int index); public void setMarkerTime(int marker, long time);
public long getCursorTime(); public long getCursorTime();
public int getSelectedMarkerId(); public int getSelectedMarker();
public long getMarkerTime(int index); public long getMarkerTime(int marker);
public void addPropertyChangeListener(PropertyChangeListener listener); public void addPropertyChangeListener(PropertyChangeListener listener);
@ -101,21 +99,18 @@ public interface IWaveformView extends PropertyChangeListener, ISelectionProvide
public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener); public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener);
public String getScaledTime(long time);
public String[] getZoomLevels();
public List<ICursor> getCursorList(); public List<ICursor> getCursorList();
public long getBaselineTime();
public void setBaselineTime(Long scale);
public void scrollHorizontal(int percent); public void scrollHorizontal(int percent);
public void scrollTo(int pos);
public void addDisposeListener( DisposeListener listener ); public void addDisposeListener( DisposeListener listener );
public void deleteSelectedTracks(); public void deleteSelectedTracks();
public TrackEntry addWaveform(IWaveform waveform, int pos); public TrackEntry addWaveform(IWaveform waveform, int pos);
public IWaveformZoom getWaveformZoom();
} }

View File

@ -0,0 +1,24 @@
package com.minres.scviewer.database.ui;
public interface IWaveformZoom {
long getMaxVisibleTime();
long getMinVisibleTime();
void setMinVisibleTime(long scale);
long getMaxTime();
long getScale();
void setScale(long factor);
void setVisibleRange(long startTime, long endTime);
void centerAt(long time);
void zoom(ZoomKind kind);
String timeToString(long time);
}

View File

@ -0,0 +1,3 @@
package com.minres.scviewer.database.ui;
public enum ZoomKind {IN, OUT, FIT, FULL}

View File

@ -1,14 +1,49 @@
package com.minres.scviewer.database.ui.swt; package com.minres.scviewer.database.ui.swt;
import java.text.DecimalFormat;
public class Constants { public class Constants {
public static final String[] UNIT_STRING={"fs", "ps", "ns", "us", "ms"};//, "s"}; public static final String[] UNIT_STRING={"fs", "ps", "ns", "us", "ms", "s"};
public static final long[] UNIT_MULTIPLIER={1l, 1000l, 1000l*1000, 1000l*1000*1000, 1000l*1000*1000*1000, 1000l*1000*1000*1000*1000 };
public static final int[] UNIT_MULTIPLIER={1, 3, 10, 30, 100, 300};
//public static final int[] UNIT_MULTIPLIER={1, 3, 10, 30, 100, 300};
public static final long[] SCALE_MULTIPLIER={1, 2, 5, 10, 20, 50, 100, 200, 500};
public static final String CONTENT_PROVIDER_TAG = "TOOLTIP_CONTENT_PROVIDER"; public static final String CONTENT_PROVIDER_TAG = "TOOLTIP_CONTENT_PROVIDER";
public static final String HELP_PROVIDER_TAG = "TOOLTIP_HELP_PROVIDER"; public static final String HELP_PROVIDER_TAG = "TOOLTIP_HELP_PROVIDER";
public static final DecimalFormat TIME_FORMAT_FS = new DecimalFormat("#");
public static final DecimalFormat TIME_FORMAT_PS = new DecimalFormat("#");
public static final DecimalFormat TIME_FORMAT_NS = new DecimalFormat("#.0##");
public static final DecimalFormat TIME_FORMAT_UMS = new DecimalFormat("#.0#####");
public static final long[] POWERS_OF_TEN = {
1L,
10L,
100L,
1_000L,
10_000L,
100_000L,
1_000_000L,
10_000_000L,
100_000_000L,
1_000_000_000L,
10_000_000_000L,
100_000_000_000L,
1_000_000_000_000L,
10_000_000_000_000L,
100_000_000_000_000L,
1_000_000_000_000_000L};
public static DecimalFormat getTimeFormatForLevel(int idx) {
switch(idx) {
case 0: return TIME_FORMAT_FS;
case 1: return TIME_FORMAT_PS;
case 2: return TIME_FORMAT_NS;
default:
return TIME_FORMAT_UMS;
}
}
private Constants() {} private Constants() {}
} }

View File

@ -13,6 +13,7 @@ package com.minres.scviewer.database.ui.swt;
import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Plugin; import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.Status;
import org.eclipse.wb.swt.SWTResourceManager;
import org.osgi.framework.BundleContext; import org.osgi.framework.BundleContext;
public class DatabaseUiPlugin extends Plugin { public class DatabaseUiPlugin extends Plugin {
@ -24,6 +25,7 @@ public class DatabaseUiPlugin extends Plugin {
@Override @Override
public void stop(BundleContext context) throws Exception { public void stop(BundleContext context) throws Exception {
SWTResourceManager.dispose();
getLog().log(new Status(IStatus.OK, "org.eclipse.e4.core", "Stopping org.eclipse.e4.core bundle...")); getLog().log(new Status(IStatus.OK, "org.eclipse.e4.core", "Stopping org.eclipse.e4.core bundle..."));
} }
} }

View File

@ -10,9 +10,11 @@
*******************************************************************************/ *******************************************************************************/
package com.minres.scviewer.database.ui.swt.internal; package com.minres.scviewer.database.ui.swt.internal;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Optional;
import org.eclipse.swt.SWT; import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Color;
@ -21,8 +23,11 @@ import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Display;
import com.minres.scviewer.database.IEvent;
import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.RelationType; import com.minres.scviewer.database.RelationType;
import com.minres.scviewer.database.tx.ITx; import com.minres.scviewer.database.tx.ITx;
import com.minres.scviewer.database.tx.ITxEvent;
import com.minres.scviewer.database.tx.ITxRelation; import com.minres.scviewer.database.tx.ITxRelation;
import com.minres.scviewer.database.ui.WaveformColors; import com.minres.scviewer.database.ui.WaveformColors;
@ -32,7 +37,7 @@ public class ArrowPainter implements IPainter {
private int yCtrlOffset = 30; private int yCtrlOffset = 30;
private WaveformCanvas waveCanvas; private final WaveformCanvas waveCanvas;
private ITx tx; private ITx tx;
@ -48,8 +53,6 @@ public class ArrowPainter implements IPainter {
long scaleFactor; long scaleFactor;
boolean deferUpdate;
public ArrowPainter(WaveformCanvas waveCanvas, RelationType relationType) { public ArrowPainter(WaveformCanvas waveCanvas, RelationType relationType) {
this.waveCanvas = waveCanvas; this.waveCanvas = waveCanvas;
highlightType=relationType; highlightType=relationType;
@ -72,42 +75,53 @@ public class ArrowPainter implements IPainter {
this.tx = newTx; this.tx = newTx;
iRect = new LinkedList<>(); iRect = new LinkedList<>();
oRect = new LinkedList<>(); oRect = new LinkedList<>();
scaleFactor = waveCanvas.getScaleFactor(); scaleFactor = waveCanvas.getScale();
if (tx != null) { if (tx != null) {
calculateGeometries(); calculateGeometries();
} }
} }
protected void calculateGeometries() { private int getConcurrencyIndex(ITx tx) {
deferUpdate = false; IEvent[] eventList = tx.getStream().getEventsBeforeTime(tx.getBeginTime());
Optional<Integer> res = Arrays.stream(eventList).map(e -> ((ITxEvent)e).getRowIndex()).findFirst();
return res.isPresent()? res.get():0;
}
protected boolean calculateGeometries() {
iRect.clear(); iRect.clear();
oRect.clear(); oRect.clear();
IWaveformPainter painter = waveCanvas.wave2painterMap.get(tx.getStream()); IWaveformPainter painter = waveCanvas.wave2painterMap.get(tx.getStream());
if(painter == null)
painter = waveCanvas.wave2painterMap.get(tx.getGenerator());
if (painter == null) { // stream has been added but painter not yet if (painter == null) { // stream has been added but painter not yet
// created // created
deferUpdate = true; return true;
return;
} }
int laneHeight = painter.getHeight() / tx.getStream().getWidth(); int laneHeight = painter.getHeight() / tx.getStream().getRowCount();
txRectangle = new Rectangle((int) (tx.getBeginTime() / scaleFactor), txRectangle = new Rectangle((int) (tx.getBeginTime() / scaleFactor),
waveCanvas.rulerHeight + painter.getVerticalOffset() + laneHeight * tx.getConcurrencyIndex(), waveCanvas.rulerHeight + painter.getVerticalOffset() + laneHeight * getConcurrencyIndex(tx),
(int) ((tx.getEndTime() - tx.getBeginTime()) / scaleFactor), laneHeight); (int) ((tx.getEndTime() - tx.getBeginTime()) / scaleFactor), laneHeight);
deriveGeom(tx.getIncomingRelations(), iRect, false); deriveGeom(tx.getIncomingRelations(), iRect, false);
deriveGeom(tx.getOutgoingRelations(), oRect, true); deriveGeom(tx.getOutgoingRelations(), oRect, true);
return false;
} }
protected void deriveGeom(Collection<ITxRelation> relations, List<LinkEntry> res, boolean useTarget) { protected void deriveGeom(Collection<ITxRelation> relations, List<LinkEntry> res, boolean useTarget) {
for (ITxRelation iTxRelation : relations) { for (ITxRelation iTxRelation : relations) {
ITx otherTx = useTarget ? iTxRelation.getTarget() : iTxRelation.getSource(); ITx otherTx = useTarget ? iTxRelation.getTarget() : iTxRelation.getSource();
if (waveCanvas.wave2painterMap.containsKey(otherTx.getStream())) { for(IWaveform iWaveform: new IWaveform[]{otherTx.getStream(), otherTx.getGenerator()}) {
IWaveformPainter painter = waveCanvas.wave2painterMap.get(otherTx.getStream()); if (waveCanvas.wave2painterMap.containsKey(iWaveform)) {
int height = waveCanvas.styleProvider.getTrackHeight(); IWaveformPainter painter = waveCanvas.wave2painterMap.get(iWaveform);
Rectangle bb = new Rectangle( if(painter!=null) {
(int) (otherTx.getBeginTime() / scaleFactor), int height = waveCanvas.styleProvider.getTrackHeight();
waveCanvas.rulerHeight + painter.getVerticalOffset() + height * otherTx.getConcurrencyIndex(), Rectangle bb = new Rectangle(
(int) ((otherTx.getEndTime() - otherTx.getBeginTime()) / scaleFactor), (int) (otherTx.getBeginTime() / scaleFactor),
height); waveCanvas.rulerHeight + painter.getVerticalOffset() + height * getConcurrencyIndex(otherTx),
res.add(new LinkEntry(bb, iTxRelation.getRelationType())); (int) ((otherTx.getEndTime() - otherTx.getBeginTime()) / scaleFactor),
height);
res.add(new LinkEntry(bb, iTxRelation.getRelationType()));
}
}
} }
} }
} }
@ -119,11 +133,9 @@ public class ArrowPainter implements IPainter {
Color highliteColor = waveCanvas.styleProvider.getColor(WaveformColors.REL_ARROW_HIGHLITE); Color highliteColor = waveCanvas.styleProvider.getColor(WaveformColors.REL_ARROW_HIGHLITE);
if(tx==null) return; if(tx==null) return;
if (!deferUpdate) { scaleFactor = waveCanvas.getScale();
scaleFactor = waveCanvas.getScaleFactor(); if(calculateGeometries())
calculateGeometries(); return;
}
if(deferUpdate) return;
int correctionValue = (int)(selectionOffset); int correctionValue = (int)(selectionOffset);
Rectangle correctedTargetRectangle = new Rectangle(txRectangle.x+correctionValue, txRectangle.y, txRectangle.width, txRectangle.height); Rectangle correctedTargetRectangle = new Rectangle(txRectangle.x+correctionValue, txRectangle.y, txRectangle.width, txRectangle.height);
for (LinkEntry entry : iRect) { for (LinkEntry entry : iRect) {

View File

@ -65,7 +65,7 @@ public class CursorPainter implements IPainter, ICursor {
Rectangle area = proj.unProject(clientRect); Rectangle area = proj.unProject(clientRect);
if(!waveCanvas.painterList.isEmpty()){ if(!waveCanvas.painterList.isEmpty()){
long scaleFactor=waveCanvas.getScaleFactor(); long scaleFactor=waveCanvas.getScale();
long beginPos = area.x; long beginPos = area.x;
maxPosX = area.x + area.width; maxPosX = area.x + area.width;
@ -83,8 +83,7 @@ public class CursorPainter implements IPainter, ICursor {
proj.drawLine(x, top, x, area.y+area.height); proj.drawLine(x, top, x, area.y+area.height);
proj.setBackground(drawColor); proj.setBackground(drawColor);
proj.setForeground(textColor); proj.setForeground(textColor);
double dTime=time; proj.drawText(waveCanvas.timeToString(time), x+1, top);
proj.drawText((dTime/waveCanvas.getScaleFactorPow10())+waveCanvas.getUnitStr(), x+1, top);
} }
} }
} }

View File

@ -10,22 +10,21 @@
*******************************************************************************/ *******************************************************************************/
package com.minres.scviewer.database.ui.swt.internal; package com.minres.scviewer.database.ui.swt.internal;
import java.text.DecimalFormat;
import org.eclipse.swt.SWT; import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.wb.swt.SWTResourceManager; import org.eclipse.wb.swt.SWTResourceManager;
import com.minres.scviewer.database.ui.swt.Constants;
public class RulerPainter implements IPainter { public class RulerPainter implements IPainter {
protected WaveformCanvas waveCanvas; protected final WaveformCanvas waveCanvas;
static final int RULER_TICK_MINOR = 10; static final int RULER_TICK_MINOR = 10;
static final int RULER_TICK_MAJOR = 100; static final int RULER_TICK_MAJOR = 100;
static final DecimalFormat df = new DecimalFormat("#.00####");
public RulerPainter(WaveformCanvas waveCanvas) { public RulerPainter(WaveformCanvas waveCanvas) {
this.waveCanvas=waveCanvas; this.waveCanvas=waveCanvas;
} }
@ -39,26 +38,26 @@ public class RulerPainter implements IPainter {
Color headerBgColor = waveCanvas.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND); Color headerBgColor = waveCanvas.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
if(headerBgColor.isDisposed()) if(headerBgColor.isDisposed())
headerBgColor=SWTResourceManager.getColor(255,255,255); headerBgColor=SWTResourceManager.getColor(255,255,255);
String unit=waveCanvas.getUnitStr();
int unitMultiplier=waveCanvas.getUnitMultiplier(); long scaleFactor=waveCanvas.getScale();
long scaleFactor=waveCanvas.getScaleFactor(); long startTime=waveCanvas.getMinVisibleTime();
long endTime=waveCanvas.getMaxVisibleTime();
long startPos=area.x*scaleFactor;
long startVal=startPos - proj.getTranslation().x*scaleFactor;
long endPos=startPos+area.width*scaleFactor;
long rulerTickMinor = RULER_TICK_MINOR*scaleFactor;
long rulerTickMajor = RULER_TICK_MAJOR*scaleFactor;
long multiplier = Constants.POWERS_OF_TEN[waveCanvas.getScaleMagnitude()];
long rulerTickMinor = RULER_TICK_MINOR*multiplier;
long rulerTickMajor = RULER_TICK_MAJOR*multiplier;
if((endTime-startTime)/rulerTickMinor>area.width/5) {
rulerTickMinor*=10;
rulerTickMajor*=10;
}
int minorTickY = waveCanvas.rulerHeight-5; int minorTickY = waveCanvas.rulerHeight-5;
int majorTickY = waveCanvas.rulerHeight-15; int majorTickY = waveCanvas.rulerHeight-15;
int textY=waveCanvas.rulerHeight-20; int textY=waveCanvas.rulerHeight-30;
int baselineY=waveCanvas.rulerHeight - 1; int baselineY=waveCanvas.rulerHeight - 1;
int bottom=waveCanvas.rulerHeight - 2; int bottom=waveCanvas.rulerHeight - 2;
long modulo = startVal % rulerTickMinor; long startTickTime = startTime+rulerTickMinor-(startTime % rulerTickMinor);
long startMinorIncrPos = startPos+rulerTickMinor-modulo; long majorTickDist = rulerTickMajor/scaleFactor;
long startMinorIncrVal = startVal+rulerTickMinor-modulo;
gc.setBackground(waveCanvas.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); gc.setBackground(waveCanvas.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
gc.fillRectangle(new Rectangle(area.x, area.y, area.width, waveCanvas.rulerHeight)); gc.fillRectangle(new Rectangle(area.x, area.y, area.width, waveCanvas.rulerHeight));
@ -66,13 +65,22 @@ public class RulerPainter implements IPainter {
gc.fillRectangle(new Rectangle(area.x, area.y, area.width, baselineY)); gc.fillRectangle(new Rectangle(area.x, area.y, area.width, baselineY));
gc.setForeground(headerFgColor); gc.setForeground(headerFgColor);
gc.drawLine(area.x, area.y+bottom, area.x+area.width, area.y+bottom); gc.drawLine(area.x, area.y+bottom, area.x+area.width, area.y+bottom);
int maxTextLength=0;
for (long pos = startMinorIncrPos, tick = startMinorIncrVal; pos < endPos; pos+= rulerTickMinor, tick += rulerTickMinor) { for (long tickTime = startTickTime; tickTime < endTime; tickTime+= rulerTickMinor) {
int x0Pos = (int) (pos/scaleFactor); if ((tickTime % rulerTickMajor) == 0) {
long x0Val = tick/scaleFactor; Point textSize = gc.textExtent(waveCanvas.timeToString(tickTime));
if ((tick % rulerTickMajor) == 0) { maxTextLength=textSize.x>maxTextLength?textSize.x:maxTextLength;
gc.drawText(df.format(x0Val*unitMultiplier)+unit, x0Pos, area.y+textY); }
}
boolean drawEvery = majorTickDist>maxTextLength;
boolean drawText=true;
for (long tickTime = startTickTime; tickTime < endTime; tickTime+= rulerTickMinor) {
int x0Pos = (int) (tickTime/scaleFactor) + proj.getTranslation().x;
if ((tickTime % rulerTickMajor) == 0) {
if(drawEvery || drawText)
gc.drawText(waveCanvas.timeToString(tickTime), x0Pos, area.y+textY);
gc.drawLine(x0Pos, area.y+majorTickY, x0Pos,area.y+ bottom); gc.drawLine(x0Pos, area.y+majorTickY, x0Pos,area.y+ bottom);
drawText=!drawText;
} else { } else {
gc.drawLine(x0Pos, area.y+minorTickY, x0Pos, area.y+bottom); gc.drawLine(x0Pos, area.y+minorTickY, x0Pos, area.y+bottom);
} }

View File

@ -12,8 +12,6 @@ package com.minres.scviewer.database.ui.swt.internal;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Map.Entry;
import java.util.NavigableMap;
import javax.swing.JPanel; import javax.swing.JPanel;
@ -26,7 +24,9 @@ import org.eclipse.swt.graphics.Rectangle;
import com.minres.scviewer.database.BitVector; import com.minres.scviewer.database.BitVector;
import com.minres.scviewer.database.DoubleVal; import com.minres.scviewer.database.DoubleVal;
import com.minres.scviewer.database.EventEntry;
import com.minres.scviewer.database.IEvent; import com.minres.scviewer.database.IEvent;
import com.minres.scviewer.database.IEventList;
import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.ui.TrackEntry; import com.minres.scviewer.database.ui.TrackEntry;
import com.minres.scviewer.database.ui.WaveformColors; import com.minres.scviewer.database.ui.WaveformColors;
@ -37,16 +37,16 @@ public class SignalPainter extends TrackPainter {
IEvent value; IEvent value;
boolean fromMap; boolean fromMap;
public SignalChange(Entry<Long, IEvent[]> entry) { public SignalChange(EventEntry entry) {
time = entry.getKey(); time = entry.timestamp;
value = entry.getValue()[0]; value = entry.events[0];
fromMap = true; fromMap = true;
} }
public void set(Entry<Long, IEvent[]> entry, Long actTime) { public void set(EventEntry entry, Long actTime) {
if (entry != null) { if (entry != null) {
time = entry.getKey(); time = entry.timestamp;
value = entry.getValue()[0]; value = entry.events[0];
fromMap = true; fromMap = true;
} else { } else {
time = actTime; time = actTime;
@ -82,7 +82,7 @@ public class SignalPainter extends TrackPainter {
} }
private int getXPosEnd(long time) { private int getXPosEnd(long time) {
long ltmp = time / this.waveCanvas.getScaleFactor(); long ltmp = time / this.waveCanvas.getScale();
return ltmp > maxPosX ? maxPosX : (int) ltmp; return ltmp > maxPosX ? maxPosX : (int) ltmp;
} }
@ -95,31 +95,26 @@ public class SignalPainter extends TrackPainter {
proj.setFillRule(SWT.FILL_EVEN_ODD); proj.setFillRule(SWT.FILL_EVEN_ODD);
proj.fillRectangle(area); proj.fillRectangle(area);
long scaleFactor = this.waveCanvas.getScaleFactor(); long scaleFactor = this.waveCanvas.getScale();
long beginPos = area.x; long beginPos = area.x;
long beginTime = beginPos*scaleFactor; long beginTime = beginPos*scaleFactor;
long endTime = beginTime + area.width*scaleFactor; long endTime = beginTime + area.width*scaleFactor;
Entry<Long, IEvent[]> first = signal.getEvents().floorEntry(beginTime); EventEntry first = signal.getEvents().floorEntry(beginTime);
Entry<Long, IEvent[]> last = signal.getEvents().floorEntry(endTime); if (first == null)
if (first == null) {
if (last == null)
return;
first = signal.getEvents().firstEntry(); first = signal.getEvents().firstEntry();
} else if (last == null) { beginTime = first.timestamp;
last = signal.getEvents().lastEntry();
}
proj.setForeground(this.waveCanvas.styleProvider.getColor(WaveformColors.LINE)); proj.setForeground(this.waveCanvas.styleProvider.getColor(WaveformColors.LINE));
proj.setLineStyle(SWT.LINE_SOLID); proj.setLineStyle(SWT.LINE_SOLID);
proj.setLineWidth(1); proj.setLineWidth(1);
NavigableMap<Long, IEvent[]> entries = signal.getEvents().subMap(first.getKey(), false, last.getKey(), true); IEventList entries = signal.getEvents().subMap(beginTime, true, endTime);
SignalChange left = new SignalChange(first); SignalChange left = new SignalChange(entries.firstEntry());
SignalChange right = new SignalChange(entries.size() > 0 ? entries.firstEntry() : first); SignalChange right = new SignalChange(entries.size() > 1 ? entries.higherEntry(left.time) : entries.firstEntry());
maxPosX = area.x + area.width; maxPosX = area.x + area.width;
yOffsetT = this.waveCanvas.styleProvider.getTrackHeight() / 5 + area.y; yOffsetT = this.waveCanvas.styleProvider.getTrackHeight() / 5 + area.y;
yOffsetM = this.waveCanvas.styleProvider.getTrackHeight() / 2 + area.y; yOffsetM = this.waveCanvas.styleProvider.getTrackHeight() / 2 + area.y;
yOffsetB = 4 * this.waveCanvas.styleProvider.getTrackHeight() / 5 + area.y; yOffsetB = 4 * this.waveCanvas.styleProvider.getTrackHeight() / 5 + area.y;
int xSigChangeBeginVal = Math.max(area.x, (int) (left.time / this.waveCanvas.getScaleFactor())); int xSigChangeBeginVal = Math.max(area.x, (int) (left.time / this.waveCanvas.getScale()));
int xSigChangeBeginPos = area.x; int xSigChangeBeginPos = area.x;
int xSigChangeEndPos = Math.max(area.x, getXPosEnd(right.time)); int xSigChangeEndPos = Math.max(area.x, getXPosEnd(right.time));
@ -132,7 +127,7 @@ public class SignalPainter extends TrackPainter {
right.time = endTime; right.time = endTime;
} else { } else {
multiple = true; multiple = true;
long eTime = (xSigChangeBeginVal + 1) * this.waveCanvas.getScaleFactor(); long eTime = (xSigChangeBeginVal + 1) * this.waveCanvas.getScale();
right.set(entries.floorEntry(eTime), endTime); right.set(entries.floorEntry(eTime), endTime);
right.time = eTime; right.time = eTime;
} }
@ -152,16 +147,16 @@ public class SignalPainter extends TrackPainter {
multiple = false; multiple = false;
if (xSigChangeEndPos == xSigChangeBeginPos) { if (xSigChangeEndPos == xSigChangeBeginPos) {
multiple = true; multiple = true;
long eTime = (xSigChangeBeginPos + 1) * this.waveCanvas.getScaleFactor(); long eTime = (xSigChangeBeginPos + 1) * this.waveCanvas.getScale();
Entry<Long, IEvent[]> entry = entries.floorEntry(eTime); EventEntry entry = entries.floorEntry(eTime);
if(entry!=null && entry.getKey()> right.time) if(entry!=null && entry.timestamp> right.time)
right.set(entry, endTime); right.set(entry, endTime);
xSigChangeEndPos = getXPosEnd(eTime); xSigChangeEndPos = getXPosEnd(eTime);
} }
} while (left.time < endTime); } while (left.time < endTime);
} }
private SignalStencil getStencil(GC gc, SignalChange left, NavigableMap<Long, IEvent[]> entries) { private SignalStencil getStencil(GC gc, SignalChange left, IEventList entries) {
IEvent val = left.value; IEvent val = left.value;
if(val instanceof BitVector) { if(val instanceof BitVector) {
BitVector bv = (BitVector) val; BitVector bv = (BitVector) val;
@ -253,15 +248,15 @@ public class SignalPainter extends TrackPainter {
private long maxVal; private long maxVal;
private long minVal; private long minVal;
double yRange = (yOffsetB-yOffsetT); double yRange = (yOffsetB-yOffsetT);
public MultiBitStencilAnalog(NavigableMap<Long, IEvent[]> entries, Object left, boolean continous, boolean signed) { public MultiBitStencilAnalog(IEventList entries, Object left, boolean continous, boolean signed) {
this.continous=continous; this.continous=continous;
this.signed=signed; this.signed=signed;
Collection<IEvent[]> values = entries.values(); Collection<EventEntry> ievents = entries.entrySet();
minVal=signed?((BitVector)left).toSignedValue():((BitVector)left).toUnsignedValue(); minVal=signed?((BitVector)left).toSignedValue():((BitVector)left).toUnsignedValue();
if(!values.isEmpty()) { if(!ievents.isEmpty()) {
maxVal=minVal; maxVal=minVal;
for (IEvent[] tp : entries.values()) for (EventEntry tp : ievents)
for(IEvent e: tp) { for(IEvent e: tp.events) {
long v = signed?((BitVector)e).toSignedValue():((BitVector)e).toUnsignedValue(); long v = signed?((BitVector)e).toSignedValue():((BitVector)e).toUnsignedValue();
maxVal=Math.max(maxVal, v); maxVal=Math.max(maxVal, v);
minVal=Math.min(minVal, v); minVal=Math.min(minVal, v);
@ -358,15 +353,15 @@ public class SignalPainter extends TrackPainter {
boolean continous=true; boolean continous=true;
public RealStencil(NavigableMap<Long, IEvent[]> entries, Object left, boolean continous) { public RealStencil(IEventList entries, Object left, boolean continous) {
this.continous=continous; this.continous=continous;
Collection<IEvent[]> values = entries.values(); Collection<EventEntry> values = entries.entrySet();
minVal=(Double) left; minVal=((DoubleVal) left).value;
range=2.0; range=2.0;
if(!values.isEmpty()) { if(!values.isEmpty()) {
double maxVal=minVal; double maxVal=minVal;
for (IEvent[] val : entries.values()) for (EventEntry val : values)
for(IEvent e:val) { for(IEvent e:val.events) {
double v = ((DoubleVal)e).value; double v = ((DoubleVal)e).value;
if(Double.isNaN(maxVal)) if(Double.isNaN(maxVal))
maxVal=v; maxVal=v;

View File

@ -10,18 +10,17 @@
*******************************************************************************/ *******************************************************************************/
package com.minres.scviewer.database.ui.swt.internal; package com.minres.scviewer.database.ui.swt.internal;
import java.util.Collection; import java.util.TreeMap;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.TreeSet;
import org.eclipse.swt.SWT; import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.graphics.Rectangle;
import com.minres.scviewer.database.EventEntry;
import com.minres.scviewer.database.EventKind; import com.minres.scviewer.database.EventKind;
import com.minres.scviewer.database.IEvent; import com.minres.scviewer.database.IEvent;
import com.minres.scviewer.database.IEventList;
import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.tx.ITx; import com.minres.scviewer.database.tx.ITx;
import com.minres.scviewer.database.tx.ITxEvent; import com.minres.scviewer.database.tx.ITxEvent;
@ -37,19 +36,27 @@ public class StreamPainter extends TrackPainter{
private IWaveform stream; private IWaveform stream;
private int txBase; private int txBase;
private int txHeight; private int txHeight;
private TreeSet<ITx> seenTx; // TODO: remove TreeMap usage
private TreeMap<ITx, ITxEvent> seenTx;
public StreamPainter(WaveformCanvas waveCanvas, boolean even, TrackEntry trackEntry) { public StreamPainter(WaveformCanvas waveCanvas, boolean even, TrackEntry trackEntry) {
super(trackEntry, even); super(trackEntry, even);
this.waveCanvas = waveCanvas; this.waveCanvas = waveCanvas;
this.stream=trackEntry.waveform; this.stream=trackEntry.waveform;
this.seenTx=new TreeSet<>(); this.seenTx=new TreeMap<>();
} }
@SuppressWarnings("unchecked")
public void paintArea(Projection proj, Rectangle area) { public void paintArea(Projection proj, Rectangle area) {
if(stream.getEvents().size()==0) return; int trackHeight=trackEntry.height/stream.getRowCount();
int trackHeight=trackEntry.height/stream.getWidth(); if(stream.getEvents().size()==0) {
proj.setFillRule(SWT.FILL_EVEN_ODD);
proj.setLineStyle(SWT.LINE_SOLID);
proj.setLineWidth(1);
proj.setForeground(this.waveCanvas.styleProvider.getColor(WaveformColors.LINE));
for( int y1=area.y+trackHeight/2; y1<area.y+trackEntry.height; y1+=trackHeight)
proj.drawLine(area.x, y1, area.x+area.width, y1);
return;
}
txBase=trackHeight/5; txBase=trackHeight/5;
txHeight=trackHeight*3/5; txHeight=trackHeight*3/5;
if(trackEntry.selected) { if(trackEntry.selected) {
@ -60,15 +67,16 @@ public class StreamPainter extends TrackPainter{
proj.setFillRule(SWT.FILL_EVEN_ODD); proj.setFillRule(SWT.FILL_EVEN_ODD);
proj.fillRectangle(area); proj.fillRectangle(area);
long scaleFactor = this.waveCanvas.getScaleFactor(); long scaleFactor = this.waveCanvas.getScale();
long beginPos = area.x; long beginPos = area.x;
long beginTime = beginPos*scaleFactor; long beginTime = beginPos*scaleFactor;
long endTime = beginTime + area.width*scaleFactor; long endTime = beginTime + area.width*scaleFactor;
Entry<Long, ?> firstTx=stream.getEvents().floorEntry(beginTime); IEventList events = stream.getEvents();
Entry<Long, ?> lastTx=stream.getEvents().ceilingEntry(endTime); EventEntry firstTx = events.floorEntry(beginTime);
if(firstTx==null) firstTx = stream.getEvents().firstEntry(); EventEntry lastTx = events.ceilingEntry(endTime);
if(lastTx==null) lastTx=stream.getEvents().lastEntry(); if(firstTx==null) firstTx = events.firstEntry();
if(lastTx==null) lastTx = events.lastEntry();
proj.setFillRule(SWT.FILL_EVEN_ODD); proj.setFillRule(SWT.FILL_EVEN_ODD);
proj.setLineStyle(SWT.LINE_SOLID); proj.setLineStyle(SWT.LINE_SOLID);
proj.setLineWidth(1); proj.setLineWidth(1);
@ -77,49 +85,53 @@ public class StreamPainter extends TrackPainter{
for( int y1=area.y+trackHeight/2; y1<area.y+trackEntry.height; y1+=trackHeight) for( int y1=area.y+trackHeight/2; y1<area.y+trackEntry.height; y1+=trackHeight)
proj.drawLine(area.x, y1, area.x+area.width, y1); proj.drawLine(area.x, y1, area.x+area.width, y1);
if(firstTx==lastTx) { if(firstTx==lastTx) {
for(ITxEvent txEvent:(Collection<? extends ITxEvent>)firstTx.getValue()) for(IEvent txEvent: firstTx.events)
drawTx(proj, area, txEvent.getTransaction(), false); drawTx(proj, area, ((ITxEvent)txEvent).getTransaction(), ((ITxEvent)txEvent).getRowIndex(), false);
}else{ }else{
seenTx.clear(); seenTx.clear();
NavigableMap<Long, IEvent[]> entries = stream.getEvents().subMap(firstTx.getKey(), true, lastTx.getKey(), true); ITxEvent highlighed=null;
boolean highlighed=false;
proj.setForeground(this.waveCanvas.styleProvider.getColor(WaveformColors.LINE)); proj.setForeground(this.waveCanvas.styleProvider.getColor(WaveformColors.LINE));
long selectedId=waveCanvas.currentSelection!=null? waveCanvas.currentSelection.getId():-1; long selectedId=waveCanvas.currentSelection!=null? waveCanvas.currentSelection.getId():-1;
for(Entry<Long, IEvent[]> entry: entries.entrySet()) for(EventEntry entry: events.subMap(firstTx.timestamp, true, lastTx.timestamp))
for(IEvent evt:entry.getValue()){ for(IEvent e:entry.events){
ITx tx = ((ITxEvent) evt).getTransaction(); ITxEvent evt = (ITxEvent) e;
highlighed|=selectedId==tx.getId(); ITx tx = evt.getTransaction();
if(selectedId==tx.getId())
highlighed=evt;
switch(evt.getKind()) { switch(evt.getKind()) {
case BEGIN: case BEGIN:
seenTx.add(tx); seenTx.put(tx, evt);
break; break;
case END: case END:
drawTx(proj, area, tx, evt.getRowIndex(), false);
seenTx.remove(tx); seenTx.remove(tx);
break;
case SINGLE: case SINGLE:
drawTx(proj, area, tx, false); drawTx(proj, area, tx, evt.getRowIndex(), false);
break; break;
} }
} }
for(ITx tx:seenTx){ seenTx.entrySet().stream().forEach(e -> {
drawTx(proj, area, tx, false); drawTx(proj, area, e.getKey(), e.getValue().getRowIndex(), false);
} });
if(highlighed){
if(highlighed!=null){
proj.setForeground(this.waveCanvas.styleProvider.getColor(WaveformColors.LINE_HIGHLITE)); proj.setForeground(this.waveCanvas.styleProvider.getColor(WaveformColors.LINE_HIGHLITE));
drawTx(proj, area, waveCanvas.currentSelection, true); drawTx(proj, area, highlighed.getTransaction(), highlighed.getRowIndex(), true);
} }
} }
} }
protected void drawTx(Projection proj, Rectangle area, ITx tx, boolean highlighted ) { protected void drawTx(Projection proj, Rectangle area, ITx tx, int concurrencyIndex, boolean highlighted ) {
// compute colors // compute colors
Color[] transColor = waveCanvas.styleProvider.computeColor( tx.getGenerator().getName()); Color[] transColor = waveCanvas.styleProvider.computeColor( tx.getGenerator().getName());
proj.setBackground(transColor[highlighted?1:0]); proj.setBackground(transColor[highlighted?1:0]);
int offset = tx.getConcurrencyIndex()*this.waveCanvas.styleProvider.getTrackHeight(); int offset = concurrencyIndex*this.waveCanvas.styleProvider.getTrackHeight();
Rectangle bb = new Rectangle( Rectangle bb = new Rectangle(
(int)(tx.getBeginTime()/this.waveCanvas.getScaleFactor()), area.y+offset+txBase, (int)(tx.getBeginTime()/this.waveCanvas.getScale()), area.y+offset+txBase,
(int)((tx.getEndTime()-tx.getBeginTime())/this.waveCanvas.getScaleFactor()), txHeight); (int)((tx.getEndTime()-tx.getBeginTime())/this.waveCanvas.getScale()), txHeight);
if(bb.x+bb.width<area.x || bb.x>area.x+area.width) return; if(bb.x+bb.width<area.x || bb.x>area.x+area.width) return;
if(bb.width==0){ if(bb.width==0){
@ -143,12 +155,12 @@ public class StreamPainter extends TrackPainter{
public ITx getClicked(Point point) { public ITx getClicked(Point point) {
int lane=point.y/waveCanvas.styleProvider.getTrackHeight(); int lane=point.y/waveCanvas.styleProvider.getTrackHeight();
Entry<Long, IEvent[]> firstTx=stream.getEvents().floorEntry(point.x*waveCanvas.getScaleFactor()); EventEntry firstTx=stream.getEvents().floorEntry(point.x*waveCanvas.getScale());
if(firstTx!=null){ if(firstTx!=null){
do { do {
ITx tx = getTxFromEntry(lane, point.x, firstTx); ITx tx = getTxFromEntry(lane, point.x, firstTx.events);
if(tx!=null) return tx; if(tx!=null) return tx;
firstTx=stream.getEvents().lowerEntry(firstTx.getKey()); firstTx=stream.getEvents().lowerEntry(firstTx.timestamp);
}while(firstTx!=null); }while(firstTx!=null);
} }
return null; return null;
@ -162,27 +174,21 @@ public class StreamPainter extends TrackPainter{
this.stream = stream; this.stream = stream;
} }
protected ITx getTxFromEntry(int lane, int offset, Entry<Long, IEvent[]> firstTx) { protected ITx getTxFromEntry(int lane, int offset, IEvent[] firstTx) {
long timePoint=offset*waveCanvas.getScaleFactor(); long timePoint=offset*waveCanvas.getScale();
for(IEvent evt:firstTx.getValue()){ long timePointLow=(offset-5)*waveCanvas.getScale();
if(evt instanceof ITxEvent) { long timePointHigh=(offset+5)*waveCanvas.getScale();
ITx tx=((ITxEvent)evt).getTransaction(); for(IEvent e:firstTx){
if((evt.getKind()==EventKind.BEGIN || evt.getKind()==EventKind.SINGLE)&& if(e instanceof ITxEvent) {
tx.getConcurrencyIndex()==lane && tx.getBeginTime()<=timePoint && tx.getEndTime()>=timePoint){ ITxEvent evt = (ITxEvent) e;
return ((ITxEvent)evt).getTransaction(); ITx tx=evt.getTransaction();
} if(
} (evt.getKind()==EventKind.SINGLE && evt.getTime()==timePoint) ||
} (evt.getKind()==EventKind.SINGLE && evt.getTime()>timePointLow && evt.getTime()<timePointHigh) ||
// now with some fuzziness (evt.getKind()==EventKind.BEGIN && evt.getRowIndex()==lane && evt.getTime()<=timePoint && tx.getEndTime()>=timePoint)
timePoint=(offset-5)*waveCanvas.getScaleFactor(); ){
long timePointHigh=(offset+5)*waveCanvas.getScaleFactor(); return tx;
for(IEvent evt:firstTx.getValue()){ }
if(evt instanceof ITxEvent) {
ITx tx=((ITxEvent)evt).getTransaction();
if((evt.getKind()==EventKind.BEGIN || evt.getKind()==EventKind.SINGLE) &&
tx.getConcurrencyIndex()==lane && tx.getBeginTime()<=timePointHigh && tx.getEndTime()>=timePoint){
return ((ITxEvent)evt).getTransaction();
}
} }
} }
return null; return null;

View File

@ -19,7 +19,7 @@ import org.eclipse.swt.graphics.Rectangle;
import com.minres.scviewer.database.ui.WaveformColors; import com.minres.scviewer.database.ui.WaveformColors;
public class TrackAreaPainter implements IPainter { public class TrackAreaPainter implements IPainter {
/** /**
* *
*/ */
@ -35,14 +35,15 @@ public class TrackAreaPainter implements IPainter {
} }
public void paintArea(Projection proj, Rectangle a) { public void paintArea(Projection proj, Rectangle a) {
Rectangle area = proj.unProject(new Rectangle(a.x, a.y+waveCanvas.rulerHeight, a.width, a.height-waveCanvas.rulerHeight)); Rectangle area = proj.unProject(new Rectangle(a.x, a.y+waveCanvas.rulerHeight, a.width, a.height-waveCanvas.rulerHeight));
proj.setBackground(this.waveCanvas.styleProvider.getColor(WaveformColors.TRACK_BG_EVEN)); proj.setBackground(this.waveCanvas.styleProvider.getColor(WaveformColors.TRACK_BG_EVEN));
proj.setFillRule(SWT.FILL_EVEN_ODD); proj.setFillRule(SWT.FILL_EVEN_ODD);
proj.fillRectangle(area); proj.fillRectangle(area);
if(trackVerticalOffset.size()>0){ if(trackVerticalOffset.size()>0){
Integer firstKey=trackVerticalOffset.floorKey(area.y); Integer firstKey=trackVerticalOffset.floorKey(area.y);
if(firstKey==null) firstKey=trackVerticalOffset.firstKey(); if(firstKey==null) firstKey=trackVerticalOffset.firstKey();
Integer lastKey = trackVerticalOffset.floorKey(area.y+area.height); Integer lastKey = trackVerticalOffset.floorKey(area.y+area.height);
//if(lastKey==null) lastKey= trackVerticalOffset.lastKey();
Rectangle subArea = new Rectangle(area.x, 0, area.width, 0); Rectangle subArea = new Rectangle(area.x, 0, area.width, 0);
if(lastKey.equals(firstKey)){ if(lastKey.equals(firstKey)){
subArea.y=firstKey; subArea.y=firstKey;
@ -61,9 +62,9 @@ public class TrackAreaPainter implements IPainter {
public void addTrackPainter(IWaveformPainter trackPainter){ public void addTrackPainter(IWaveformPainter trackPainter){
trackVerticalOffset.put(trackPainter.getVerticalOffset()+waveCanvas.rulerHeight, trackPainter); trackVerticalOffset.put(trackPainter.getVerticalOffset()+waveCanvas.rulerHeight, trackPainter);
} }
public int getHeight(){ public int getHeight(){
if(trackVerticalOffset.size()==0) return 1; if(trackVerticalOffset.size()==0) return 1;
return trackVerticalOffset.lastKey() + trackVerticalOffset.lastEntry().getValue().getHeight(); return trackVerticalOffset.lastKey() + trackVerticalOffset.lastEntry().getValue().getHeight();

View File

@ -11,10 +11,12 @@
package com.minres.scviewer.database.ui.swt.internal; package com.minres.scviewer.database.ui.swt.internal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Optional;
import org.eclipse.swt.SWT; import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlAdapter;
@ -32,37 +34,47 @@ import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.ScrollBar; import org.eclipse.swt.widgets.ScrollBar;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.minres.scviewer.database.EventEntry;
import com.minres.scviewer.database.IEvent;
import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.RelationType; import com.minres.scviewer.database.RelationType;
import com.minres.scviewer.database.tx.ITx; import com.minres.scviewer.database.tx.ITx;
import com.minres.scviewer.database.tx.ITxEvent;
import com.minres.scviewer.database.ui.IWaveformStyleProvider; import com.minres.scviewer.database.ui.IWaveformStyleProvider;
import com.minres.scviewer.database.ui.IWaveformView; import com.minres.scviewer.database.ui.IWaveformView;
import com.minres.scviewer.database.ui.IWaveformZoom;
import com.minres.scviewer.database.ui.TrackEntry; import com.minres.scviewer.database.ui.TrackEntry;
import com.minres.scviewer.database.ui.ZoomKind;
import com.minres.scviewer.database.ui.swt.Constants; import com.minres.scviewer.database.ui.swt.Constants;
import com.minres.scviewer.database.ui.swt.internal.slider.ZoomBar;
public class WaveformCanvas extends Canvas { public class WaveformCanvas extends Canvas implements IWaveformZoom{
public static final long ZOOM_FIT = -2;
public static final long ZOOM_FULL = -1;
private static final int INITIAL_ZOOM_BAR_MAX = 1000;
private boolean doubleBuffering = true; private boolean doubleBuffering = true;
IWaveformStyleProvider styleProvider; IWaveformStyleProvider styleProvider;
private long scaleFactor = 1000000L; // 1ns private int scaleMagnitude = 6;
String unit="ns"; private long scaleFactor = Constants.POWERS_OF_TEN[scaleMagnitude];
private int level = 12; private long maxTime;
private long maxTime; protected Point origin; /* original size */
protected Point origin; /* original size */ protected int rulerHeight=40;
protected int rulerHeight=40; protected List<IPainter> painterList;
protected List<IPainter> painterList; ITx currentSelection;
ITx currentSelection; private List<SelectionAdapter> selectionListeners;
private List<SelectionAdapter> selectionListeners;
private RulerPainter rulerPainter; private RulerPainter rulerPainter;
@ -72,443 +84,525 @@ public class WaveformCanvas extends Canvas {
private List<CursorPainter> cursorPainters; private List<CursorPainter> cursorPainters;
private ZoomBar horizontal;
private int[] lastHorSelection;
private long sliderScaleFactor = 1;
private ScrollBar vertical;
HashMap<IWaveform, IWaveformPainter> wave2painterMap; HashMap<IWaveform, IWaveformPainter> wave2painterMap;
/**
* Constructor for ScrollableCanvas. public WaveformCanvas(final Composite parent, int style, IWaveformStyleProvider styleProvider, ZoomBar.IProvider scrollbarProvider) {
* super(parent, (style & ~SWT.H_SCROLL) | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.V_SCROLL );
* @param parent this.styleProvider=styleProvider;
* the parent of this control.super(parent, style | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE | SWT.V_SCROLL | SWT.H_SCROLL); addControlListener(new ControlAdapter() { /* resize listener. */
* @param style
* the style of this control.
*/
public WaveformCanvas(final Composite parent, int style, IWaveformStyleProvider styleProvider) {
super(parent, style | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.V_SCROLL | SWT.H_SCROLL);
this.styleProvider=styleProvider;
addControlListener(new ControlAdapter() { /* resize listener. */
@Override @Override
public void controlResized(ControlEvent event) { public void controlResized(ControlEvent event) {
syncScrollBars(); syncSb();
} }
}); });
addPaintListener((final PaintEvent event) -> paint(event.gc)); addPaintListener((final PaintEvent event) -> paint(event.gc));
painterList = new LinkedList<>(); painterList = new LinkedList<>();
origin = new Point(0, 0); origin = new Point(0, 0);
selectionListeners = new LinkedList<>(); selectionListeners = new LinkedList<>();
cursorPainters= new ArrayList<>(); cursorPainters= new ArrayList<>();
wave2painterMap=new HashMap<>(); wave2painterMap=new HashMap<>();
initScrollBars(); horizontal = scrollbarProvider.getScrollBar();
vertical = getVerticalBar();
initScrollBars();
// order is important: it is bottom to top // order is important: it is bottom to top
trackAreaPainter=new TrackAreaPainter(this); trackAreaPainter=new TrackAreaPainter(this);
painterList.add(trackAreaPainter); painterList.add(trackAreaPainter);
arrowPainter=new ArrowPainter(this, IWaveformView.NEXT_PREV_IN_STREAM); arrowPainter=new ArrowPainter(this, IWaveformView.NEXT_PREV_IN_STREAM);
painterList.add(arrowPainter); painterList.add(arrowPainter);
rulerPainter=new RulerPainter(this); rulerPainter=new RulerPainter(this);
painterList.add(rulerPainter); painterList.add(rulerPainter);
CursorPainter cp = new CursorPainter(this, scaleFactor * 10, cursorPainters.size()-1); CursorPainter cp = new CursorPainter(this, getScale() * 10, cursorPainters.size()-1);
painterList.add(cp); painterList.add(cp);
cursorPainters.add(cp); cursorPainters.add(cp);
CursorPainter marker = new CursorPainter(this, scaleFactor * 100, cursorPainters.size()-1); CursorPainter marker = new CursorPainter(this, getScale() * 100, cursorPainters.size()-1);
painterList.add(marker); painterList.add(marker);
cursorPainters.add(marker); cursorPainters.add(marker);
wave2painterMap=new HashMap<>(); wave2painterMap=new HashMap<>();
} }
public void addCursoPainter(CursorPainter cursorPainter){ public void addCursoPainter(CursorPainter cursorPainter){
painterList.add(cursorPainter); painterList.add(cursorPainter);
cursorPainters.add(cursorPainter); cursorPainters.add(cursorPainter);
} }
public void setHighliteRelation(RelationType relationType){
if(arrowPainter!=null){
boolean redraw = arrowPainter.getHighlightType()!=relationType;
arrowPainter.setHighlightType(relationType);
if(redraw) redraw();
}
}
public Point getOrigin() {
return origin;
}
public int getWidth() { public void setHighliteRelation(RelationType relationType){
return getClientArea().width; if(arrowPainter!=null){
} boolean redraw = arrowPainter.getHighlightType()!=relationType;
public void setOrigin(Point origin) { arrowPainter.setHighlightType(relationType);
setOrigin(origin.x, origin.y); if(redraw) redraw();
} }
}
public void setOrigin(int x, int y) { public Point getOrigin() {
checkWidget(); return origin;
ScrollBar hBar = getHorizontalBar(); }
hBar.setSelection(-x);
x = -hBar.getSelection();
ScrollBar vBar = getVerticalBar();
vBar.setSelection(-y);
y = -vBar.getSelection();
origin.x = x;
origin.y = y;
syncScrollBars();
}
public long getMaxTime() { public int getWidth() {
return maxTime; return getClientArea().width;
} }
public void setOrigin(Point origin) {
setOrigin(origin.x, origin.y);
}
public void setMaxTime(long maxTime) { public void setOrigin(int x, int y) {
this.maxTime = maxTime; checkWidget();
syncScrollBars(); origin.x = x;
} origin.y = y;
syncSb();
}
public int getZoomLevel() { @Override
return level; public long getMaxTime() {
} return maxTime;
}
public int getMaxZoomLevel(){
return Constants.UNIT_MULTIPLIER.length*Constants.UNIT_STRING.length-1;
}
public void setZoomLevel(int level) { public void setMaxTime(long maxTime) {
long tc=cursorPainters.get(0).getTime(); // cursor time this.maxTime = maxTime;
setZoomLevel(level, tc); if(maxTime>INITIAL_ZOOM_BAR_MAX) {
} long maxBarTime = maxTime;
while(maxBarTime>Integer.MAX_VALUE) maxBarTime/=1000;
horizontal.setMaximum((int) maxBarTime);
}
sliderScaleFactor = maxTime/horizontal.getMaximum();
syncSb();
}
public void setZoomLevel(int level, long centerTime) { @Override
//FIXME: keep center if zoom-out and cursor is not in view public long getScale() {
long oldScaleFactor=scaleFactor; return scaleFactor;
if(level<0) level = 0; }
if(level<Constants.UNIT_MULTIPLIER.length*Constants.UNIT_STRING.length){
this.scaleFactor = (long) Math.pow(10, level/2d); @Override
if(level%2==1) this.scaleFactor*=3; public void setScale(long factor) {
ITx tx = arrowPainter.getTx(); setScalingFactor(factor, (getMaxVisibleTime()+getMinVisibleTime())/2);
arrowPainter.setTx(null); }
/*
* xc = tc/oldScaleFactor @Override
* xoffs = xc+origin.x public void setVisibleRange(long startTime, long endTime) {
* xcn = tc/newScaleFactor assert(startTime<endTime);
* t0n = (xcn-xoffs)*scaleFactor long time_diff = endTime-startTime;
*/ long factor = (time_diff*11/10)/getClientArea().width;
long xc=centerTime/oldScaleFactor; // cursor total x-offset setScalingFactor(factor, startTime+time_diff/2);
long xoffs=xc+origin.x; // cursor offset relative to left border }
long xcn=centerTime/scaleFactor; // new total x-offset
//@Override
public void setScalingFactor(long factor, long centerTime) {
Rectangle clientArea = getClientArea();
long clientAreaWidth = clientArea.width;
long maxFactor=maxTime/clientAreaWidth;
if(factor<0) {
if(factor== ZOOM_FIT) {
long cTime = getCursorPainters().get(0).getTime();
long time_diff = centerTime>cTime?centerTime-cTime:cTime-centerTime;
centerTime = (centerTime>cTime?cTime:centerTime)+time_diff/2;
factor = (time_diff*11/10)/clientAreaWidth;
} else if(factor== ZOOM_FULL)
factor = maxFactor;
}
if(factor==0)
factor=1;
else if(factor>maxFactor)
factor=maxFactor;
if(factor!=getScale() || (getMaxVisibleTime()+getMinVisibleTime()/2) != centerTime) {
updateScaleFactor(factor);
ITx tx = arrowPainter.getTx();
arrowPainter.setTx(null);
/*
* xc = tc/oldScaleFactor
* xoffs = xc+origin.x
* xcn = tc/newScaleFactor
* t0n = (xcn-xoffs)*getScale()
*/
long xoffs = clientAreaWidth/2;
long xcn=centerTime/getScale(); // new total x-offset
long originX=xcn-xoffs; long originX=xcn-xoffs;
if(originX>0) { if(originX>0) {
origin.x=(int) -originX; // new cursor time offset relative to left border origin.x=(int) -originX; // new cursor time offset relative to left border
}else { }else {
origin.x=0; origin.x=0;
} }
syncScrollBars(); syncSb();
arrowPainter.setTx(tx); arrowPainter.setTx(tx);
redraw(); redraw();
this.level = level; }
} }
}
public long getScaleFactor() { private void updateScaleFactor(long factor) {
return scaleFactor; scaleFactor = factor;
} scaleMagnitude = 0;
for(int i=Constants.POWERS_OF_TEN.length-1; i>0; i--) {
if(scaleFactor>=Constants.POWERS_OF_TEN[i]) {
scaleMagnitude = i;
break;
}
}
}
public long getScaleFactorPow10() { @Override
int scale = level/Constants.UNIT_MULTIPLIER.length; public String timeToString(long time) {
double res = Math.pow(1000, scale); int idx = scaleMagnitude/3;
return (long) res; double fTime = (double)time/Constants.UNIT_MULTIPLIER[idx];
} return Constants.getTimeFormatForLevel(idx).format(fTime)+Constants.UNIT_STRING[idx];
}
public String getUnitStr(){ public long getTimeForOffset(int xOffset){
return Constants.UNIT_STRING[level/Constants.UNIT_MULTIPLIER.length]; return (xOffset-origin.x) * getScale();
} }
public int getUnitMultiplier(){
return Constants.UNIT_MULTIPLIER[level%Constants.UNIT_MULTIPLIER.length];
}
public long getTimeForOffset(int xOffset){
return (xOffset-origin.x) * scaleFactor;
}
public void addPainter(IPainter painter) {
painterList.add(painter);
redraw();
}
public void removePainter(IPainter painter) { public void addPainter(IPainter painter) {
painterList.remove(painter); painterList.add(painter);
redraw(); redraw();
} }
public void clearAllWaveformPainter() { public void removePainter(IPainter painter) {
clearAllWaveformPainter(true); painterList.remove(painter);
} redraw();
}
void clearAllWaveformPainter(boolean update) {
trackAreaPainter.trackVerticalOffset.clear();
wave2painterMap.clear();
if(update) syncScrollBars();
}
public void addWaveformPainter(IWaveformPainter painter) { public void clearAllWaveformPainter() {
addWaveformPainter(painter, true); clearAllWaveformPainter(true);
} }
void addWaveformPainter(IWaveformPainter painter, boolean update) {
trackAreaPainter.addTrackPainter(painter);
wave2painterMap.put(painter.getTrackEntry().waveform, painter);
if(update) syncScrollBars();
}
public List<CursorPainter> getCursorPainters() { void clearAllWaveformPainter(boolean update) {
trackAreaPainter.trackVerticalOffset.clear();
wave2painterMap.clear();
if(update) syncSb();
}
public void addWaveformPainter(IWaveformPainter painter) {
addWaveformPainter(painter, true);
}
void addWaveformPainter(IWaveformPainter painter, boolean update) {
trackAreaPainter.addTrackPainter(painter);
wave2painterMap.put(painter.getTrackEntry().waveform, painter);
if(update) syncSb();
}
public List<CursorPainter> getCursorPainters() {
return cursorPainters; return cursorPainters;
} }
/* Initialize the scrollbar and register listeners. */ /* Initialize the scrollbar and register listeners. */
private void initScrollBars() { private void initScrollBars() {
ScrollBar horizontal = getHorizontalBar(); horizontal.setEnabled(false);
horizontal.setEnabled(false); horizontal.setVisible(true);
horizontal.setVisible(true); horizontal.addSelectionListener(new SelectionAdapter() {
horizontal.addSelectionListener(new SelectionAdapter() {
@Override @Override
public void widgetSelected(SelectionEvent event) { public void widgetSelected(SelectionEvent event) {
if (painterList.isEmpty()) if (!painterList.isEmpty()) {
return; int[] sel = horizontal.getSelection();
setOrigin(-((ScrollBar) event.widget).getSelection(), origin.y); long lowerTime = sel[0]*sliderScaleFactor;
} long upperTime = sel[1]*sliderScaleFactor;
}); if(sel[1]-sel[0] != lastHorSelection[1]-lastHorSelection[0]) {
ScrollBar vertical = getVerticalBar(); long time_diff = upperTime-lowerTime;
vertical.setEnabled(false); long factor = time_diff/getClientArea().width;
vertical.setVisible(true); setScalingFactor(factor, lowerTime+time_diff/2);
vertical.addSelectionListener(new SelectionAdapter() { } else {
origin.x = -(int) (lowerTime/getScale());
WaveformCanvas.this.getDisplay().asyncExec(() -> {redraw();});
}
lastHorSelection=sel;
}
}
});
horizontal.setMinimum(0);
horizontal.setMaximum(INITIAL_ZOOM_BAR_MAX);
lastHorSelection = horizontal.getSelection();
vertical.setEnabled(false);
vertical.setVisible(true);
vertical.addSelectionListener(new SelectionAdapter() {
@Override @Override
public void widgetSelected(SelectionEvent event) { public void widgetSelected(SelectionEvent event) {
if (painterList.isEmpty()) if (!painterList.isEmpty()) {
return; origin.y=-vertical.getSelection();
setOrigin(origin.x, -((ScrollBar) event.widget).getSelection()); fireSelectionEvent();
} WaveformCanvas.this.getDisplay().asyncExec(() -> {redraw();});
}); }
} }
});
/**
* Synchronize the scrollbar with the image. If the transform is out of
* range, it will correct it. This function considers only following factors
* :<b> transform, image size, client area</b>.
*/
public void syncScrollBars() {
if (painterList.isEmpty()) {
redraw();
return;
}
int height = trackAreaPainter.getHeight(); // incl. Ruler
long width = maxTime / scaleFactor;
Rectangle clientArea=getClientArea();
ScrollBar horizontal = getHorizontalBar();
horizontal.setIncrement(getClientArea().width / 100);
horizontal.setPageIncrement(getClientArea().width);
int clientWidthw = clientArea.width;
if (width > clientWidthw) { /* image is wider than client area */
horizontal.setMinimum(0);
horizontal.setMaximum((int)width);
horizontal.setEnabled(true);
if (-origin.x > horizontal.getMaximum() - clientWidthw) {
origin.x = -horizontal.getMaximum() + clientWidthw;
}
} else { /* image is narrower than client area */
horizontal.setEnabled(false);
}
horizontal.setThumb(clientWidthw);
horizontal.setSelection(-origin.x);
ScrollBar vertical = getVerticalBar();
vertical.setIncrement(getClientArea().height / 100);
vertical.setPageIncrement(getClientArea().height);
int clientHeighth = clientArea.height;
if (height > clientHeighth) { /* image is higher than client area */
vertical.setMinimum(0);
vertical.setMaximum(height);
vertical.setEnabled(true);
if ( -origin.y > vertical.getMaximum() - clientHeighth) {
origin.y = -vertical.getMaximum() + clientHeighth;
}
} else { /* image is less higher than client area */
vertical.setMaximum(clientHeighth);
vertical.setEnabled(false);
}
vertical.setThumb(clientHeighth);
vertical.setSelection(-origin.y);
redraw();
fireSelectionEvent();
}
/* Paint function */
private void paint(GC gc) {
Point pt = getSize();
if(pt.x==0 || pt.y==0) return;
Rectangle clientRect = getClientArea(); /* Canvas' painting area */
GC thisGc = gc;
Image dBackingImg = null;
if(doubleBuffering) {
dBackingImg = new Image(getDisplay(), pt.x, pt.y);
thisGc = new GC(dBackingImg);
thisGc.setBackground(gc.getBackground());
thisGc.setForeground(gc.getForeground());
thisGc.setFont(gc.getFont());
}
Projection p = new Projection(thisGc);
p.setTranslation(origin);
if (!painterList.isEmpty() ) {
for (IPainter painter : painterList)
painter.paintArea(p, clientRect);
} else {
gc.fillRectangle(clientRect);
initScrollBars();
}
if(doubleBuffering) {
gc.drawImage(dBackingImg, 0, 0);
if(dBackingImg!=null) dBackingImg.dispose();
thisGc.dispose();
}
}
public List<Object> getElementsAt(Point point) {
LinkedList<Object> result=new LinkedList<>();
for (IPainter p : Lists.reverse(painterList)) {
if (p instanceof TrackAreaPainter) {
int y = point.y - origin.y;
int x = point.x - origin.x;
Entry<Integer, IWaveformPainter> entry = trackAreaPainter.trackVerticalOffset.floorEntry(y);
if (entry != null) {
if (entry.getValue() instanceof StreamPainter) {
ITx tx = ((StreamPainter) entry.getValue()).getClicked(new Point(x, y - entry.getKey()));
if(tx!=null)
result.add(tx);
}
result.add(entry.getValue().getTrackEntry());
}
} else if (p instanceof CursorPainter) {
if (Math.abs(point.x - origin.x - ((CursorPainter) p).getTime()/scaleFactor) < 2) {
result.add(p);
}
}
}
return result;
}
public List<Object> getEntriesAtPosition(IWaveform iWaveform, int i) {
LinkedList<Object> result=new LinkedList<>();
int x = i - origin.x;
for(IWaveformPainter p: wave2painterMap.values()){
if (p instanceof StreamPainter && ((StreamPainter)p).getStream()==iWaveform) {
result.add(((StreamPainter) p).getClicked(new Point(x, styleProvider.getTrackHeight()/2)));
}
}
return result;
}
public void setSelected(ITx currentSelection) {
this.currentSelection = currentSelection;
if (currentSelection != null)
reveal(currentSelection);
arrowPainter.setTx(currentSelection);
redraw();
}
public void reveal(ITx tx) {
int lower = (int) (tx.getBeginTime() / scaleFactor);
int higher = (int) (tx.getEndTime() / scaleFactor);
Point size = getSize();
size.x -= getVerticalBar().getSize().x + 2;
size.y -= getHorizontalBar().getSize().y;
if (lower < -origin.x) {
setOrigin(-lower, origin.y);
} else if (higher > (size.x - origin.x)) {
setOrigin(size.x - higher, origin.y);
}
for (IWaveformPainter painter : wave2painterMap.values()) {
if (painter instanceof StreamPainter && ((StreamPainter) painter).getStream() == tx.getStream()) {
int top = painter.getVerticalOffset() + styleProvider.getTrackHeight() * tx.getConcurrencyIndex();
int bottom = top + styleProvider.getTrackHeight();
if (top < -origin.y) {
setOrigin(origin.x, -(top-styleProvider.getTrackHeight()));
} else if (bottom > (size.y - origin.y)) {
setOrigin(origin.x, size.y - bottom);
}
}
}
}
public void reveal(IWaveform waveform) {
for (IWaveformPainter painter : wave2painterMap.values()) {
TrackEntry te = painter.getTrackEntry();
if(te.waveform == waveform) {
Point size = getSize();
size.y -=+rulerHeight;
ScrollBar sb = getHorizontalBar();
if((sb.getStyle()&SWT.SCROLLBAR_OVERLAY)!=0 && sb.isVisible())
size.y-= getHorizontalBar().getSize().y;
int top = te.vOffset;
int bottom = top + styleProvider.getTrackHeight();
if (top < -origin.y) {
setOrigin(origin.x, -(top-styleProvider.getTrackHeight()));
} else if (bottom > (size.y - origin.y)) {
setOrigin(origin.x, size.y - bottom);
}
}
}
} }
public void reveal(long time) { /**
int scaledTime = (int) (time / scaleFactor); * Synchronize the scrollbar with the image. If the transform is out of
Point size = getSize(); * range, it will correct it. This function considers only following factors
size.x -= getVerticalBar().getSize().x + 2; * :<b> transform, image size, client area</b>.
size.y -= getHorizontalBar().getSize().y; */
if (scaledTime < -origin.x) { public void syncSb() {
setOrigin(-scaledTime+10, origin.y); if (!painterList.isEmpty()) {
} else if (scaledTime > (size.x - origin.x)) { syncHSb();
setOrigin(size.x - scaledTime-30, origin.y); syncVSb();
} fireSelectionEvent();
} }
redraw();
}
public int getRulerHeight() { private void syncVSb() {
return rulerHeight; Rectangle clientArea=getClientArea();
} int height = trackAreaPainter.getHeight(); // incl. Ruler
int clientHeight = clientArea.height;
vertical.setIncrement(clientHeight / 100);
vertical.setPageIncrement(clientHeight/2);
if (height > clientHeight) { /* image is higher than client area */
vertical.setMinimum(0);
vertical.setMaximum(height);
vertical.setEnabled(true);
if ( -origin.y > vertical.getMaximum() - clientHeight) {
origin.y = -vertical.getMaximum() + clientHeight;
}
} else { /* image is less higher than client area */
vertical.setMaximum(clientHeight);
vertical.setEnabled(false);
}
vertical.setThumb(clientHeight);
vertical.setSelection(-origin.y);
}
public void setRulerHeight(int rulerHeight) { private void syncHSb() {
this.rulerHeight = rulerHeight; horizontal.setEnabled(wave2painterMap.size()>0);
} Rectangle clientArea=getClientArea();
int clientWidth = clientArea.width;
if(sliderScaleFactor>0) {
int lower = (int) ( ( -origin.x * getScale()) / sliderScaleFactor);
int upper = (int) (((clientWidth-origin.x) * getScale()) / sliderScaleFactor);
lastHorSelection = new int[] {Math.max(lower,0), Math.min(upper, horizontal.getMaximum())};
horizontal.setSelection(lastHorSelection);
}
long width = maxTime / getScale();
horizontal.setButtonsEnabled(width > clientWidth);
}
public void addSelectionListener(SelectionAdapter selectionAdapter) { /* Paint function */
selectionListeners.add(selectionAdapter); private void paint(GC gc) {
} Point pt = getSize();
if(pt.x==0 || pt.y==0) return;
Rectangle clientRect = getClientArea(); /* Canvas' painting area */
GC thisGc = gc;
Image dBackingImg = null;
if(doubleBuffering) {
dBackingImg = new Image(getDisplay(), pt.x, pt.y);
thisGc = new GC(dBackingImg);
thisGc.setBackground(gc.getBackground());
thisGc.setForeground(gc.getForeground());
thisGc.setFont(gc.getFont());
public void removeSelectionListener(SelectionAdapter selectionAdapter) { }
selectionListeners.remove(selectionAdapter); Projection p = new Projection(thisGc);
} p.setTranslation(origin);
if (!painterList.isEmpty() ) {
for (IPainter painter : painterList)
painter.paintArea(p, clientRect);
} else {
gc.fillRectangle(clientRect);
initScrollBars();
}
if(doubleBuffering) {
gc.drawImage(dBackingImg, 0, 0);
if(dBackingImg!=null) dBackingImg.dispose();
thisGc.dispose();
}
}
/** public List<Object> getElementsAt(Point point) {
* LinkedList<Object> result=new LinkedList<>();
*/ for (IPainter p : Lists.reverse(painterList)) {
protected void fireSelectionEvent() { if (p instanceof TrackAreaPainter) {
Event e = new Event(); int y = point.y - origin.y;
e.widget = this; int x = point.x - origin.x;
e.detail=SWT.SELECTED; Entry<Integer, IWaveformPainter> entry = trackAreaPainter.trackVerticalOffset.floorEntry(y);
e.type=SWT.Selection; if (entry != null) {
SelectionEvent ev = new SelectionEvent(e); if (entry.getValue() instanceof StreamPainter) {
ev.x = origin.x; ITx tx = ((StreamPainter) entry.getValue()).getClicked(new Point(x, y - entry.getKey()));
ev.y = origin.y; if(tx!=null)
for (SelectionAdapter a : selectionListeners) { result.add(tx);
a.widgetSelected(ev); }
} result.add(entry.getValue().getTrackEntry());
} }
} else if (p instanceof CursorPainter) {
if (Math.abs(point.x - origin.x - ((CursorPainter) p).getTime()/getScale()) < 2) {
result.add(p);
}
}
}
return result;
}
long getMaxVisibleTime() { public List<Object> getEntriesAtPosition(IWaveform iWaveform, int i) {
return (getClientArea().width+origin.x)*scaleFactor; LinkedList<Object> result=new LinkedList<>();
} int x = i - origin.x;
for(IWaveformPainter p: wave2painterMap.values()){
if (p instanceof StreamPainter && ((StreamPainter)p).getStream()==iWaveform) {
result.add(((StreamPainter) p).getClicked(new Point(x, styleProvider.getTrackHeight()/2)));
}
}
return result;
}
long getMinVisibleTime() { public void setSelected(ITx currentSelection) {
return origin.x * scaleFactor; this.currentSelection = currentSelection;
} if (currentSelection != null)
reveal(currentSelection);
arrowPainter.setTx(currentSelection);
redraw();
}
public void reveal(ITx tx) {
int lower = (int) (tx.getBeginTime() / getScale());
int higher = (int) (tx.getEndTime() / getScale());
Point size = getSize();
size.x -= vertical.getSize().x + 2;
size.y -= horizontal.getSize().y;
if (lower < -origin.x) {
setOrigin(-lower, origin.y);
} else if (higher > (size.x - origin.x)) {
setOrigin(size.x - higher, origin.y);
}
for (IWaveformPainter painter : wave2painterMap.values()) {
if (painter instanceof StreamPainter && ((StreamPainter) painter).getStream() == tx.getStream()) {
EventEntry entry = tx.getStream().getEvents().floorEntry(tx.getBeginTime());
Optional<IEvent> res = Arrays.stream(entry.events).filter(e -> ((ITxEvent)e).getTransaction().equals(tx)).findFirst();
if(res.isPresent()) {
int top = painter.getVerticalOffset() + styleProvider.getTrackHeight() * ((ITxEvent)res.get()).getRowIndex();
int bottom = top + styleProvider.getTrackHeight();
if (top < -origin.y) {
setOrigin(origin.x, -(top-styleProvider.getTrackHeight()));
} else if (bottom > (size.y - origin.y)) {
setOrigin(origin.x, size.y - bottom);
}
}
}
}
}
public void reveal(IWaveform waveform) {
for (IWaveformPainter painter : wave2painterMap.values()) {
TrackEntry te = painter.getTrackEntry();
if(te.waveform == waveform) {
Point size = getSize();
size.y -=+rulerHeight;
if((horizontal.getStyle()&SWT.SCROLLBAR_OVERLAY)!=0 && horizontal.isVisible())
size.y-= horizontal.getSize().y;
int top = te.vOffset;
int bottom = top + styleProvider.getTrackHeight();
if (top < -origin.y) {
setOrigin(origin.x, -(top-styleProvider.getTrackHeight()));
} else if (bottom > (size.y - origin.y)) {
setOrigin(origin.x, size.y - bottom);
}
}
}
}
public void reveal(long time) {
int scaledTime = (int) (time / getScale());
Point size = getSize();
size.x -= vertical.getSize().x + 2;
size.y -= horizontal.getSize().y;
if (scaledTime < -origin.x) {
setOrigin(-scaledTime+10, origin.y);
} else if (scaledTime > (size.x - origin.x)) {
setOrigin(size.x - scaledTime-30, origin.y);
}
}
@Override
public void centerAt(long time) {
int scaledTime = (int) (time / getScale());
int newX = -scaledTime+getWidth()/2;
setOrigin(newX>0?0:newX, origin.y);
}
public int getRulerHeight() {
return rulerHeight;
}
public void setRulerHeight(int rulerHeight) {
this.rulerHeight = rulerHeight;
}
public void addSelectionListener(SelectionAdapter selectionAdapter) {
selectionListeners.add(selectionAdapter);
}
public void removeSelectionListener(SelectionAdapter selectionAdapter) {
selectionListeners.remove(selectionAdapter);
}
/**
*
*/
protected void fireSelectionEvent() {
Event e = new Event();
e.widget = this;
e.detail=SWT.SELECTED;
e.type=SWT.Selection;
SelectionEvent ev = new SelectionEvent(e);
ev.x = origin.x;
ev.y = origin.y;
for (SelectionAdapter a : selectionListeners) {
a.widgetSelected(ev);
}
}
@Override
public long getMaxVisibleTime() {
return (getClientArea().width-origin.x)*getScale();
}
@Override
public long getMinVisibleTime() {
return -origin.x * getScale();
}
@Override
public void setMinVisibleTime(long time) {
long duration = getMaxVisibleTime()-getMinVisibleTime();
if(time>0) {
if((time+duration)<getMaxTime()) {
int scaledTime = (int) (time / getScale());
setOrigin(-scaledTime, origin.y);
}
} else {
setOrigin(0, origin.y);
}
}
@Override
public void zoom(ZoomKind kind) {
switch(kind) {
case IN:
setScale(getScale()/2);
break;
case OUT:
setScale(getScale()*2);
break;
case FIT:
setScalingFactor(WaveformCanvas.ZOOM_FIT, cursorPainters.get(1).getTime());
break;
case FULL:
setScale(WaveformCanvas.ZOOM_FULL);
break;
}
}
public void setStyleProvider(IWaveformStyleProvider styleProvider) { public void setStyleProvider(IWaveformStyleProvider styleProvider) {
this.styleProvider=styleProvider; this.styleProvider=styleProvider;
redraw(); redraw();
} }
public int getScaleMagnitude() {
return scaleMagnitude;
}
} }

View File

@ -13,7 +13,6 @@ package com.minres.scviewer.database.ui.swt.internal;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport; import java.beans.PropertyChangeSupport;
import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@ -21,7 +20,6 @@ import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Optional; import java.util.Optional;
import java.util.TreeMap; import java.util.TreeMap;
@ -77,8 +75,10 @@ import org.eclipse.wb.swt.SWTResourceManager;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.minres.scviewer.database.BitVector; import com.minres.scviewer.database.BitVector;
import com.minres.scviewer.database.DoubleVal; import com.minres.scviewer.database.DoubleVal;
import com.minres.scviewer.database.EventEntry;
import com.minres.scviewer.database.EventKind; import com.minres.scviewer.database.EventKind;
import com.minres.scviewer.database.IEvent; import com.minres.scviewer.database.IEvent;
import com.minres.scviewer.database.IEventList;
import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.RelationType; import com.minres.scviewer.database.RelationType;
import com.minres.scviewer.database.WaveformType; import com.minres.scviewer.database.WaveformType;
@ -89,8 +89,9 @@ import com.minres.scviewer.database.ui.GotoDirection;
import com.minres.scviewer.database.ui.ICursor; import com.minres.scviewer.database.ui.ICursor;
import com.minres.scviewer.database.ui.IWaveformStyleProvider; import com.minres.scviewer.database.ui.IWaveformStyleProvider;
import com.minres.scviewer.database.ui.IWaveformView; import com.minres.scviewer.database.ui.IWaveformView;
import com.minres.scviewer.database.ui.IWaveformZoom;
import com.minres.scviewer.database.ui.TrackEntry; import com.minres.scviewer.database.ui.TrackEntry;
import com.minres.scviewer.database.ui.swt.Constants; import com.minres.scviewer.database.ui.swt.internal.slider.ZoomBar;
public class WaveformView implements IWaveformView { public class WaveformView implements IWaveformView {
@ -98,8 +99,6 @@ public class WaveformView implements IWaveformView {
private PropertyChangeSupport pcs; private PropertyChangeSupport pcs;
static final DecimalFormat df = new DecimalFormat("#0.00####");
private ITx currentTxSelection; private ITx currentTxSelection;
private ArrayList<TrackEntry> currentWaveformSelection = new ArrayList<>(); private ArrayList<TrackEntry> currentWaveformSelection = new ArrayList<>();
@ -114,6 +113,10 @@ public class WaveformView implements IWaveformView {
private final Canvas valueList; private final Canvas valueList;
private final Control nameFill;
private final Control valueFill;
final WaveformCanvas waveformCanvas; final WaveformCanvas waveformCanvas;
final ToolTipHandler toolTipHandler; final ToolTipHandler toolTipHandler;
@ -162,8 +165,7 @@ public class WaveformView implements IWaveformView {
: streams.subList(firstIdx, lastIdx + 1); : streams.subList(firstIdx, lastIdx + 1);
setSelection(new StructuredSelection(res), (e.stateMask & SWT.CTRL) != 0, false); setSelection(new StructuredSelection(res), (e.stateMask & SWT.CTRL) != 0, false);
} else } else
setSelection(new StructuredSelection(entry.getValue()), (e.stateMask & SWT.CTRL) != 0, setSelection(new StructuredSelection(entry.getValue()), (e.stateMask & SWT.CTRL) != 0, false);
false);
} else { } else {
setSelection(new StructuredSelection(entry.getValue()), (e.stateMask & SWT.CTRL) != 0, false); setSelection(new StructuredSelection(entry.getValue()), (e.stateMask & SWT.CTRL) != 0, false);
} }
@ -196,88 +198,69 @@ public class WaveformView implements IWaveformView {
down = false; down = false;
if (start == null) if (start == null)
return; return;
if ((e.stateMask & SWT.MODIFIER_MASK & ~SWT.SHIFT) != 0) if ((e.stateMask & SWT.MODIFIER_MASK & ~(SWT.SHIFT | SWT.CTRL)) != 0)
return; // don't react on modifier except shift return; // don't react on modifier except shift and control
if (e.button == 1 && Math.abs(e.x - start.x) > 3) { boolean isCtrl = (e.stateMask & SWT.CTRL)!=0;
asyncUpdate(e.widget); boolean isShift = (e.stateMask & SWT.SHIFT)!=0;
long startTime = waveformCanvas.getTimeForOffset(start.x); if (e.button == 1) {
long endTime = waveformCanvas.getTimeForOffset(end.x); if (Math.abs(e.x - start.x) > 3) { // was drag event
long targetTimeRange = endTime - startTime;
long currentTimeRange = waveformCanvas.getMaxVisibleTime() - waveformCanvas.getMinVisibleTime();
if (targetTimeRange == 0)
return;
long relation = currentTimeRange / targetTimeRange;
long i = 1;
int level = 0;
do {
if (relation < 0) {
if (-relation < i) {
break;
}
level--;
if (-relation < i * 3) {
break;
}
level--;
} else {
if (relation < i) {
break;
}
level++;
if (relation < i * 3) {
break;
}
level++;
}
i = i * 10;
} while (i < 10000);
if (i < 10000) {
int curLevel = waveformCanvas.getZoomLevel();
waveformCanvas.setZoomLevel(curLevel - level, (startTime + endTime) / 2);
}
} else if (e.button == 1 && ((e.stateMask & SWT.SHIFT) == 0)) {
// set cursor (button 1 and no shift)
if (Math.abs(e.x - start.x) < 3 && Math.abs(e.y - start.y) < 3) {
// first set cursor time
setCursorTime(snapOffsetToEvent(start));
// then set selection and reveal
setSelection(new StructuredSelection(initialSelected));
asyncUpdate(e.widget); asyncUpdate(e.widget);
long startTime = waveformCanvas.getTimeForOffset(start.x);
long endTime = waveformCanvas.getTimeForOffset(end.x);
if(startTime<endTime) {
waveformCanvas.setVisibleRange(startTime, endTime);
} else if(start.x!=end.x){
long targetTimeRange = startTime-endTime;
long currentTimeRange = waveformCanvas.getMaxVisibleTime() - waveformCanvas.getMinVisibleTime();
long factor = currentTimeRange/targetTimeRange *waveformCanvas.getScale();
waveformCanvas.setScalingFactor(factor, (startTime+endTime)/2);
}
} else if( isShift) { // set marker (button 1 and shift)
setMarkerTime(selectedMarker, snapOffsetToEvent(start));
} else if(isCtrl) { // set cursor (button 1 and ctrl)
setCursorTime(snapOffsetToEvent(start));
} else { // set cursor (button 1 only)
if (Math.abs(e.y - start.y) < 3) {
// first set cursor time
setCursorTime(snapOffsetToEvent(start));
// then set selection and reveal
setSelection(new StructuredSelection(initialSelected));
}
} }
} else if (e.button == 2 || (e.button == 1 && (e.stateMask & SWT.SHIFT) != 0)) { } else if (e.button == 2) { // set marker (button 2)
// set marker (button 1 and shift) setMarkerTime(selectedMarker, snapOffsetToEvent(start));
setMarkerTime(snapOffsetToEvent(start), selectedMarker);
asyncUpdate(e.widget);
} }
asyncUpdate(e.widget);
} }
protected long snapOffsetToEvent(Point p) { protected long snapOffsetToEvent(Point p) {
long time = waveformCanvas.getTimeForOffset(p.x); long time = waveformCanvas.getTimeForOffset(p.x);
long scaling = 5 * waveformCanvas.getScaleFactor(); long scaling = 5 * waveformCanvas.getScale();
for (Object o : waveformCanvas.getElementsAt(p)) { for (Object o : waveformCanvas.getElementsAt(p)) {
Entry<Long, IEvent[]> floorEntry = null; EventEntry floorEntry = null;
Entry<Long, IEvent[]> ceilEntry = null; EventEntry ceilEntry = null;
if (o instanceof TrackEntry) { if (o instanceof TrackEntry) {
TrackEntry entry = (TrackEntry) o; TrackEntry entry = (TrackEntry) o;
NavigableMap<Long, IEvent[]> map = entry.waveform.getEvents(); IEventList map = entry.waveform.getEvents();
floorEntry = map.floorEntry(time); floorEntry = map.floorEntry(time);
ceilEntry = map.ceilingEntry(time); ceilEntry = map.ceilingEntry(time);
} else if (o instanceof ITx) { } else if (o instanceof ITx) {
NavigableMap<Long, IEvent[]> map = ((ITx) o).getStream().getEvents(); IEventList map = ((ITx) o).getStream().getEvents();
floorEntry = map.floorEntry(time); floorEntry = map.floorEntry(time);
ceilEntry = map.ceilingEntry(time); ceilEntry = map.ceilingEntry(time);
} }
if (floorEntry != null && time - floorEntry.getKey() > scaling) if (floorEntry != null && time - floorEntry.timestamp > scaling)
floorEntry = null; floorEntry = null;
if (ceilEntry != null && ceilEntry.getKey() - time > scaling) if (ceilEntry != null && ceilEntry.timestamp - time > scaling)
ceilEntry = null; ceilEntry = null;
if (ceilEntry == null && floorEntry != null) { if (ceilEntry == null && floorEntry != null) {
time = floorEntry.getKey(); time = floorEntry.timestamp;
} else if (ceilEntry != null && floorEntry == null) { } else if (ceilEntry != null && floorEntry == null) {
time = ceilEntry.getKey(); time = ceilEntry.timestamp;
} else if (ceilEntry != null && floorEntry != null) { } else if (ceilEntry != null && floorEntry != null) {
time = time - floorEntry.getKey() < ceilEntry.getKey() - time ? floorEntry.getKey() time = time - floorEntry.timestamp < ceilEntry.timestamp - time ? floorEntry.timestamp
: ceilEntry.getKey(); : ceilEntry.timestamp;
} }
} }
return time; return time;
@ -287,6 +270,25 @@ public class WaveformView implements IWaveformView {
public void handleEvent(Event e) { public void handleEvent(Event e) {
switch (e.type) { switch (e.type) {
case SWT.MouseWheel: case SWT.MouseWheel:
if((e.stateMask & SWT.CTRL) != 0) {
if(e.count<0) // up scroll
waveformCanvas.setScale(waveformCanvas.getScale()*11/10);
else // down scroll
waveformCanvas.setScale(waveformCanvas.getScale()*10/11);
e.doit=false;
} else if((e.stateMask & SWT.SHIFT) != 0) {
long upper = waveformCanvas.getMaxVisibleTime();
long lower = waveformCanvas.getMinVisibleTime();
long duration = upper-lower;
if(e.count<0) { // up scroll
long newLower = Math.min(waveformCanvas.getMaxTime()-duration, lower+duration/10);
waveformCanvas.setMinVisibleTime(newLower);
} else {// down scroll
long newLower = Math.max(0, lower-duration/10);
waveformCanvas.setMinVisibleTime(newLower);
}
e.doit=false;
}
break; break;
case SWT.MouseDown: case SWT.MouseDown:
start = new Point(e.x, e.y); start = new Point(e.x, e.y);
@ -346,8 +348,26 @@ public class WaveformView implements IWaveformView {
rightSash.setBackground(SWTResourceManager.getColor(SWT.COLOR_GRAY)); rightSash.setBackground(SWTResourceManager.getColor(SWT.COLOR_GRAY));
Composite valuePane = new Composite(rightSash, SWT.NONE); Composite valuePane = new Composite(rightSash, SWT.NONE);
waveformCanvas = new WaveformCanvas(rightSash, SWT.NONE, styleProvider);
Composite waveformPane = new Composite(rightSash, SWT.NONE);
GridLayout gl_waveformPane = new GridLayout(1, false);
gl_waveformPane.verticalSpacing = 0;
gl_waveformPane.marginWidth = 0;
gl_waveformPane.marginHeight = 0;
waveformPane.setLayout(gl_waveformPane);
waveformCanvas = new WaveformCanvas(waveformPane, SWT.NONE | SWT.V_SCROLL /*| SWT.H_SCROLL*/, styleProvider, new ZoomBar.IProvider() {
@Override
public ZoomBar getScrollBar() {
ZoomBar timeSliderPane = new ZoomBar(waveformPane, SWT.NONE);
GridData gd_timeSliderPane = new GridData(SWT.FILL, SWT.BOTTOM, false, false, 1, 1);
timeSliderPane.setLayoutData(gd_timeSliderPane);
return timeSliderPane;
}
});
waveformCanvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
// create the name pane // create the name pane
createTextPane(namePane, "Name"); createTextPane(namePane, "Name");
@ -363,7 +383,10 @@ public class WaveformView implements IWaveformView {
@Override @Override
public void controlResized(ControlEvent e) { public void controlResized(ControlEvent e) {
nameListScrolled.getVerticalBar().setVisible(false); nameListScrolled.getVerticalBar().setVisible(false);
if(nameListScrolled.getSize().y == nameList.getSize().y) {
((GridData)nameFill.getLayoutData()).heightHint=18;
namePane.layout();
}
} }
}); });
nameList = new Canvas(nameListScrolled, SWT.NONE) { nameList = new Canvas(nameListScrolled, SWT.NONE) {
@ -382,7 +405,8 @@ public class WaveformView implements IWaveformView {
}); });
nameList.addMouseListener(nameValueMouseListener); nameList.addMouseListener(nameValueMouseListener);
nameListScrolled.setContent(nameList); nameListScrolled.setContent(nameList);
nameFill = createFill(namePane);
createTextPane(valuePane, "Value"); createTextPane(valuePane, "Value");
valuePane.setBackground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BACKGROUND)); valuePane.setBackground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BACKGROUND));
@ -395,7 +419,10 @@ public class WaveformView implements IWaveformView {
@Override @Override
public void controlResized(ControlEvent e) { public void controlResized(ControlEvent e) {
valueListScrolled.getVerticalBar().setVisible(false); valueListScrolled.getVerticalBar().setVisible(false);
if(valueListScrolled.getSize().y == valueList.getSize().y) {
((GridData)valueFill.getLayoutData()).heightHint=18;
valuePane.layout();
}
} }
}); });
valueList = new Canvas(valueListScrolled, SWT.NONE) { valueList = new Canvas(valueListScrolled, SWT.NONE) {
@ -414,6 +441,7 @@ public class WaveformView implements IWaveformView {
}); });
valueList.addMouseListener(nameValueMouseListener); valueList.addMouseListener(nameValueMouseListener);
valueListScrolled.setContent(valueList); valueListScrolled.setContent(valueList);
valueFill = createFill(valuePane);
waveformCanvas.setMaxTime(1); waveformCanvas.setMaxTime(1);
waveformCanvas.addPaintListener(waveformMouseListener); waveformCanvas.addPaintListener(waveformMouseListener);
@ -460,6 +488,26 @@ public class WaveformView implements IWaveformView {
toolTipHandler = new ToolTipHandler(parent.getShell()); toolTipHandler = new ToolTipHandler(parent.getShell());
toolTipHandler.activateHoverHelp(waveformCanvas); toolTipHandler.activateHoverHelp(waveformCanvas);
// This is the filter that prevents the default handling of mouse wheel in waveformCanvas
getControl().getDisplay().addFilter(SWT.MouseWheel, new Listener() {
@Override
public void handleEvent(Event e) {
// Check if it's the correct widget
if(e.widget.equals(waveformCanvas) && (e.stateMask & SWT.CTRL) != 0) {
waveformMouseListener.handleEvent(e);
e.doit = false;
}
}
});
}
private Control createFill(Composite pane) {
Label cLabel = new Label(pane, SWT.NONE);
cLabel.setBackground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BACKGROUND));
GridData gd_cLabel = new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1);
gd_cLabel.heightHint = 0;
cLabel.setLayoutData(gd_cLabel);
return cLabel;
} }
private void createTextPane(Composite namePane, String text) { private void createTextPane(Composite namePane, String text) {
@ -514,7 +562,7 @@ public class WaveformView implements IWaveformView {
streamEntry.vOffset = tracksVerticalHeight; streamEntry.vOffset = tracksVerticalHeight;
if (streamEntry.waveform.getType() == WaveformType.TRANSACTION) { if (streamEntry.waveform.getType() == WaveformType.TRANSACTION) {
streamEntry.currentValue = ""; streamEntry.currentValue = "";
streamEntry.height *= streamEntry.waveform.getWidth(); streamEntry.height *= streamEntry.waveform.getRowCount();
painter = new StreamPainter(waveformCanvas, even, streamEntry); painter = new StreamPainter(waveformCanvas, even, streamEntry);
} else if (streamEntry.waveform.getType() == WaveformType.SIGNAL) { } else if (streamEntry.waveform.getType() == WaveformType.SIGNAL) {
streamEntry.currentValue = "---"; streamEntry.currentValue = "---";
@ -527,7 +575,7 @@ public class WaveformView implements IWaveformView {
tracksVerticalHeight += streamEntry.height; tracksVerticalHeight += streamEntry.height;
even = !even; even = !even;
} }
waveformCanvas.syncScrollBars(); waveformCanvas.syncSb();
nameList.setSize(nameMaxWidth + 15, tracksVerticalHeight); nameList.setSize(nameMaxWidth + 15, tracksVerticalHeight);
nameListScrolled.setMinSize(nameMaxWidth + 15, tracksVerticalHeight); nameListScrolled.setMinSize(nameMaxWidth + 15, tracksVerticalHeight);
nameList.redraw(); nameList.redraw();
@ -579,20 +627,21 @@ public class WaveformView implements IWaveformView {
entry.currentValue = Double.toString(val); entry.currentValue = Double.toString(val);
} }
} else if (entry.waveform.getType() == WaveformType.TRANSACTION) { } else if (entry.waveform.getType() == WaveformType.TRANSACTION) {
ITx[] resultsList = new ITx[entry.waveform.getWidth()]; ITx[] resultsList = new ITx[entry.waveform.getRowCount()];
Entry<Long, IEvent[]> firstTx = entry.waveform.getEvents().floorEntry(time); EventEntry firstTx = entry.waveform.getEvents().floorEntry(time);
if (firstTx != null) { if (firstTx != null) {
do { do {
for (IEvent evt : firstTx.getValue()) { for (IEvent e : firstTx.events) {
if (evt instanceof ITxEvent) { if (e instanceof ITxEvent) {
ITx tx = ((ITxEvent) evt).getTransaction(); ITxEvent evt = ((ITxEvent) e);
ITx tx = evt.getTransaction();
if ((evt.getKind() == EventKind.BEGIN || evt.getKind() == EventKind.SINGLE) if ((evt.getKind() == EventKind.BEGIN || evt.getKind() == EventKind.SINGLE)
&& tx.getBeginTime() <= time && tx.getEndTime() >= time && tx.getBeginTime() <= time && tx.getEndTime() >= time
&& resultsList[tx.getConcurrencyIndex()] == null) && resultsList[evt.getRowIndex()] == null)
resultsList[tx.getConcurrencyIndex()] = ((ITxEvent) evt).getTransaction(); resultsList[evt.getRowIndex()] = evt.getTransaction();
} }
} }
firstTx = entry.waveform.getEvents().lowerEntry(firstTx.getKey()); firstTx = entry.waveform.getEvents().lowerEntry(firstTx.timestamp);
} while (firstTx != null && !isArrayFull(resultsList)); } while (firstTx != null && !isArrayFull(resultsList));
boolean separator = false; boolean separator = false;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
@ -750,27 +799,30 @@ public class WaveformView implements IWaveformView {
if (!add) if (!add)
currentWaveformSelection.clear(); currentWaveformSelection.clear();
List<?> selList = sel.toList(); List<?> selList = sel.toList();
if (selList.get(0) instanceof ITx) { for(Object o: selList) {
ITx txSel = (ITx) selList.get(0); if (o instanceof ITx) {
TrackEntry trackEntry = selList.size() == 2 && selList.get(1) instanceof TrackEntry ITx txSel = (ITx) o;
? (TrackEntry) selList.get(1) TrackEntry trackEntry = selList.size() == 2 && selList.get(1) instanceof TrackEntry
: null; ? (TrackEntry) selList.get(1)
if (trackEntry == null) { : null;
trackEntry = getEntryFor(txSel); if (trackEntry == null) {
if (trackEntry == null && addIfNeeded) { trackEntry = getEntryFor(txSel);
trackEntry = new TrackEntry(txSel.getStream(), styleProvider); if (trackEntry == null && addIfNeeded) {
streams.add(trackEntry); trackEntry = new TrackEntry(txSel.getStream(), styleProvider);
streams.add(trackEntry);
}
} }
currentTxSelection = txSel;
currentWaveformSelection.clear();
currentWaveformSelection.add(trackEntry);
selectionChanged = true;
} else if (o instanceof TrackEntry) {
TrackEntry e = (TrackEntry)o;
if(!currentWaveformSelection.contains(e))
currentWaveformSelection.add(e);
selectionChanged = true;
} }
currentTxSelection = txSel;
currentWaveformSelection.clear();
currentWaveformSelection.add(trackEntry);
selectionChanged = true;
} else if (selList.size() == 1 && selList.get(0) instanceof TrackEntry) {
currentWaveformSelection.add((TrackEntry) selList.get(0));
if (currentTxSelection != null)
currentTxSelection = null;
selectionChanged = true;
} }
} }
} else { } else {
@ -853,11 +905,11 @@ public class WaveformView implements IWaveformView {
} }
} }
if (transaction == null) { if (transaction == null) {
Entry<Long, IEvent[]> entry = selectedWaveform.waveform.getEvents() EventEntry entry = selectedWaveform.waveform.getEvents()
.higherEntry(currentTxSelection.getBeginTime()); .higherEntry(currentTxSelection.getBeginTime());
if (entry != null) if (entry != null)
do { do {
for (IEvent evt : entry.getValue()) { for (IEvent evt : entry.events) {
if (evt instanceof ITxEvent && (evt.getKind() == EventKind.BEGIN if (evt instanceof ITxEvent && (evt.getKind() == EventKind.BEGIN
|| evt.getKind() == EventKind.SINGLE)) { || evt.getKind() == EventKind.SINGLE)) {
transaction = ((ITxEvent) evt).getTransaction(); transaction = ((ITxEvent) evt).getTransaction();
@ -865,7 +917,7 @@ public class WaveformView implements IWaveformView {
} }
} }
if (transaction == null) if (transaction == null)
entry = selectedWaveform.waveform.getEvents().higherEntry(entry.getKey()); entry = selectedWaveform.waveform.getEvents().higherEntry(entry.timestamp);
} while (entry != null && transaction == null); } while (entry != null && transaction == null);
} }
} else if (direction == GotoDirection.PREV) { } else if (direction == GotoDirection.PREV) {
@ -882,11 +934,11 @@ public class WaveformView implements IWaveformView {
} }
} }
if (transaction == null) { if (transaction == null) {
Entry<Long, IEvent[]> entry = selectedWaveform.waveform.getEvents() EventEntry entry = selectedWaveform.waveform.getEvents()
.lowerEntry(currentTxSelection.getBeginTime()); .lowerEntry(currentTxSelection.getBeginTime());
if (entry != null) if (entry != null)
do { do {
for (IEvent evt : Lists.reverse(Arrays.asList(entry.getValue()))) { for (IEvent evt : Lists.reverse(Arrays.asList(entry.events))) {
if (evt instanceof ITxEvent && (evt.getKind() == EventKind.BEGIN if (evt instanceof ITxEvent && (evt.getKind() == EventKind.BEGIN
|| evt.getKind() == EventKind.SINGLE)) { || evt.getKind() == EventKind.SINGLE)) {
transaction = ((ITxEvent) evt).getTransaction(); transaction = ((ITxEvent) evt).getTransaction();
@ -894,7 +946,7 @@ public class WaveformView implements IWaveformView {
} }
} }
if (transaction == null) if (transaction == null)
entry = selectedWaveform.waveform.getEvents().lowerEntry(entry.getKey()); entry = selectedWaveform.waveform.getEvents().lowerEntry(entry.timestamp);
} while (entry != null && transaction == null); } while (entry != null && transaction == null);
} }
} }
@ -928,7 +980,7 @@ public class WaveformView implements IWaveformView {
return candidates.get(0); return candidates.get(0);
default: default:
ArrayList<ITxRelation> visibleCandidates = candidates.stream().filter(this::streamsVisible) ArrayList<ITxRelation> visibleCandidates = candidates.stream().filter(this::streamsVisible)
.collect(Collectors.toCollection(ArrayList::new)); .collect(Collectors.toCollection(ArrayList::new));
if (visibleCandidates.isEmpty()) { if (visibleCandidates.isEmpty()) {
return new RelSelectionDialog(waveformCanvas.getShell(), candidates, target).open(); return new RelSelectionDialog(waveformCanvas.getShell(), candidates, target).open();
} else if (visibleCandidates.size() == 1) { } else if (visibleCandidates.size() == 1) {
@ -957,14 +1009,14 @@ public class WaveformView implements IWaveformView {
return; return;
TrackEntry sel = currentWaveformSelection.get(0); TrackEntry sel = currentWaveformSelection.get(0);
long time = getCursorTime(); long time = getCursorTime();
NavigableMap<Long, ?> map = null; IEventList map = null;
if (sel.waveform.getType() == WaveformType.TRANSACTION || sel.waveform.getType() == WaveformType.SIGNAL) { if (sel.waveform.getType() == WaveformType.TRANSACTION || sel.waveform.getType() == WaveformType.SIGNAL) {
map = sel.waveform.getEvents(); map = sel.waveform.getEvents();
} }
if (map != null) { if (map != null) {
Entry<Long, ?> entry = direction == GotoDirection.PREV ? map.lowerEntry(time) : map.higherEntry(time); EventEntry entry = direction == GotoDirection.PREV ? map.lowerEntry(time) : map.higherEntry(time);
if (entry != null) { if (entry != null) {
time = entry.getKey(); time = entry.timestamp;
setCursorTime(time); setCursorTime(time);
waveformCanvas.reveal(time); waveformCanvas.reveal(time);
waveformCanvas.redraw(); waveformCanvas.redraw();
@ -1036,7 +1088,7 @@ public class WaveformView implements IWaveformView {
TrackEntry trackEntry = trackVerticalOffset.get(firstKey); TrackEntry trackEntry = trackVerticalOffset.get(firstKey);
IWaveform w = trackEntry.waveform; IWaveform w = trackEntry.waveform;
if (w.getType() == WaveformType.TRANSACTION) if (w.getType() == WaveformType.TRANSACTION)
subArea.height *= w.getWidth(); subArea.height *= w.getRowCount();
drawTextFormat(gc, subArea, firstKey, w.getFullName(), trackEntry.selected); drawTextFormat(gc, subArea, firstKey, w.getFullName(), trackEntry.selected);
} else { } else {
for (Entry<Integer, TrackEntry> entry : trackVerticalOffset.subMap(firstKey, true, lastKey, true) for (Entry<Integer, TrackEntry> entry : trackVerticalOffset.subMap(firstKey, true, lastKey, true)
@ -1044,7 +1096,7 @@ public class WaveformView implements IWaveformView {
IWaveform w = entry.getValue().waveform; IWaveform w = entry.getValue().waveform;
subArea.height = styleProvider.getTrackHeight(); subArea.height = styleProvider.getTrackHeight();
if (w.getType() == WaveformType.TRANSACTION) if (w.getType() == WaveformType.TRANSACTION)
subArea.height *= w.getWidth(); subArea.height *= w.getRowCount();
drawTextFormat(gc, subArea, entry.getKey(), w.getFullName(), entry.getValue().selected); drawTextFormat(gc, subArea, entry.getKey(), w.getFullName(), entry.getValue().selected);
} }
} }
@ -1065,7 +1117,7 @@ public class WaveformView implements IWaveformView {
TrackEntry trackEntry = trackVerticalOffset.get(firstKey); TrackEntry trackEntry = trackVerticalOffset.get(firstKey);
IWaveform w = trackEntry.waveform; IWaveform w = trackEntry.waveform;
if (w.getType() == WaveformType.TRANSACTION) if (w.getType() == WaveformType.TRANSACTION)
subArea.height *= w.getWidth(); subArea.height *= w.getRowCount();
drawValue(gc, subArea, firstKey, trackEntry.currentValue, trackEntry.selected); drawValue(gc, subArea, firstKey, trackEntry.currentValue, trackEntry.selected);
} else { } else {
for (Entry<Integer, TrackEntry> entry : trackVerticalOffset.subMap(firstKey, true, lastKey, true) for (Entry<Integer, TrackEntry> entry : trackVerticalOffset.subMap(firstKey, true, lastKey, true)
@ -1073,7 +1125,7 @@ public class WaveformView implements IWaveformView {
IWaveform w = entry.getValue().waveform; IWaveform w = entry.getValue().waveform;
subArea.height = styleProvider.getTrackHeight(); subArea.height = styleProvider.getTrackHeight();
if (w.getType() == WaveformType.TRANSACTION) if (w.getType() == WaveformType.TRANSACTION)
subArea.height *= w.getWidth(); subArea.height *= w.getRowCount();
drawValue(gc, subArea, entry.getKey(), entry.getValue().currentValue, drawValue(gc, subArea, entry.getKey(), entry.getValue().currentValue,
entry.getValue().selected); entry.getValue().selected);
} }
@ -1113,16 +1165,6 @@ public class WaveformView implements IWaveformView {
this.waveformCanvas.setHighliteRelation(relationType); this.waveformCanvas.setHighliteRelation(relationType);
} }
/*
* (non-Javadoc)
*
* @see com.minres.scviewer.database.swt.IWaveformPanel#getMaxTime()
*/
@Override
public long getMaxTime() {
return waveformCanvas.getMaxTime();
}
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
@ -1133,27 +1175,6 @@ public class WaveformView implements IWaveformView {
this.waveformCanvas.setMaxTime(maxTime); this.waveformCanvas.setMaxTime(maxTime);
} }
/*
* (non-Javadoc)
*
* @see com.minres.scviewer.database.swt.IWaveformPanel#setZoomLevel(int)
*/
@Override
public void setZoomLevel(int scale) {
waveformCanvas.setZoomLevel(scale);
waveformCanvas.reveal(getCursorTime());
}
/*
* (non-Javadoc)
*
* @see com.minres.scviewer.database.swt.IWaveformPanel#getZoomLevel()
*/
@Override
public int getZoomLevel() {
return waveformCanvas.getZoomLevel();
}
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
@ -1172,10 +1193,10 @@ public class WaveformView implements IWaveformView {
* @see com.minres.scviewer.database.swt.IWaveformPanel#setMarkerTime(long, int) * @see com.minres.scviewer.database.swt.IWaveformPanel#setMarkerTime(long, int)
*/ */
@Override @Override
public void setMarkerTime(long time, int index) { public void setMarkerTime(int marker, long time) {
if (waveformCanvas.getCursorPainters().size() > index + 1) { if (waveformCanvas.getCursorPainters().size() > marker + 1) {
final Long oldVal = waveformCanvas.getCursorPainters().get(1 + index).getTime(); final Long oldVal = waveformCanvas.getCursorPainters().get(1 + marker).getTime();
waveformCanvas.getCursorPainters().get(1 + index).setTime(time); waveformCanvas.getCursorPainters().get(1 + marker).setTime(time);
pcs.firePropertyChange(MARKER_PROPERTY, oldVal, time); pcs.firePropertyChange(MARKER_PROPERTY, oldVal, time);
} }
} }
@ -1196,7 +1217,7 @@ public class WaveformView implements IWaveformView {
* @see com.minres.scviewer.database.swt.IWaveformPanel#getActMarkerTime() * @see com.minres.scviewer.database.swt.IWaveformPanel#getActMarkerTime()
*/ */
@Override @Override
public int getSelectedMarkerId() { public int getSelectedMarker() {
return selectedMarker; return selectedMarker;
} }
@ -1228,7 +1249,7 @@ public class WaveformView implements IWaveformView {
if (event.y < tracksVerticalHeight) { if (event.y < tracksVerticalHeight) {
event.doit = true; event.doit = true;
LocalSelectionTransfer.getTransfer() LocalSelectionTransfer.getTransfer()
.setSelection(new StructuredSelection(currentWaveformSelection)); .setSelection(new StructuredSelection(currentWaveformSelection));
} }
} }
@ -1448,58 +1469,32 @@ public class WaveformView implements IWaveformView {
return this.pcs.hasListeners(propertyName); return this.pcs.hasListeners(propertyName);
} }
/*
* (non-Javadoc)
*
* @see com.minres.scviewer.database.swt.IWaveformPanel#getScaledTime(long)
*/
@Override
public String getScaledTime(long time) {
StringBuilder sb = new StringBuilder();
double dTime = time;
double scaledTime = dTime / waveformCanvas.getScaleFactorPow10();
return sb.append(df.format(scaledTime)).append(waveformCanvas.getUnitStr()).toString();
}
/*
* (non-Javadoc)
*
* @see com.minres.scviewer.database.swt.IWaveformPanel#getZoomLevels()
*/
@Override
public String[] getZoomLevels() {
String[] res = new String[Constants.UNIT_MULTIPLIER.length * Constants.UNIT_STRING.length];
int index = 0;
for (String unit : Constants.UNIT_STRING) {
for (int factor : Constants.UNIT_MULTIPLIER) {
res[index++] = Integer.toString(factor) + unit;
}
}
return res;
}
@Override
public long getBaselineTime() {
return -waveformCanvas.getScaleFactorPow10() * waveformCanvas.getOrigin().x;
}
@Override
public void setBaselineTime(Long time) {
Point origin = waveformCanvas.getOrigin();
origin.x = (int) (-time / waveformCanvas.getScaleFactorPow10());
waveformCanvas.setOrigin(origin);
}
@Override @Override
public void scrollHorizontal(int percent) { public void scrollHorizontal(int percent) {
if (percent < -100) if (percent < -100)
percent = -100; percent = -100;
if (percent > 100) if (percent > 100)
percent = 100; percent = 100;
int diff = (waveformCanvas.getWidth() * percent) / 100; long minTime = waveformCanvas.getMinVisibleTime();
Point o = waveformCanvas.getOrigin(); long duration = waveformCanvas.getMaxVisibleTime()-minTime;
waveformCanvas.setOrigin(o.x - diff, o.y); long diff = (duration * percent) / 100;
waveformCanvas.redraw(); waveformCanvas.setMinVisibleTime(minTime+diff);
}
@Override
public void scrollTo(int pos) {
long time = 0;
switch(pos) {
case IWaveformView.CURSOR_POS:
time = getCursorTime();
break;
case IWaveformView.MARKER_POS:
time = getMarkerTime(selectedMarker);
break;
default:
break;
}
waveformCanvas.centerAt(time);
} }
public void asyncUpdate(Widget widget) { public void asyncUpdate(Widget widget) {
@ -1531,5 +1526,13 @@ public class WaveformView implements IWaveformView {
getStreamList().add(idx, e); getStreamList().add(idx, e);
return e; return e;
} }
public boolean waveformsContainsTx() {
return streams.stream().filter(e -> e.waveform.getType() == WaveformType.TRANSACTION).findFirst().isPresent();
}
@Override
public IWaveformZoom getWaveformZoom() {
return waveformCanvas;
}
} }

View File

@ -0,0 +1,35 @@
package com.minres.scviewer.database.ui.swt.internal.slider;
import org.eclipse.swt.widgets.Display;
public class ActionTimer implements Runnable {
public static final int INITIAL_DELAY = 300;
public static final int FAST_DELAY = 50;
private final Display display;
private final TimerAction timerAction;
public interface TimerAction extends Runnable {
boolean isEnabled();
}
public ActionTimer( TimerAction timerAction, Display display ) {
this.display = display;
this.timerAction = timerAction;
}
public void activate() {
if( timerAction.isEnabled() ) {
display.timerExec( INITIAL_DELAY, this );
}
}
@Override
public void run() {
if( timerAction.isEnabled() ) {
timerAction.run();
display.timerExec( FAST_DELAY, this );
}
}
}

View File

@ -0,0 +1,192 @@
package com.minres.scviewer.database.ui.swt.internal.slider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
public class ImageButton extends Composite
{
private Image hoverImage;
private Image normalImage;
private Image pressedImage;
private Image disabledImage;
private int width;
private int height;
private boolean hover;
private boolean pressed;
private boolean autoFire;
private ActionTimer actionTimer;
private ActionTimer.TimerAction timerAction;
public ImageButton(Composite parent, int style) {
super(parent, style);
timerAction = new ActionTimer.TimerAction() {
@Override
public void run() {
notifyListeners();
}
@Override
public boolean isEnabled() {
return pressed;
}
};
actionTimer = new ActionTimer(timerAction, this.getDisplay() );
addListener(SWT.Dispose, event -> {
if (hoverImage != null) hoverImage.dispose();
if (normalImage != null) normalImage.dispose();
if (pressedImage != null) pressedImage.dispose();
if (disabledImage != null) disabledImage.dispose();
});
addListener(SWT.Paint, event -> {
paintControl(event);
});
addMouseTrackListener(new MouseTrackAdapter() {
public void mouseEnter(MouseEvent arg0) {
if(isEnabled()) {
hover=true;
redraw();
}
}
public void mouseExit(MouseEvent arg0) {
if(isEnabled()) {
hover=false;
redraw();
}
}
});
addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(MouseEvent e) {
if(isEnabled()) {
pressed=true;
notifyListeners();
if(autoFire) actionTimer.activate();
redraw();
}
}
@Override
public void mouseUp(MouseEvent e) {
pressed=false;
redraw();
}
});
}
private void paintControl(Event event) {
GC gc = event.gc;
if (hoverImage != null) {
if(pressed)
gc.drawImage(pressedImage, 1, 1);
else if(hover) {
gc.drawImage(hoverImage, 1, 1);
} else if(isEnabled()){
gc.drawImage(normalImage, 1, 1);
} else
gc.drawImage(disabledImage, 1, 1);
}
}
public void setImage(Image[] imgs) {
assert(imgs.length==3);
Display d = Display.getDefault();
normalImage = new Image(d, imgs[0], SWT.IMAGE_COPY);
hoverImage = new Image(d, imgs[1], SWT.IMAGE_COPY);
pressedImage = new Image(d, imgs[2], SWT.IMAGE_COPY);
disabledImage = new Image(d, imgs[0], SWT.IMAGE_DISABLE);
width = imgs[0].getBounds().width;
height = imgs[0].getBounds().height;
redraw();
}
@Override
public Point computeSize(int wHint, int hHint, boolean changed) {
int overallWidth = width;
int overallHeight = height;
if (wHint != SWT.DEFAULT && wHint < overallWidth)
overallWidth = wHint;
if (hHint != SWT.DEFAULT && hHint < overallHeight)
overallHeight = hHint;
return new Point(overallWidth + 2, overallHeight + 2);
}
/**
* Adds the listener to the collection of listeners who will be notified when
* the user changes the receiver's value, by sending it one of the messages
* defined in the <code>SelectionListener</code> interface.
* <p>
* <code>widgetSelected</code> is called when the user changes the receiver's
* value. <code>widgetDefaultSelected</code> is not called.
* </p>
*
* @param listener the listener which should be notified
*
* @exception IllegalArgumentException
* <ul>
* <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
* </ul>
* @exception SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been
* disposed</li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*
* @see SelectionListener
* @see #removeSelectionListener
*/
public void addSelectionListener(final SelectionListener listener) {
checkWidget();
SelectionListenerUtil.addSelectionListener(this, listener);
}
/**
* Removes the listener from the collection of listeners who will be notified
* when the user changes the receiver's value.
*
* @param listener the listener which should no longer be notified
*
* @exception IllegalArgumentException
* <ul>
* <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
* </ul>
* @exception SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been
* disposed</li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*
* @see SelectionListener
* @see #addSelectionListener
*/
public void removeSelectionListener(final SelectionListener listener) {
checkWidget();
SelectionListenerUtil.removeSelectionListener(this, listener);
}
private void notifyListeners() {
Event e = new Event();
e.widget=this;
e.type=SWT.Selection;
SelectionListenerUtil.fireSelectionListeners(this,e);
}
public boolean isAutoFire() {
return autoFire;
}
public void setAutoFire(boolean autoFire) {
this.autoFire = autoFire;
}
}

View File

@ -0,0 +1,631 @@
package com.minres.scviewer.database.ui.swt.internal.slider;
import java.text.Format;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.wb.swt.SWTResourceManager;
public class RangeSlider extends Canvas {
private static final int NONE = 0;
private static final int UPPER = 1 << 0;
private static final int LOWER = 1 << 1;
private static final int BOTH = UPPER | LOWER;
private final int minHeight;
private final int markerWidth;
private final int thumbWidth = 0;
private final Image[] slider, sliderHover, sliderDrag;
private int minimum;
private int maximum;
private int lowerValue;
private int upperValue;
private int increment;
private int pageIncrement;
private int selectedElement;
private boolean upperHover, lowerHover;
private int previousUpperValue, previousLowerValue;
private int startDragUpperValue, startDragLowerValue;
private Point startDragPoint;
private final boolean isFullSelection=false;
private final boolean isHighQuality;
private final boolean isOn;
private Format toolTipFormatter;
private String clientToolTipText;
private StringBuffer toolTip;
private Point coordUpper;
private Point coordLower;
public RangeSlider(final Composite parent, final int style) {
super(parent, SWT.DOUBLE_BUFFERED | ((style & SWT.BORDER) == SWT.BORDER ? SWT.BORDER : SWT.NONE));
slider = new Image[] {
SWTResourceManager.getImage(this.getClass(), "marker_l.png"),
SWTResourceManager.getImage(this.getClass(), "marker_r.png")};
sliderHover = new Image[] {
SWTResourceManager.getImage(this.getClass(), "marker_l_hover.png"),
SWTResourceManager.getImage(this.getClass(), "marker_r_hover.png")};
sliderDrag = new Image[] {
SWTResourceManager.getImage(this.getClass(), "marker_l_pressed.png"),
SWTResourceManager.getImage(this.getClass(), "marker_r_pressed.png")};
Rectangle imgSize = slider[0].getBounds();
minHeight =imgSize.height+2;
markerWidth = imgSize.width;
minimum = lowerValue = 0;
maximum = upperValue = 100;
increment = 1;
pageIncrement = 10;
isHighQuality = (style & SWT.HIGH) == SWT.HIGH;
isOn = (style & SWT.ON) == SWT.ON;
selectedElement = NONE;
addMouseListeners();
addListener(SWT.Resize, event -> {
});
addListener(SWT.KeyDown, event -> {
handleKeyDown(event);
});
addPaintListener(event -> {
drawWidget(event);
});
}
@Override
public int getStyle() {
return super.getStyle() | //
(isOn ? SWT.ON : SWT.NONE) | //
(isFullSelection ? SWT.CONTROL : SWT.NONE) | //
(isHighQuality ? SWT.HIGH : SWT.NONE);
}
private void addMouseListeners() {
addListener(SWT.MouseDown, e -> {
if (e.button == 1 || e.button == 2) {
selectKnobs(e);
selectedElement = (lowerHover ? LOWER : NONE) | (upperHover ? UPPER : NONE);
if (selectedElement!=NONE) {
if((e.stateMask & SWT.CTRL)==0 && e.button != 2)
selectedElement=BOTH;
startDragLowerValue = previousLowerValue = lowerValue;
startDragUpperValue = previousUpperValue = upperValue;
startDragPoint = new Point(e.x, e.y);
}
}
});
addListener(SWT.MouseUp, e -> {
if (selectedElement!=NONE) {
startDragPoint = null;
validateNewValues(e);
super.setToolTipText(clientToolTipText);
selectedElement=NONE;
redraw();
} else if (e.button == 1) {
if(e.x<coordLower.x) {
translateValues(-pageIncrement);
validateNewValues(e);
redraw();
} else if(e.x>coordUpper.x+markerWidth) {
translateValues(pageIncrement);
validateNewValues(e);
redraw();
}
}
});
addListener(SWT.MouseDoubleClick, event -> {
handleMouseDoubleClick(event);
});
addListener(SWT.MouseMove, event -> {
handleMouseMove(event);
});
addListener(SWT.MouseWheel, event -> {
handleMouseWheel(event);
});
addListener(SWT.MouseHover, event -> {
handleMouseHover(event);
});
addMouseTrackListener(new MouseTrackAdapter() {
public void mouseExit(MouseEvent event) {
lowerHover = upperHover = false;
redraw();
}
});
}
private void validateNewValues(final Event e) {
if (upperValue != previousUpperValue || lowerValue != previousLowerValue) {
if (!SelectionListenerUtil.fireSelectionListeners(this,e)) {
upperValue = previousUpperValue;
lowerValue = previousLowerValue;
}
previousUpperValue = upperValue;
previousLowerValue = lowerValue;
increment = Math.max(1, (upperValue-lowerValue)/100);
pageIncrement = Math.max(1, (upperValue-lowerValue)/2);
redraw();
}
}
private boolean busy = false;
private void handleMouseMove(final Event e) {
if (selectedElement==NONE) {
final boolean wasUpper = upperHover;
final boolean wasLower = lowerHover;
selectKnobs(e);
if (wasUpper != upperHover || wasLower != lowerHover) {
redraw();
}
} else { // dragInProgress
final int x = e.x;
if (selectedElement == BOTH) {
final int diff = (int) ((startDragPoint.x - x) / computePixelSizeForSlider()) + minimum;
int newUpper = startDragUpperValue - diff;
int newLower = startDragLowerValue - diff;
if (newUpper > maximum) {
newUpper = maximum;
newLower = maximum - (startDragUpperValue - startDragLowerValue);
} else if (newLower < minimum) {
newLower = minimum;
newUpper = minimum + startDragUpperValue - startDragLowerValue;
}
upperValue = newUpper;
lowerValue = newLower;
handleToolTip(lowerValue, upperValue);
} else if (selectedElement == UPPER) {
upperValue = (int) Math.round((double)(x - markerWidth) / computePixelSizeForSlider()) + minimum;
checkUpperValue();
handleToolTip(upperValue);
} else if (selectedElement == LOWER){
lowerValue = (int) Math.round((double)(x - markerWidth) / computePixelSizeForSlider()) + minimum;
checkLowerValue();
handleToolTip(lowerValue);
}
if (isOn && !busy) {
validateNewValues(e);
busy=true;
getDisplay().timerExec(50, ()->{busy=false;});
} else {
redraw();
}
}
}
private boolean isBetweenKnobs(int x, int y) {
return x < coordUpper.x && x > coordLower.x && y >= minHeight/3 && y <= minHeight/3 + getClientArea().height - 2*minHeight/3;
}
private void selectKnobs(final Event e) {
if (coordLower != null) {
final Rectangle imgBounds = slider[0].getBounds();
final int x = e.x, y = e.y;
lowerHover = x >= coordLower.x && x <= coordLower.x + imgBounds.width && y >= coordLower.y && y <= coordLower.y + imgBounds.height;
upperHover = ((e.stateMask & (SWT.CTRL | SWT.SHIFT)) != 0 || !lowerHover) && //
x >= coordUpper.x && x <= coordUpper.x + imgBounds.width && //
y >= coordUpper.y && y <= coordUpper.y + imgBounds.height;
lowerHover &= (e.stateMask & SWT.CTRL) != 0 || !upperHover;
if (!lowerHover && !upperHover && isBetweenKnobs(x, y)) {
lowerHover = upperHover = true;
}
}
}
private int getCursorValue(int x, int y) {
int value = -1;
final Rectangle clientArea = getClientArea();
if (x < clientArea.width - 2*markerWidth && x >= markerWidth && y >= minHeight/3 && y <= clientArea.height - minHeight/3) {
value = (int) Math.round((x - 9d) / computePixelSizeForSlider()) + minimum;
}
return value;
}
private void handleMouseDoubleClick(final Event e) {
final int value = getCursorValue(e.x, e.y);
if (value >= 0) {
if (value > upperValue) {
translateValues(value-upperValue);
} else if (value < lowerValue) {
translateValues(value-lowerValue);
}
validateNewValues(e);
}
}
private void handleToolTip(int... values) {
if (toolTipFormatter != null) {
try {
if (values.length == 1) {
toolTip.setLength(0);
toolTipFormatter.format(values[0], toolTip, null);
super.setToolTipText(toolTip.toString());
} else if (values.length == 2) {
toolTip.setLength(0);
toolTipFormatter.format(values[0], toolTip, null);
toolTip.append(" \u2194 "); // LEFT RIGHT ARROW
toolTipFormatter.format(values[1], toolTip, null);
super.setToolTipText(toolTip.toString());
}
} catch (final IllegalArgumentException ex) {
super.setToolTipText(clientToolTipText);
}
}
}
private void handleMouseHover(final Event e) {
if (selectedElement!=NONE && toolTipFormatter != null) {
final int value = getCursorValue(e.x, e.y);
if (value >= 0) {
try {
toolTip.setLength(0);
toolTipFormatter.format(value, toolTip, null);
super.setToolTipText(toolTip.toString());
} catch (final IllegalArgumentException ex) {
super.setToolTipText(clientToolTipText);
}
} else {
super.setToolTipText(clientToolTipText);
}
}
}
public void setToolTipFormatter(Format formatter) {
toolTip = formatter != null ? new StringBuffer() : null;
toolTipFormatter = formatter;
}
@Override
public void setToolTipText(String string) {
super.setToolTipText(clientToolTipText = string);
}
private void handleMouseWheel(final Event e) {
previousLowerValue = lowerValue;
previousUpperValue = upperValue;
final int amount = Math.max(1, ((e.stateMask & SWT.SHIFT) != 0 ? (upperValue-lowerValue)/6 : (upperValue-lowerValue)/15));
if ((e.stateMask&SWT.CTRL)==0) {
int newLower = lowerValue + e.count * amount;
int newUpper = upperValue + e.count * amount;
if (newUpper > maximum) {
newUpper = maximum;
newLower = maximum - (upperValue - lowerValue);
} else if (newLower < minimum) {
newLower = minimum;
newUpper = minimum + upperValue - lowerValue;
}
upperValue = newUpper;
lowerValue = newLower;
} else {
int newLower = lowerValue + e.count * amount/2;
int newUpper = upperValue - e.count * amount/2;
int dist = newUpper - newLower;
if (newUpper > maximum) {
newUpper = maximum;
newLower = maximum - dist;
} else if (newLower < minimum) {
newLower = minimum;
newUpper = minimum + dist;
}
if(newUpper<=newLower) {
newLower=lowerValue + (upperValue - lowerValue)/2;
newUpper=newLower+1;
}
upperValue = newUpper;
lowerValue = newLower;
}
validateNewValues(e);
e.doit = false; // we are consuming this event
}
private void checkLowerValue() {
if (lowerValue < minimum) {
lowerValue = minimum;
} else if (lowerValue > (upperValue-thumbWidth)) {
lowerValue = (upperValue-thumbWidth);
}
}
private void checkUpperValue() {
if (upperValue > maximum) {
upperValue = maximum;
} else if (upperValue < (lowerValue+thumbWidth)) {
upperValue = lowerValue+thumbWidth;
}
}
private float computePixelSizeForSlider() {
return (getClientArea().width - 2.0f*markerWidth) / (maximum - minimum);
}
private void drawWidget(final PaintEvent e) {
final Rectangle rect = getClientArea();
if (rect.width == 0 || rect.height == 0) {
return;
}
e.gc.setAdvanced(true);
e.gc.setAntialias(SWT.ON);
drawBackground(e.gc);
if (lowerHover || (selectedElement & LOWER) != 0) {
coordUpper = drawMarker(e.gc, upperValue, true);
coordLower = drawMarker(e.gc, lowerValue, false);
} else {
coordLower = drawMarker(e.gc, lowerValue, false);
coordUpper = drawMarker(e.gc, upperValue, true);
}
}
private void drawBackground(final GC gc) {
final Rectangle clientArea = getClientArea();
gc.setBackground(getBackground());
gc.fillRectangle(clientArea);
if (isEnabled()) {
gc.setForeground(getForeground());
} else {
gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_GRAY));
}
gc.drawRoundRectangle(markerWidth, minHeight/3, clientArea.width - 2*markerWidth, clientArea.height - 2*minHeight/3, 3, 3);
final float pixelSize = computePixelSizeForSlider();
final int startX = (int) (pixelSize * lowerValue);
final int endX = (int) (pixelSize * upperValue);
if (isEnabled()) {
gc.setBackground(getForeground());
} else {
gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_GRAY));
}
gc.fillRectangle(markerWidth+startX, minHeight/3, endX - startX, clientArea.height - 2*minHeight/3);
}
private Point drawMarker(final GC gc, final int value, final boolean upper) {
final float pixelSize = computePixelSizeForSlider();
int x = (int) (pixelSize * value);
final int idx = upper?1:0;
Image image;
if (upper) {
if (upperHover) {
image = (selectedElement & UPPER) != 0 ? sliderDrag[idx] : sliderHover[idx];
} else {
image = slider[idx];
}
} else {
if (lowerHover) {
image = (selectedElement & LOWER) != 0 ? sliderDrag[idx] : sliderHover[idx];
} else {
image = slider[idx];
}
}
if(upper)
x+=slider[idx].getBounds().width;
if (isEnabled()) {
gc.drawImage(image, x, getClientArea().height / 2 - slider[idx].getBounds().height / 2);
} else {
final Image temp = new Image(getDisplay(), image, SWT.IMAGE_DISABLE);
gc.drawImage(temp, x, getClientArea().height / 2 - slider[idx].getBounds().height / 2);
temp.dispose();
}
return new Point(x, getClientArea().height / 2 - slider[idx].getBounds().height / 2);
}
private void moveCursorPosition(int xDelta, int yDelta) {
final Point cursorPosition = getDisplay().getCursorLocation();
cursorPosition.x += xDelta;
cursorPosition.y += yDelta;
getDisplay().setCursorLocation(cursorPosition);
}
private void handleKeyDown(final Event event) {
int accelerator = (event.stateMask & SWT.SHIFT) != 0 ? 10 : (event.stateMask & SWT.CTRL) != 0 ? 2 : 1;
if (selectedElement != NONE) {
switch (event.keyCode) {
case SWT.ESC:
startDragPoint = null;
upperValue = startDragUpperValue;
lowerValue = startDragLowerValue;
validateNewValues(event);
selectedElement = NONE;
if (!isOn) {
redraw();
}
event.doit = false;
break;
case SWT.ARROW_UP:
accelerator = -accelerator;
case SWT.ARROW_LEFT:
moveCursorPosition(-accelerator, 0);
event.doit = false;
break;
case SWT.ARROW_DOWN:
accelerator = -accelerator;
case SWT.ARROW_RIGHT:
moveCursorPosition(accelerator, 0);
event.doit = false;
break;
}
return;
}
previousLowerValue = lowerValue;
previousUpperValue = upperValue;
switch (event.keyCode) {
case SWT.HOME:
if ((event.stateMask & (SWT.SHIFT| SWT.CTRL)) == 0) {
upperValue = minimum + upperValue - lowerValue;
lowerValue = minimum;
}
break;
case SWT.END:
if ((event.stateMask & (SWT.SHIFT| SWT.CTRL)) == 0) {
lowerValue = maximum - (upperValue - lowerValue);
upperValue = maximum;
}
break;
case SWT.PAGE_UP:
translateValues(-accelerator * pageIncrement);
break;
case SWT.PAGE_DOWN:
translateValues( accelerator * pageIncrement);
break;
case SWT.ARROW_DOWN:
case SWT.ARROW_RIGHT:
translateValues( accelerator * increment);
break;
case SWT.ARROW_UP:
case SWT.ARROW_LEFT:
translateValues(-accelerator * increment);
break;
}
if (previousLowerValue != lowerValue || previousUpperValue != upperValue) {
checkLowerValue();
checkUpperValue();
validateNewValues(event);
}
}
private void translateValues(int amount) {
int newLower = lowerValue + amount;
int newUpper = upperValue + amount;
if (newUpper > maximum) {
newUpper = maximum;
newLower = maximum - (upperValue - lowerValue);
} else if (newLower < minimum) {
newLower = minimum;
newUpper = minimum + upperValue - lowerValue;
}
upperValue = newUpper;
lowerValue = newLower;
}
public void addSelectionListener(final SelectionListener listener) {
checkWidget();
SelectionListenerUtil.addSelectionListener(this, listener);
}
public void removeSelectionListener(final SelectionListener listener) {
checkWidget();
SelectionListenerUtil.removeSelectionListener(this, listener);
}
@Override
public Point computeSize(final int wHint, final int hHint, final boolean changed) {
checkWidget();
final int width = Math.max(2*markerWidth+100, wHint);
final int height = Math.max(minHeight, hHint);
return new Point(width, height);
}
public int[] getSelection() {
checkWidget();
return new int[] {lowerValue, upperValue};
}
public int getIncrement() {
checkWidget();
return increment;
}
public int getMaximum() {
checkWidget();
return maximum;
}
public int getMinimum() {
checkWidget();
return minimum;
}
public int getPageIncrement() {
checkWidget();
return pageIncrement;
}
public void setMaximum(final int value) {
setLimits(minimum, value);
}
public void setMinimum(final int value) {
setLimits(value, maximum);
}
public void setLimits(final int min, final int max) {
checkWidget();
if (min >= 0 && min < max && (min != minimum || max != maximum)) {
minimum = min;
maximum = max;
if (lowerValue < minimum) {
lowerValue = minimum;
} else if (lowerValue > maximum) {
lowerValue = maximum;
}
if (upperValue < minimum) {
upperValue = minimum;
} else if (upperValue > maximum) {
upperValue = maximum;
}
redraw();
}
}
public int getUpperValue() {
checkWidget();
return upperValue;
}
public void setUpperValue(final int value) {
setValues(lowerValue, value);
}
public int getLowerValue() {
checkWidget();
return lowerValue;
}
public void setLowerValue(final int value) {
setValues(value, upperValue);
}
public void setValues(final int[] values) {
if (values.length == 2) {
setValues(values[0], values[1]);
}
}
public void setValues(final int lowerValue, final int upperValue) {
setValues(lowerValue, upperValue, false);
}
public void setValues(final int lowerValue, final int upperValue, boolean update) {
checkWidget();
if (lowerValue <= upperValue && lowerValue >= minimum && upperValue <= maximum && (this.lowerValue != lowerValue || this.upperValue != upperValue)) {
this.lowerValue = lowerValue;
this.upperValue = upperValue;
if(update) {
Event e = new Event();
e.type=SWT.Selection;
e.doit=true;
validateNewValues(e);
} else {
increment = Math.max(1, (upperValue-lowerValue)/100);
pageIncrement = Math.max(1, (upperValue-lowerValue)/2);
}
redraw();
}
}
}

View File

@ -0,0 +1,48 @@
package com.minres.scviewer.database.ui.swt.internal.slider;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectionUtils {
/**
* Call a method using introspection (so ones can call a private or protected method)
* @param object object on which the method will be called
* @param methodName method name
* @param args arguments of this method (can be null)
* @return the value returned by this method (if this method returns a value)
*/
public static Object callMethod(final Object object, final String methodName, final Object... args) {
if (object == null) {
return null;
}
final Class<?>[] array = new Class<?>[args == null ? 0 : args.length];
int index = 0;
if (args != null) {
for (final Object o : args) {
array[index++] = o == null ? Object.class : o.getClass();
}
}
return callMethodWithClassType(object, methodName, array, args);
}
private static Object callMethodWithClassType(final Object object, final String methodName, final Class<?>[] array, final Object... args) {
Class<?> currentClass = object.getClass();
Method method = null;
while (currentClass != null) {
try {
method = currentClass.getDeclaredMethod(methodName, array);
break;
} catch (final NoSuchMethodException nsme) {
currentClass = currentClass.getSuperclass();
}
}
try {
method.setAccessible(true);
return method.invoke(object, args);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
return null;
}
}
}

View File

@ -0,0 +1,74 @@
package com.minres.scviewer.database.ui.swt.internal.slider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.TypedListener;
public class SelectionListenerUtil {
/**
* Add a <code>SelectionListener</code> to a given Control
*
* @param control control on which the selection listener is added
* @param listener listener to add
*/
public static void addSelectionListener(final Control control, final SelectionListener listener) {
if (listener == null) {
SWT.error(SWT.ERROR_NULL_ARGUMENT);
}
TypedListener typedListener = new TypedListener(listener);
control.addListener(SWT.Selection, typedListener);
}
/**
* Remove a <code>SelectionListener</code> of a given Control
*
* @param control control on which the selection listener is removed
* @param listener listener to remove
*/
public static void removeSelectionListener(final Control control, final SelectionListener listener) {
if (listener == null) {
SWT.error(SWT.ERROR_NULL_ARGUMENT);
}
final Listener[] listeners = control.getListeners(SWT.Selection);
for (Listener l : listeners) {
if (l instanceof TypedListener) {
TypedListener typedListener = (TypedListener) l;
if (typedListener.getEventListener() == listener) {
ReflectionUtils.callMethod(control, "removeListener", SWT.Selection, ((TypedListener) l).getEventListener());
return;
}
}
}
}
/**
* Fire the selection listeners of a given control
*
* @param control the control that fires the event
* @param sourceEvent mouse event
* @return true if the selection could be changed, false otherwise
*/
public static boolean fireSelectionListeners(final Control control, final Event sourceEvent) {
for (final Listener listener : control.getListeners(SWT.Selection)) {
final Event event = new Event();
event.button = sourceEvent==null?1:sourceEvent.button;
event.display = control.getDisplay();
event.item = null;
event.widget = control;
event.data = sourceEvent == null ? null : sourceEvent.data;
event.time = sourceEvent == null ? 0 : sourceEvent.time;
event.x = sourceEvent == null ? 0 : sourceEvent.x;
event.y = sourceEvent == null ? 0 : sourceEvent.y;
event.type = SWT.Selection;
listener.handleEvent(event);
if (!event.doit) {
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,127 @@
package com.minres.scviewer.database.ui.swt.internal.slider;
import java.text.Format;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.wb.swt.SWTResourceManager;
public class ZoomBar extends Composite {
static public interface IProvider {
ZoomBar getScrollBar();
}
final RangeSlider timeSlider;
final ImageButton leftButton;
final ImageButton rightButton;
/**
* Create the composite.
* @param parent
* @param style
*/
public ZoomBar(Composite parent, int style) {
super(parent, SWT.NO_FOCUS);
GridLayout gridLayout = new GridLayout(3, false);
gridLayout.horizontalSpacing = 0;
gridLayout.verticalSpacing = 0;
gridLayout.marginWidth = 0;
gridLayout.marginHeight = 0;
setLayout(gridLayout);
leftButton = new ImageButton(this, SWT.NONE);
GridData gd_leftButton = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
gd_leftButton.widthHint=14;
gd_leftButton.heightHint=18;
leftButton.setLayoutData(gd_leftButton);
leftButton.setImage(new Image[] {
SWTResourceManager.getImage(this.getClass(), "arrow_left.png"),
SWTResourceManager.getImage(this.getClass(), "arrow_left_hover.png"),
SWTResourceManager.getImage(this.getClass(), "arrow_left_pressed.png")});
leftButton.setAutoFire(true);
timeSlider = new RangeSlider(this, SWT.ON|SWT.HIGH|SWT.SMOOTH|SWT.CONTROL);
timeSlider.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
rightButton = new ImageButton(this, SWT.NONE);
GridData gd_rightButton = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
gd_rightButton.widthHint=18;
gd_rightButton.heightHint=18;
rightButton.setLayoutData(gd_rightButton);
rightButton.setImage(new Image[] {
SWTResourceManager.getImage(this.getClass(), "arrow_right.png"),
SWTResourceManager.getImage(this.getClass(), "arrow_right_hover.png"),
SWTResourceManager.getImage(this.getClass(), "arrow_right_pressed.png")});
rightButton.setAutoFire(true);
leftButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
int[] value = timeSlider.getSelection();
int incr=timeSlider.getIncrement();
int lower = Math.max(timeSlider.getMinimum(), value[0]-incr);
timeSlider.setValues(lower, lower + (value[1]-value[0]), true);
}
});
rightButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
int[] value = timeSlider.getSelection();
int incr=timeSlider.getIncrement();
int upper = Math.min(timeSlider.getMaximum(), value[1]+incr);
timeSlider.setValues(upper - (value[1]-value[0]), upper, true);
}
});
}
@Override
public void setEnabled (boolean enabled) {
timeSlider.setEnabled(enabled);
leftButton.setEnabled(enabled);
rightButton.setEnabled(enabled);
super.setEnabled(enabled);
redraw();
}
public void setButtonsEnabled (boolean enabled) {
leftButton.setEnabled(enabled);
rightButton.setEnabled(enabled);
redraw();
}
public void setToolTipFormatter(Format formatter){
timeSlider.setToolTipFormatter(formatter);
}
public void setToolTipText(String string) {
timeSlider.setToolTipText(string);
}
public void setSelection(int sel) {
timeSlider.setLowerValue(sel);
}
public void setSelection(int[] sel) {
assert(sel.length==2);
timeSlider.setValues(sel[0], sel[1]);
}
public int[] getSelection() {
return timeSlider.getSelection();
}
public void addSelectionListener(SelectionListener selectionListener) {
timeSlider.addSelectionListener(selectionListener);
}
public void setMinimum(int value) {
timeSlider.setMinimum(value);
}
public void setMaximum(int value) {
timeSlider.setMaximum(value);
}
public int getMaximum() {
return timeSlider.getMaximum();
}
public int getMinimum() {
return timeSlider.getMinimum();
}
}

Some files were not shown because too many files have changed in this diff Show More