diff --git a/com.minres.scviewer.database.sqlite/META-INF/MANIFEST.MF b/com.minres.scviewer.database.sqlite/META-INF/MANIFEST.MF index 904a248..edea213 100644 --- a/com.minres.scviewer.database.sqlite/META-INF/MANIFEST.MF +++ b/com.minres.scviewer.database.sqlite/META-INF/MANIFEST.MF @@ -8,7 +8,8 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Require-Bundle: com.minres.scviewer.database;bundle-version="1.0.0", org.eclipse.equinox.util;bundle-version="1.0.500", org.eclipse.equinox.ds;bundle-version="1.4.200", - 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" Bundle-ClassPath: ., sqlite-jdbc-3.8.7.jar Service-Component: OSGI-INF/component.xml diff --git a/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/SQLiteDbLoader.java b/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/SQLiteDbLoader.java index d252028..334d3e7 100644 --- a/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/SQLiteDbLoader.java +++ b/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/SQLiteDbLoader.java @@ -9,10 +9,10 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import com.minres.scviewer.database.EventTime; import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveformDb; import com.minres.scviewer.database.IWaveformDbLoader; +import com.minres.scviewer.database.IWaveformEvent; import com.minres.scviewer.database.RelationType; import com.minres.scviewer.database.sqlite.db.IDatabase; import com.minres.scviewer.database.sqlite.db.SQLiteDatabase; @@ -25,7 +25,7 @@ public class SQLiteDbLoader implements IWaveformDbLoader { protected IDatabase database; - protected List streams; + protected List> streams; long timeResolution=1; @@ -37,25 +37,25 @@ public class SQLiteDbLoader implements IWaveformDbLoader { } @Override - public EventTime getMaxTime() { + public Long getMaxTime() { SQLiteDatabaseSelectHandler handler = new SQLiteDatabaseSelectHandler(ScvTxEvent.class, - database, "time = SELECT MAX(time) FROM ScvTxEvent"); + database, "time = (SELECT MAX(time) FROM ScvTxEvent)"); try { List event = handler.selectObjects(); if(event.size()>0) - return new EventTime(event.get(0).getTime()); + return event.get(0).getTime(); } catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException | InvocationTargetException | SQLException | IntrospectionException e) { e.printStackTrace(); } - return EventTime.ZERO; + return 0L; } @Override - public List getAllWaves() { + public List> getAllWaves() { if(streams==null){ SQLiteDatabaseSelectHandler handler = new SQLiteDatabaseSelectHandler(ScvStream.class, database); - streams=new ArrayList(); + streams=new ArrayList>(); try { for(ScvStream scvStream:handler.selectObjects()){ streams.add(new TxStream(database, db, scvStream)); diff --git a/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/Tx.java b/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/Tx.java index dc8e31e..5714129 100644 --- a/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/Tx.java +++ b/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/Tx.java @@ -8,12 +8,12 @@ import java.util.Collection; import java.util.List; import com.minres.scviewer.database.AssociationType; -import com.minres.scviewer.database.EventTime; +import com.minres.scviewer.database.ITx; import com.minres.scviewer.database.ITxAttribute; +import com.minres.scviewer.database.ITxEvent; import com.minres.scviewer.database.ITxGenerator; import com.minres.scviewer.database.ITxRelation; import com.minres.scviewer.database.ITxStream; -import com.minres.scviewer.database.ITx; import com.minres.scviewer.database.sqlite.db.IDatabase; import com.minres.scviewer.database.sqlite.db.SQLiteDatabaseSelectHandler; import com.minres.scviewer.database.sqlite.tables.ScvTx; @@ -28,7 +28,7 @@ public class Tx implements ITx { private TxGenerator trGenerator; private ScvTx scvTx; private List attributes; - private EventTime begin, end; + private Long begin, end; private List incoming, outgoing; public Tx(IDatabase database, TxStream trStream, TxGenerator trGenerator, ScvTx scvTx) { @@ -44,7 +44,7 @@ public class Tx implements ITx { } @Override - public ITxStream getStream() { + public ITxStream getStream() { return trStream; } @@ -54,13 +54,18 @@ public class Tx implements ITx { } @Override - public EventTime getBeginTime() { + public int getConcurrencyIndex() { + return scvTx.getConcurrencyLevel(); + } + + @Override + public Long getBeginTime() { if(begin==null){ SQLiteDatabaseSelectHandler handler = new SQLiteDatabaseSelectHandler(ScvTxEvent.class, database, "tx="+scvTx.getId()+" AND type="+ AssociationType.BEGIN.ordinal()); try { for(ScvTxEvent scvEvent:handler.selectObjects()){ - begin= new EventTime(scvEvent.getTime()*(Long)database.getData("TIMERESOLUTION")); + begin= scvEvent.getTime()*(Long)database.getData("TIMERESOLUTION"); } } catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException | InvocationTargetException | SQLException | IntrospectionException e) { @@ -70,13 +75,13 @@ public class Tx implements ITx { } @Override - public EventTime getEndTime() { + public Long getEndTime() { if(end==null){ SQLiteDatabaseSelectHandler handler = new SQLiteDatabaseSelectHandler(ScvTxEvent.class, database, "tx="+scvTx.getId()+" AND type="+ AssociationType.END.ordinal()); try { for(ScvTxEvent scvEvent:handler.selectObjects()){ - end = new EventTime(scvEvent.getTime()*(Long)database.getData("TIMERESOLUTION")); + end = scvEvent.getTime()*(Long)database.getData("TIMERESOLUTION"); } } catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException | InvocationTargetException | SQLException | IntrospectionException e) { diff --git a/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/TxEvent.java b/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/TxEvent.java new file mode 100644 index 0000000..24f78fc --- /dev/null +++ b/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/TxEvent.java @@ -0,0 +1,43 @@ +package com.minres.scviewer.database.sqlite; + +import com.minres.scviewer.database.ITx; +import com.minres.scviewer.database.ITxEvent; +import com.minres.scviewer.database.IWaveformEvent; + +public class TxEvent implements ITxEvent { + + private final Type type; + private ITx tx; + + public TxEvent(Type type, ITx tx) { + super(); + this.type = type; + this.tx = tx; + } + + @Override + public Long getTime() { + return type==Type.BEGIN?tx.getBeginTime():tx.getEndTime(); + } + + @Override + public IWaveformEvent duplicate() throws CloneNotSupportedException { + return new TxEvent(type, tx); + } + + @Override + public int compareTo(IWaveformEvent o) { + return getTime().compareTo(o.getTime()); + } + + @Override + public ITx getTransaction() { + return tx; + } + + @Override + public Type getType() { + return type; + } + +} diff --git a/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/TxGenerator.java b/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/TxGenerator.java index 8a36c56..97b3f28 100644 --- a/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/TxGenerator.java +++ b/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/TxGenerator.java @@ -2,16 +2,17 @@ package com.minres.scviewer.database.sqlite; import java.util.List; +import com.minres.scviewer.database.ITx; +import com.minres.scviewer.database.ITxEvent; import com.minres.scviewer.database.ITxGenerator; import com.minres.scviewer.database.ITxStream; -import com.minres.scviewer.database.ITx; import com.minres.scviewer.database.sqlite.tables.ScvGenerator; public class TxGenerator implements ITxGenerator { - private ITxStream stream; + private ITxStream stream; private ScvGenerator scvGenerator; - public TxGenerator(ITxStream stream, ScvGenerator scvGenerator) { + public TxGenerator(ITxStream stream, ScvGenerator scvGenerator) { this.stream=stream; this.scvGenerator=scvGenerator; } @@ -22,7 +23,7 @@ public class TxGenerator implements ITxGenerator { } @Override - public ITxStream getStream() { + public ITxStream getStream() { return stream; } diff --git a/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/TxStream.java b/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/TxStream.java index 2c720b4..c85b5b6 100644 --- a/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/TxStream.java +++ b/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/TxStream.java @@ -4,15 +4,18 @@ import java.beans.IntrospectionException; import java.lang.reflect.InvocationTargetException; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; -import java.util.NavigableSet; -import java.util.TreeSet; +import java.util.Map.Entry; +import java.util.NavigableMap; +import com.google.common.collect.TreeMultimap; import com.minres.scviewer.database.HierNode; +import com.minres.scviewer.database.ITx; +import com.minres.scviewer.database.ITxEvent; import com.minres.scviewer.database.ITxGenerator; import com.minres.scviewer.database.ITxStream; -import com.minres.scviewer.database.ITx; import com.minres.scviewer.database.IWaveformDb; import com.minres.scviewer.database.sqlite.db.IDatabase; import com.minres.scviewer.database.sqlite.db.SQLiteDatabaseSelectHandler; @@ -20,7 +23,7 @@ import com.minres.scviewer.database.sqlite.tables.ScvGenerator; import com.minres.scviewer.database.sqlite.tables.ScvStream; import com.minres.scviewer.database.sqlite.tables.ScvTx; -public class TxStream extends HierNode implements ITxStream { +public class TxStream extends HierNode implements ITxStream { private IDatabase database; @@ -32,7 +35,11 @@ public class TxStream extends HierNode implements ITxStream { private HashMap generators; - private NavigableSet transactions; + private HashMap transactions; + + private Integer maxConcurrency; + + private TreeMultimap events; public TxStream(IDatabase database, IWaveformDb waveformDb, ScvStream scvStream) { super(scvStream.getName()); @@ -81,36 +88,71 @@ public class TxStream extends HierNode implements ITxStream { } @Override - public NavigableSet getTransactions() { - checkTransactions(); - return transactions; + public int getMaxConcurrency() { + if(maxConcurrency==null){ + java.sql.Connection connection=null; + java.sql.Statement statement=null; + java.sql.ResultSet resultSet=null; + try { + connection = database.createConnection(); + statement = connection.createStatement(); + StringBuilder sb = new StringBuilder(); + sb.append("SELECT MAX(concurrencyLevel) as concurrencyLevel FROM ScvTx where stream="); + sb.append(scvStream.getId()); + resultSet = statement.executeQuery(sb.toString()); + while (resultSet.next()) { + Object value = resultSet.getObject("concurrencyLevel"); + if(value!=null) + maxConcurrency=(Integer) value; + } + } catch (SQLException e) { + if(maxConcurrency==null) maxConcurrency=0; + } finally { + try{ + if(resultSet!=null) resultSet.close(); + if(statement!=null) statement.close(); + if(connection!=null) connection.close(); + } catch (SQLException e) { } + } + maxConcurrency+=1; + } + return maxConcurrency; } @Override - public ITx getTransactionById(long id) { - checkTransactions(); - for(ITx trans:transactions){ - if(trans.getId()==id) - return trans; + public NavigableMap> getEvents(){ + if(events==null){ + events=TreeMultimap.create(); + for(Entry entry:getTransactions().entrySet()){ + events.put(entry.getValue().getBeginTime(), new TxEvent(TxEvent.Type.BEGIN, entry.getValue())); + events.put(entry.getValue().getBeginTime(), new TxEvent(TxEvent.Type.END, entry.getValue())); + } } - return null; + return events.asMap(); } - protected void checkTransactions() { + + protected HashMap getTransactions() { if(transactions==null){ if(generators==null) getGenerators(); + transactions = new HashMap(); SQLiteDatabaseSelectHandler handler = new SQLiteDatabaseSelectHandler(ScvTx.class, database, "stream="+scvStream.getId()); - transactions=new TreeSet(); try { for(ScvTx scvTx:handler.selectObjects()){ - transactions.add(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 | InvocationTargetException | SQLException | IntrospectionException e) { e.printStackTrace(); } } + return transactions; + } + + @Override + public Collection getWaveformEventsAtTime(Long time) { + return getEvents().get(time); } } diff --git a/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/db/SQLiteDatabase.java b/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/db/SQLiteDatabase.java index b91c848..426101a 100644 --- a/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/db/SQLiteDatabase.java +++ b/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/db/SQLiteDatabase.java @@ -39,9 +39,9 @@ public class SQLiteDatabase implements IDatabase { @Override public void close(ResultSet resultSet, Statement statement, Connection connection) { try { - resultSet.close(); - statement.close(); - connection.close(); + if(resultSet!=null) resultSet.close(); + if(statement!=null) statement.close(); + if(connection!=null) connection.close(); } catch (SQLException e) {} } diff --git a/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/tables/ScvTx.java b/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/tables/ScvTx.java index c569680..84c352c 100644 --- a/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/tables/ScvTx.java +++ b/com.minres.scviewer.database.sqlite/src/com/minres/scviewer/database/sqlite/tables/ScvTx.java @@ -25,7 +25,16 @@ public class ScvTx { this.stream = stream; } + public int getConcurrencyLevel() { + return concurrencyLevel; + } + + public void setConcurrencyLevel(int concurrencyLevel) { + this.concurrencyLevel = concurrencyLevel; + } + private int id; private int generator; private int stream; + private int concurrencyLevel; } \ No newline at end of file diff --git a/com.minres.scviewer.database.test/.classpath b/com.minres.scviewer.database.test/.classpath index 098194c..16d067f 100644 --- a/com.minres.scviewer.database.test/.classpath +++ b/com.minres.scviewer.database.test/.classpath @@ -1,7 +1,7 @@ - + diff --git a/com.minres.scviewer.database.test/inputs/my_db.txdb b/com.minres.scviewer.database.test/inputs/my_db.txdb index 7d45e18..8aeb87d 100644 Binary files a/com.minres.scviewer.database.test/inputs/my_db.txdb and b/com.minres.scviewer.database.test/inputs/my_db.txdb differ diff --git a/com.minres.scviewer.database.test/inputs/my_db.vcd b/com.minres.scviewer.database.test/inputs/my_db.vcd index 420c38a..9dbf35a 100644 --- a/com.minres.scviewer.database.test/inputs/my_db.vcd +++ b/com.minres.scviewer.database.test/inputs/my_db.vcd @@ -1,5 +1,5 @@ $date - Jan 07, 2015 08:03:07 + Jan 12, 2015 16:55:31 $end $version diff --git a/com.minres.scviewer.database.text/.classpath b/com.minres.scviewer.database.text/.classpath index 46f835e..ec468ee 100644 --- a/com.minres.scviewer.database.text/.classpath +++ b/com.minres.scviewer.database.text/.classpath @@ -1,9 +1,9 @@ - + diff --git a/com.minres.scviewer.database.text/META-INF/MANIFEST.MF b/com.minres.scviewer.database.text/META-INF/MANIFEST.MF index 05e3afa..2d579e8 100644 --- a/com.minres.scviewer.database.text/META-INF/MANIFEST.MF +++ b/com.minres.scviewer.database.text/META-INF/MANIFEST.MF @@ -11,7 +11,8 @@ Require-Bundle: com.minres.scviewer.database;bundle-version="1.0.0", org.codehaus.groovy;bundle-version="1.8.6", org.eclipse.equinox.util;bundle-version="1.0.500", org.eclipse.equinox.ds;bundle-version="1.4.200", - 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" Service-Component: OSGI-INF/component.xml Export-Package: com.minres.scviewer.database.text Bundle-ActivationPolicy: lazy diff --git a/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TextDbLoader.groovy b/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TextDbLoader.groovy index 501a602..6700173 100644 --- a/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TextDbLoader.groovy +++ b/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TextDbLoader.groovy @@ -10,31 +10,18 @@ *******************************************************************************/ package com.minres.scviewer.database.text; -import java.io.InputStream; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import com.minres.scviewer.database.AssociationType; -import com.minres.scviewer.database.DataType; -import com.minres.scviewer.database.HierNode; -import com.minres.scviewer.database.ITxAttributeType; -import com.minres.scviewer.database.ITxAttribute; +import com.minres.scviewer.database.AssociationType +import com.minres.scviewer.database.DataType +import com.minres.scviewer.database.ITxGenerator +import com.minres.scviewer.database.ITxStream import com.minres.scviewer.database.IWaveform -import com.minres.scviewer.database.IWaveformDb; -import com.minres.scviewer.database.ITxGenerator; -import com.minres.scviewer.database.IHierNode; -import com.minres.scviewer.database.ITxStream; -import com.minres.scviewer.database.IWaveformDbLoader; -import com.minres.scviewer.database.InputFormatException; -import com.minres.scviewer.database.EventTime +import com.minres.scviewer.database.IWaveformDb +import com.minres.scviewer.database.IWaveformDbLoader import com.minres.scviewer.database.RelationType public class TextDbLoader implements IWaveformDbLoader{ - private EventTime maxTime; + private Long maxTime; IWaveformDb db; @@ -46,7 +33,7 @@ public class TextDbLoader implements IWaveformDbLoader{ } @Override - public EventTime getMaxTime() { + public Long getMaxTime() { return maxTime; } @@ -74,9 +61,20 @@ public class TextDbLoader implements IWaveformDbLoader{ for(int i=0; itransaction.endTime?maxTime:transaction.endTime endTransaction=true @@ -158,4 +156,7 @@ public class TextDbLoader implements IWaveformDbLoader{ } } + private def calculateConcurrencyIndicees(){ + streams.each{ TxStream stream -> stream.getMaxConcurrency() } + } } diff --git a/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/Tx.groovy b/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/Tx.groovy index 6237366..e33ac09 100644 --- a/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/Tx.groovy +++ b/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/Tx.groovy @@ -10,9 +10,6 @@ *******************************************************************************/ package com.minres.scviewer.database.text -import java.util.Collection; -import java.util.Set - import com.minres.scviewer.database.* class Tx implements ITx { @@ -23,9 +20,11 @@ class Tx implements ITx { TxStream stream - EventTime beginTime + int concurrencyIndex - EventTime endTime + Long beginTime + + Long endTime ArrayList attributes = new ArrayList() @@ -33,7 +32,7 @@ class Tx implements ITx { def outgoingRelations =[] - Tx(int id, TxStream stream, TxGenerator generator, EventTime begin){ + Tx(int id, TxStream stream, TxGenerator generator, Long begin){ this.id=id this.stream=stream this.generator=generator diff --git a/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxEvent.groovy b/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxEvent.groovy new file mode 100644 index 0000000..8098fab --- /dev/null +++ b/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxEvent.groovy @@ -0,0 +1,32 @@ +package com.minres.scviewer.database.text; + +import com.minres.scviewer.database.ITx; +import com.minres.scviewer.database.ITxEvent; +import com.minres.scviewer.database.IWaveformEvent; + +class TxEvent implements ITxEvent { + + final ITxEvent.Type type; + + Tx transaction; + + TxEvent(ITxEvent.Type type, ITx transaction) { + super(); + this.type = type; + this.transaction = transaction; + } + + @Override + IWaveformEvent duplicate() throws CloneNotSupportedException { + new TxEvent(type, transaction, time) + } + + @Override + int compareTo(IWaveformEvent o) { + time.compareTo(o.getTime()) + } + + Long getTime(){ + return type==ITxEvent.Type.BEGIN?transaction.beginTime:transaction.endTime + } +} diff --git a/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxStream.groovy b/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxStream.groovy index 5a42146..2791cac 100644 --- a/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxStream.groovy +++ b/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxStream.groovy @@ -11,10 +11,15 @@ package com.minres.scviewer.database.text import java.beans.PropertyChangeListener; +import java.util.Collection; +import java.util.Comparator; import java.util.List; import java.util.Map; +import java.util.NavigableMap; +import com.google.common.collect.TreeMultimap; import com.minres.scviewer.database.HierNode; +import com.minres.scviewer.database.ITxEvent; import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveformDb import com.minres.scviewer.database.ITxGenerator @@ -24,24 +29,28 @@ import com.minres.scviewer.database.ITx class TxStream extends HierNode implements ITxStream { - Long id; + Long id IWaveformDb database - String fullName; + String fullName - String kind; + String kind - def generators = []; + def generators = [] + + int maxConcurrency + + private TreeMap> events - private TreeSet allTransactions; - TxStream(IWaveformDb db, int id, String name, String kind){ super(name) this.id=id this.database=db this.fullName=name this.kind=kind + this.maxConcurrency=0 + events = new TreeMap>() } List getGenerators(){ @@ -50,37 +59,50 @@ class TxStream extends HierNode implements ITxStream { @Override public IWaveformDb getDb() { - return database; + return database } - // FIXME: maybe need to be somewhere else - public int getMaxConcurrrentTx() { - def rowendtime = [0] - getTransactions().each{Tx tx -> - def rowIdx = 0 - for(rowIdx=0; rowendtime.size()tx.beginTime.value; rowIdx++); - if(rowendtime.size<=rowIdx){ - rowendtime< + generator.transactions.each{ Tx tx -> + putEvent(new TxEvent(ITxEvent.Type.BEGIN, tx)) + putEvent(new TxEvent(ITxEvent.Type.END, tx)) } + } + def rowendtime = [0] + events.keySet().each{long time -> + def value=events.get(time) + def starts=value.findAll{ITxEvent event ->event.type==ITxEvent.Type.BEGIN} + starts.each {ITxEvent event -> + Tx tx = event.transaction + def rowIdx = 0 + for(rowIdx=0; rowIdxtx.beginTime; rowIdx++); + if(rowendtime.size<=rowIdx) + rowendtime< getTransactions() { - if(!allTransactions){ - allTransactions=new TreeSet() - allTransactions.addAll(generators.transactions.flatten()) - } - return allTransactions - } - - @Override - public ITx getTransactionById(long id) { - if(!allTransactions) - allTransactions=generators.transactions.flatten().sort{it.beginTime.value} - allTransactions.find{it.id==id} + public Collection getWaveformEventsAtTime(Long time) { + return events.get(time); } } diff --git a/com.minres.scviewer.database.vcd/.classpath b/com.minres.scviewer.database.vcd/.classpath index 098194c..1fa3e68 100644 --- a/com.minres.scviewer.database.vcd/.classpath +++ b/com.minres.scviewer.database.vcd/.classpath @@ -1,6 +1,6 @@ - + diff --git a/com.minres.scviewer.database.vcd/META-INF/MANIFEST.MF b/com.minres.scviewer.database.vcd/META-INF/MANIFEST.MF index 3fff43f..0270a0c 100644 --- a/com.minres.scviewer.database.vcd/META-INF/MANIFEST.MF +++ b/com.minres.scviewer.database.vcd/META-INF/MANIFEST.MF @@ -8,6 +8,8 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Require-Bundle: com.minres.scviewer.database;bundle-version="1.0.0", org.eclipse.equinox.util;bundle-version="1.0.500", org.eclipse.equinox.ds;bundle-version="1.4.200", - 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" Service-Component: OSGI-INF/component.xml Bundle-ActivationPolicy: lazy +Import-Package: com.google.common.collect diff --git a/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDDbLoader.java b/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDDbLoader.java index 5ceecb8..8d3bf5e 100644 --- a/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDDbLoader.java +++ b/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDDbLoader.java @@ -2,25 +2,21 @@ package com.minres.scviewer.database.vcd; import java.io.File; import java.io.FileInputStream; -import java.util.HashMap; import java.util.List; import java.util.Stack; +import java.util.TreeMap; import java.util.Vector; import com.minres.scviewer.database.BitVector; -import com.minres.scviewer.database.EventTime; -import com.minres.scviewer.database.HierNode; import com.minres.scviewer.database.ISignal; import com.minres.scviewer.database.ISignalChange; import com.minres.scviewer.database.ISignalChangeMulti; import com.minres.scviewer.database.ISignalChangeSingle; -import com.minres.scviewer.database.IWaveformDb; -import com.minres.scviewer.database.IHierNode; -import com.minres.scviewer.database.ITxStream; import com.minres.scviewer.database.IWaveform; +import com.minres.scviewer.database.IWaveformDb; import com.minres.scviewer.database.IWaveformDbLoader; +import com.minres.scviewer.database.IWaveformEvent; import com.minres.scviewer.database.InputFormatException; -import com.minres.scviewer.database.SignalChange; // TODO: Auto-generated Javadoc /** @@ -29,7 +25,7 @@ import com.minres.scviewer.database.SignalChange; public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder { - private static final EventTime.Unit TIME_RES = EventTime.Unit.PS; + private static final Long TIME_RES = 1000L; // ps; private IWaveformDb db; @@ -37,7 +33,7 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder { private Stack moduleStack; /** The signals. */ - private List signals; + private List> signals; private long maxTime; @@ -54,6 +50,7 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder { /* (non-Javadoc) * @see com.minres.scviewer.database.ITrDb#load(java.io.File) */ + @SuppressWarnings("unchecked") @Override public boolean load(IWaveformDb db, File file) throws Exception { this.db=db; @@ -66,18 +63,26 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder { if (buffer[i] != x[i]) return false; - signals = new Vector(); + signals = new Vector>(); moduleStack= new Stack(); boolean res = new VCDFileParser(false).load(new FileInputStream(file), this); moduleStack=null; if(!res) throw new InputFormatException(); - EventTime lastTime=new EventTime(maxTime, TIME_RES); - for(IWaveform signal:signals){ - ISignalChange change = ((ISignal)signal).getSignalChanges().last(); - if(lastTime.compareTo(change.getTime())>0){ - ISignalChange lastChange = change.duplicate(); - ((SignalChange)lastChange).setTime(lastTime); - ((ISignal)signal).getSignalChanges().add(lastChange); + // calculate max time of database + for(IWaveform waveform:signals) + maxTime= Math.max(maxTime, ((ISignal)waveform).getEvents().lastKey()); + // extend signals to hav a last value set at max time + for(IWaveform waveform:signals){ + TreeMap events = ((VCDSignal)waveform).values; + if(events.lastKey())waveform).values.put(maxTime, + new VCDSignalChangeSingle(maxTime, ((ISignalChangeSingle)x).getValue())); + else + if(x instanceof ISignalChangeMulti) + ((VCDSignal)waveform).values.put(maxTime, + new VCDSignalChangeMulti(maxTime, ((ISignalChangeMulti)x).getValue())); } } return true; @@ -87,15 +92,15 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder { * @see com.minres.scviewer.database.ITrDb#getMaxTime() */ @Override - public EventTime getMaxTime() { - return new EventTime(maxTime, TIME_RES); + public Long getMaxTime() { + return maxTime* TIME_RES; } /* (non-Javadoc) * @see com.minres.scviewer.database.ITrDb#getAllWaves() */ @Override - public List getAllWaves() { + public List> getAllWaves() { return signals; } @@ -122,16 +127,17 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder { /* (non-Javadoc) * @see com.minres.scviewer.database.vcd.ITraceBuilder#newNet(java.lang.String, int, int) */ + @SuppressWarnings("unchecked") @Override public Integer newNet(String netName, int i, int width) { int id = signals.size(); - VCDSignal signal; + VCDSignal signal; if(width==1){ signal = i<0 ? new VCDSignal(db, id, netName) : - new VCDSignal(signals.get(i), id, netName); + new VCDSignal((VCDSignal)signals.get(i), id, netName); } else { signal = i<0 ? new VCDSignal(db, id, netName, width) : - new VCDSignal(signals.get(i), id, netName); + new VCDSignal((VCDSignal)signals.get(i), id, netName); }; signals.add(signal); return id; @@ -140,10 +146,9 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder { /* (non-Javadoc) * @see com.minres.scviewer.database.vcd.ITraceBuilder#getNetWidth(int) */ - @SuppressWarnings("unchecked") @Override public int getNetWidth(int intValue) { - VCDSignal signal = (VCDSignal) signals.get(intValue); + VCDSignal signal = (VCDSignal) signals.get(intValue); return signal.getWidth(); } @@ -152,17 +157,14 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder { */ @SuppressWarnings("unchecked") @Override - public void appendTransition(int intValue, long fCurrentTime, BitVector decodedValues) { - VCDSignal signal = (VCDSignal) signals.get(intValue); - EventTime time = new EventTime(fCurrentTime, TIME_RES); + public void appendTransition(int signalId, long fCurrentTime, BitVector decodedValues) { + VCDSignal signal = (VCDSignal) signals.get(signalId); + Long time = fCurrentTime* TIME_RES; if(signal.getWidth()==1){ - VCDSignalChangeSingle change = new VCDSignalChangeSingle(time, decodedValues.getValue()[0]); - ((VCDSignal)signal).addSignalChange(change); + ((VCDSignal)signal).values.put(time, new VCDSignalChangeSingle(time, decodedValues.getValue()[0])); } else { - VCDSignalChangeMulti change = new VCDSignalChangeMulti(time, decodedValues); - ((VCDSignal)signal).addSignalChange(change); + ((VCDSignal)signal).values.put(time, new VCDSignalChangeMulti(time, decodedValues)); } - maxTime= Math.max(maxTime, fCurrentTime); } } diff --git a/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignal.java b/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignal.java index 1ba95dc..59922cd 100644 --- a/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignal.java +++ b/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignal.java @@ -1,15 +1,18 @@ package com.minres.scviewer.database.vcd; -import java.util.NavigableSet; -import java.util.TreeSet; +import java.util.Collection; +import java.util.Map.Entry; +import java.util.NavigableMap; +import java.util.TreeMap; -import com.minres.scviewer.database.EventTime; +import com.google.common.collect.Ordering; +import com.google.common.collect.TreeMultimap; import com.minres.scviewer.database.HierNode; import com.minres.scviewer.database.ISignal; import com.minres.scviewer.database.ISignalChange; +import com.minres.scviewer.database.IWaveformEvent; import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveformDb; -import com.minres.scviewer.database.SignalChange; public class VCDSignal extends HierNode implements ISignal { @@ -23,7 +26,7 @@ public class VCDSignal extends HierNode implements ISig private IWaveformDb db; - TreeSet values; + TreeMap values; public VCDSignal(IWaveformDb db, String name) { this(db, 0, name, 1); @@ -39,16 +42,16 @@ public class VCDSignal extends HierNode implements ISig fullName=name; this.id=id; this.width=width; - this.values=new TreeSet(); + this.values=new TreeMap(); } @SuppressWarnings("unchecked") - public VCDSignal(IWaveform other, int id, String name) { + public VCDSignal(IWaveform other, int id, String name) { super(name); fullName=name; this.id=id; assert(other instanceof VCDSignal); - this.width=((VCDSignal)other).width; + this.width=((VCDSignal)other).width; this.values=((VCDSignal)other).values; this.db=other.getDb(); } @@ -82,29 +85,19 @@ public class VCDSignal extends HierNode implements ISig } public void addSignalChange(T change){ - values.add(change); + values.put(change.getTime(), change); } @Override - public NavigableSet getSignalChanges() { + public NavigableMap getEvents() { return values; } - @SuppressWarnings("unchecked") @Override - public T getSignalChangeByTime(EventTime time) { - return (T) values.floor(new SignalChange(time)); + public T getWaveformEventsAtTime(Long time) { + return values.get(time); } - @Override - public NavigableSet getSignalChangesByTimes(EventTime start, EventTime end) { - ISignalChange low = values.floor(new SignalChange(start)); - ISignalChange high = values.ceiling(new SignalChange(end)); - if(high!=null) - return values.subSet(low, true, high, true); - else - return values.subSet(low, true, values.last(), true); - } } diff --git a/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignalChangeMulti.java b/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignalChangeMulti.java index 41ec7ff..552a6f3 100644 --- a/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignalChangeMulti.java +++ b/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignalChangeMulti.java @@ -1,7 +1,6 @@ package com.minres.scviewer.database.vcd; import com.minres.scviewer.database.BitVector; -import com.minres.scviewer.database.EventTime; import com.minres.scviewer.database.ISignalChangeMulti; import com.minres.scviewer.database.SignalChange; @@ -9,11 +8,11 @@ public class VCDSignalChangeMulti extends SignalChange implements ISignalChangeM private BitVector value; - public VCDSignalChangeMulti(EventTime time) { + public VCDSignalChangeMulti(Long time) { super(time); } - public VCDSignalChangeMulti(EventTime time, BitVector decodedValues) { + public VCDSignalChangeMulti(Long time, BitVector decodedValues) { super(time); this.value=decodedValues; } diff --git a/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignalChangeSingle.java b/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignalChangeSingle.java index 568e79c..2027c4d 100644 --- a/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignalChangeSingle.java +++ b/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignalChangeSingle.java @@ -1,6 +1,5 @@ package com.minres.scviewer.database.vcd; -import com.minres.scviewer.database.EventTime; import com.minres.scviewer.database.ISignalChangeSingle; import com.minres.scviewer.database.SignalChange; @@ -8,7 +7,7 @@ public class VCDSignalChangeSingle extends SignalChange implements ISignalChange private char value; - public VCDSignalChangeSingle(EventTime time, char value) { + public VCDSignalChangeSingle(Long time, char value) { super(time); this.value=value; } diff --git a/com.minres.scviewer.database/.classpath b/com.minres.scviewer.database/.classpath index 098194c..16d067f 100644 --- a/com.minres.scviewer.database/.classpath +++ b/com.minres.scviewer.database/.classpath @@ -1,7 +1,7 @@ - + diff --git a/com.minres.scviewer.database/OSGI-INF/component.xml b/com.minres.scviewer.database/OSGI-INF/component.xml index 315ead5..d969643 100644 --- a/com.minres.scviewer.database/OSGI-INF/component.xml +++ b/com.minres.scviewer.database/OSGI-INF/component.xml @@ -2,4 +2,4 @@ - + \ No newline at end of file diff --git a/com.minres.scviewer.database/src/com/minres/scviewer/database/EventTime.java b/com.minres.scviewer.database/src/com/minres/scviewer/database/EventTime.java deleted file mode 100644 index e06f3bb..0000000 --- a/com.minres.scviewer.database/src/com/minres/scviewer/database/EventTime.java +++ /dev/null @@ -1,79 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2012 IT Just working. - * 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; - -public class EventTime implements Comparable{ - public enum Unit { - FS("fs"), PS("ps"), NS("ns"), US("us"), MS("ms"), SEC("s"); - - private String alternative; - private Unit(String alternative){ - this.alternative=alternative; - } - - public static Unit fromString(String text) { - if (text != null) - for (Unit b : Unit.values()) { - if (text.equalsIgnoreCase(b.name()) || text.equalsIgnoreCase(b.alternative)) return b; - } - return null; - } - } - - static final double[] scales = { - 1, - 1000.0, - 1000000.0, - 1000000000.0, - 1000000000000.0, - 1000000000000000.0}; - - public static final EventTime ZERO = new EventTime(0L); - - private long value; // unit is femto seconds - - public EventTime(Long value){ - this(value, Unit.FS); - } - - public EventTime(Long value, Unit scale){ - setValue(value, scale); - } - - public static double getScalingFactor(Unit scale){ - return scales[scale.ordinal()]; - } - - public long getValue(){ - return(value); - } - - public double getScaledValue(Unit scale){ - return value/scales[scale.ordinal()]; - } - - public void setValue(long value){ - this.value=value; - } - - public void setValue(long value, Unit scale){ - this.value=(long) (value*scales[scale.ordinal()]); - } - - public String toString(){ - return value/scales[Unit.NS.ordinal()] +"ns"; - } - - @Override - public int compareTo(EventTime other) { - return this.value extends IWaveform{ - public NavigableSet getSignalChanges(); +public interface ISignal extends IWaveform{ - public T getSignalChangeByTime(EventTime time); + public NavigableMap getEvents(); + + public T getWaveformEventsAtTime(Long time); - public NavigableSet getSignalChangesByTimes(EventTime start, EventTime end); } + diff --git a/com.minres.scviewer.database/src/com/minres/scviewer/database/ISignalChange.java b/com.minres.scviewer.database/src/com/minres/scviewer/database/ISignalChange.java index ef65642..3d5ea53 100644 --- a/com.minres.scviewer.database/src/com/minres/scviewer/database/ISignalChange.java +++ b/com.minres.scviewer.database/src/com/minres/scviewer/database/ISignalChange.java @@ -1,9 +1,5 @@ package com.minres.scviewer.database; -public interface ISignalChange extends Comparable{ - - public EventTime getTime(); - - public ISignalChange duplicate() throws CloneNotSupportedException; +public interface ISignalChange extends IWaveformEvent { } diff --git a/com.minres.scviewer.database/src/com/minres/scviewer/database/ITx.java b/com.minres.scviewer.database/src/com/minres/scviewer/database/ITx.java index 10d44dd..f01b1ae 100644 --- a/com.minres.scviewer.database/src/com/minres/scviewer/database/ITx.java +++ b/com.minres.scviewer.database/src/com/minres/scviewer/database/ITx.java @@ -17,13 +17,15 @@ public interface ITx extends Comparable{ public Long getId(); - public ITxStream getStream(); + public ITxStream getStream(); public ITxGenerator getGenerator(); - public EventTime getBeginTime(); + public Long getBeginTime(); - public EventTime getEndTime(); + public Long getEndTime(); + + public int getConcurrencyIndex(); public List getAttributes(); diff --git a/com.minres.scviewer.database/src/com/minres/scviewer/database/ITxEvent.java b/com.minres.scviewer.database/src/com/minres/scviewer/database/ITxEvent.java new file mode 100644 index 0000000..90bbd4a --- /dev/null +++ b/com.minres.scviewer.database/src/com/minres/scviewer/database/ITxEvent.java @@ -0,0 +1,9 @@ +package com.minres.scviewer.database; + +public interface ITxEvent extends IWaveformEvent { + enum Type {BEGIN, END}; + + public ITx getTransaction(); + + public Type getType(); +} diff --git a/com.minres.scviewer.database/src/com/minres/scviewer/database/ITxGenerator.java b/com.minres.scviewer.database/src/com/minres/scviewer/database/ITxGenerator.java index 293efc0..c835468 100644 --- a/com.minres.scviewer.database/src/com/minres/scviewer/database/ITxGenerator.java +++ b/com.minres.scviewer.database/src/com/minres/scviewer/database/ITxGenerator.java @@ -14,7 +14,7 @@ import java.util.List; public interface ITxGenerator { public Long getId(); - public ITxStream getStream(); + public ITxStream getStream(); public String getName(); public List getTransactions(); } diff --git a/com.minres.scviewer.database/src/com/minres/scviewer/database/ITxStream.java b/com.minres.scviewer.database/src/com/minres/scviewer/database/ITxStream.java index 480f156..ee916d7 100644 --- a/com.minres.scviewer.database/src/com/minres/scviewer/database/ITxStream.java +++ b/com.minres.scviewer.database/src/com/minres/scviewer/database/ITxStream.java @@ -10,15 +10,18 @@ *******************************************************************************/ package com.minres.scviewer.database; +import java.util.Collection; import java.util.List; -import java.util.NavigableSet; +import java.util.NavigableMap; -public interface ITxStream extends IWaveform { +public interface ITxStream extends IWaveform { public List getGenerators(); - public NavigableSet getTransactions(); + public int getMaxConcurrency(); - public ITx getTransactionById(long id); + public NavigableMap> getEvents(); + + public Collection getWaveformEventsAtTime(Long time); } diff --git a/com.minres.scviewer.database/src/com/minres/scviewer/database/IWaveform.java b/com.minres.scviewer.database/src/com/minres/scviewer/database/IWaveform.java index 9ab58cd..a71513a 100644 --- a/com.minres.scviewer.database/src/com/minres/scviewer/database/IWaveform.java +++ b/com.minres.scviewer.database/src/com/minres/scviewer/database/IWaveform.java @@ -1,6 +1,7 @@ package com.minres.scviewer.database; -public interface IWaveform extends IHierNode { + +public interface IWaveform extends IHierNode { public Long getId(); @@ -8,5 +9,4 @@ public interface IWaveform extends IHierNode { public IWaveformDb getDb(); - } diff --git a/com.minres.scviewer.database/src/com/minres/scviewer/database/IWaveformDb.java b/com.minres.scviewer.database/src/com/minres/scviewer/database/IWaveformDb.java index 91aae8d..6263077 100644 --- a/com.minres.scviewer.database/src/com/minres/scviewer/database/IWaveformDb.java +++ b/com.minres.scviewer.database/src/com/minres/scviewer/database/IWaveformDb.java @@ -16,11 +16,11 @@ import java.util.List; public interface IWaveformDb extends IHierNode { - public EventTime getMaxTime(); + public Long getMaxTime(); - public IWaveform getStreamByName(String name); + public IWaveform getStreamByName(String name); - public List getAllWaves(); + public List> getAllWaves(); public boolean load(File inp) throws Exception; diff --git a/com.minres.scviewer.database/src/com/minres/scviewer/database/IWaveformDbLoader.java b/com.minres.scviewer.database/src/com/minres/scviewer/database/IWaveformDbLoader.java index 256bb63..7429886 100644 --- a/com.minres.scviewer.database/src/com/minres/scviewer/database/IWaveformDbLoader.java +++ b/com.minres.scviewer.database/src/com/minres/scviewer/database/IWaveformDbLoader.java @@ -7,8 +7,8 @@ public interface IWaveformDbLoader { public boolean load(IWaveformDb db, File inp) throws Exception; - public EventTime getMaxTime(); + public Long getMaxTime(); - public List getAllWaves() ; + public List> getAllWaves() ; } diff --git a/com.minres.scviewer.database/src/com/minres/scviewer/database/IWaveformEvent.java b/com.minres.scviewer.database/src/com/minres/scviewer/database/IWaveformEvent.java new file mode 100644 index 0000000..3f78a98 --- /dev/null +++ b/com.minres.scviewer.database/src/com/minres/scviewer/database/IWaveformEvent.java @@ -0,0 +1,10 @@ +package com.minres.scviewer.database; + + +public interface IWaveformEvent extends Comparable{ + + public Long getTime(); + + public IWaveformEvent duplicate() throws CloneNotSupportedException; + +} diff --git a/com.minres.scviewer.database/src/com/minres/scviewer/database/SignalChange.java b/com.minres.scviewer.database/src/com/minres/scviewer/database/SignalChange.java index 3747253..78b0c68 100644 --- a/com.minres.scviewer.database/src/com/minres/scviewer/database/SignalChange.java +++ b/com.minres.scviewer.database/src/com/minres/scviewer/database/SignalChange.java @@ -1,36 +1,36 @@ package com.minres.scviewer.database; -public class SignalChange implements ISignalChange { +public class SignalChange implements IWaveformEvent { - EventTime time; + Long time; public SignalChange() { - time=EventTime.ZERO; + time=0L; } - public SignalChange(EventTime time) { + public SignalChange(Long time) { super(); this.time = time; } @Override - public int compareTo(ISignalChange o) { + public int compareTo(IWaveformEvent o) { return time.compareTo(o.getTime()); } @Override - public EventTime getTime() { + public Long getTime() { return time; } - public void setTime(EventTime time) { + public void setTime(Long time) { this.time = time; } @Override - public ISignalChange duplicate() throws CloneNotSupportedException { - return (ISignalChange) this.clone(); + public IWaveformEvent duplicate() throws CloneNotSupportedException { + return (IWaveformEvent) this.clone(); } } diff --git a/com.minres.scviewer.database/src/com/minres/scviewer/database/WaveformDb.java b/com.minres.scviewer.database/src/com/minres/scviewer/database/WaveformDb.java index c245992..9b3a9a3 100644 --- a/com.minres.scviewer.database/src/com/minres/scviewer/database/WaveformDb.java +++ b/com.minres.scviewer.database/src/com/minres/scviewer/database/WaveformDb.java @@ -14,9 +14,9 @@ public class WaveformDb extends HierNode implements IWaveformDb { private List childNodes; - private Map waveforms; + private Map> waveforms; - private EventTime maxTime; + private Long maxTime; public void bind(IWaveformDbLoader loader){ @@ -34,31 +34,35 @@ public class WaveformDb extends HierNode implements IWaveformDb { public WaveformDb() { super(); - waveforms = new HashMap(); - maxTime=EventTime.ZERO; + waveforms = new HashMap>(); + maxTime=0L; } @Override - public EventTime getMaxTime() { + public Long getMaxTime() { return maxTime; } @Override - public IWaveform getStreamByName(String name) { + public IWaveform getStreamByName(String name) { return waveforms.get(name); } @Override - public List getAllWaves() { - return new ArrayList(waveforms.values()); + public List> getAllWaves() { + return new ArrayList>(waveforms.values()); } @Override public boolean load(File inp) throws Exception { for(IWaveformDbLoader loader:loaders){ if(loader.load(this, inp)){ - for(IWaveform w:loader.getAllWaves()) + for(IWaveform w:loader.getAllWaves()){ waveforms.put(w.getFullName(),w); + } + if(loader.getMaxTime()>maxTime){ + maxTime=loader.getMaxTime(); + } buildHierarchyNodes() ; if(name==null) name=getFileBasename(inp.getName()); pcs.firePropertyChange("WAVEFORMS", null, waveforms); @@ -86,7 +90,7 @@ public class WaveformDb extends HierNode implements IWaveformDb { private void buildHierarchyNodes() throws InputFormatException{ childNodes= new ArrayList(); - for(IWaveform stream:getAllWaves()){ + for(IWaveform stream:getAllWaves()){ updateMaxTime(stream); String[] hier = stream.getFullName().split("\\."); IHierNode node = this; @@ -126,14 +130,13 @@ public class WaveformDb extends HierNode implements IWaveformDb { } } - private void updateMaxTime(IWaveform stream) { - EventTime last=null; - if(stream instanceof ITxStream){ - last=((ITxStream)stream).getTransactions().last().getEndTime(); - } else if(stream instanceof ISignal){ - last=((ISignal)stream).getSignalChanges().last().getTime(); - } - if(last.getValue()>maxTime.getValue()) + private void updateMaxTime(IWaveform waveform) { + Long last=0L; + if(waveform instanceof ITxStream) + last=((ITxStream)waveform).getEvents().lastEntry().getKey(); + else if(waveform instanceof ISignal) + last=((ISignal)waveform).getEvents().lastEntry().getKey(); + if(last>maxTime) maxTime=last; } diff --git a/com.minres.scviewer.ui/.classpath b/com.minres.scviewer.ui/.classpath index cdd848a..f653dd5 100644 --- a/com.minres.scviewer.ui/.classpath +++ b/com.minres.scviewer.ui/.classpath @@ -1,8 +1,8 @@ - + diff --git a/com.minres.scviewer.ui/.settings/org.eclipse.core.resources.prefs b/com.minres.scviewer.ui/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..2cfbe0c --- /dev/null +++ b/com.minres.scviewer.ui/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding//src/com/minres/scviewer/ui/swt/TxDisplay.java=UTF-8 diff --git a/com.minres.scviewer.ui/.settings/org.eclipse.jdt.core.prefs b/com.minres.scviewer.ui/.settings/org.eclipse.jdt.core.prefs index f42de36..d17b672 100644 --- a/com.minres.scviewer.ui/.settings/org.eclipse.jdt.core.prefs +++ b/com.minres.scviewer.ui/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,12 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.source=1.7 diff --git a/com.minres.scviewer.ui/META-INF/MANIFEST.MF b/com.minres.scviewer.ui/META-INF/MANIFEST.MF index 2f87e75..ed456e0 100644 --- a/com.minres.scviewer.ui/META-INF/MANIFEST.MF +++ b/com.minres.scviewer.ui/META-INF/MANIFEST.MF @@ -15,7 +15,8 @@ Require-Bundle: com.minres.scviewer.database;bundle-version="1.0.0", org.eclipse.ui.views.properties.tabbed, org.eclipse.swt, org.eclipse.osgi, - org.eclipse.core.expressions;bundle-version="3.4.600" + org.eclipse.core.expressions;bundle-version="3.4.600", + org.eclipse.jface Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Bundle-ActivationPolicy: lazy Bundle-ClassPath: ., diff --git a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/TxEditorPart.java b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/TxEditorPart.java index ce7b6b4..0ca7719 100644 --- a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/TxEditorPart.java +++ b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/TxEditorPart.java @@ -10,7 +10,12 @@ *******************************************************************************/ package com.minres.scviewer.ui; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -18,15 +23,19 @@ import java.util.regex.Pattern; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.graphics.Color; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.IFileEditorInput; +import org.eclipse.ui.IWorkbench; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.ide.FileStoreEditorInput; import org.eclipse.ui.part.EditorPart; +import org.eclipse.ui.progress.IProgressService; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; import org.eclipse.ui.views.properties.IPropertySheetPage; import org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor; @@ -50,7 +59,7 @@ public class TxEditorPart extends EditorPart implements ITabbedPropertySheetPage public static final String WAVE_ACTION_ID = "com.minres.scviewer.ui.action.AddToWave"; private TxDisplay txDisplay; - + /** This is the root of the editor's model. */ private IWaveformDb database; @@ -66,20 +75,35 @@ public class TxEditorPart extends EditorPart implements ITabbedPropertySheetPage @Override public void createPartControl(Composite parent) { myParent=parent; + database=new WaveformDb(); txDisplay = new TxDisplay(parent); - if(database!=null) database.addPropertyChangeListener(txDisplay); + txDisplay.setMaxTime(0); getSite().setSelectionProvider(txDisplay); - if(getEditorInput()!=null && ((TxEditorInput) getEditorInput()).getStreamNames().size()>0 && database!=null){ - if(MessageDialog.openConfirm(parent.getShell(), "Confirm", "Do you want the restore last state of the wave form?")) - for(String streamName:((TxEditorInput) getEditorInput()).getStreamNames()){ - IWaveform stream = database.getStreamByName(streamName); - if(stream!=null) - txDisplay.addStream(stream); + new Thread(new Runnable() { + @Override + public void run() { + try { + loadDatabases(); + } catch (InvocationTargetException | IOException | InterruptedException e) { + handleLoadException(e); } - } + } + }).run(); + database.addPropertyChangeListener(new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if("WAVEFORMS".equals(evt.getPropertyName())) { + myParent.getDisplay().syncExec(new Runnable() { + @Override + public void run() { + txDisplay.setMaxTime(database.getMaxTime()); + } + }); + } + } + }); } - /* * (non-Javadoc) * @@ -87,64 +111,107 @@ public class TxEditorPart extends EditorPart implements ITabbedPropertySheetPage */ protected void setInput(IEditorInput input) { super.setInput(input); - try { - if(input instanceof IFileEditorInput){ - if(!(input instanceof TxEditorInput)) - super.setInput(new TxEditorInput(((IFileEditorInput)input).getFile())); - IPath location = ((IFileEditorInput) input).getFile().getLocation(); - if (location != null) loadDatabases(location.toFile()); - } else if(input instanceof FileStoreEditorInput){ - File file=new File(((FileStoreEditorInput) input).getURI().getPath()); - loadDatabases(file); - } - } catch (Exception e) { - handleLoadException(e); - } - if(database!=null) setPartName(database.getName()); + if(input instanceof IFileEditorInput && !(input instanceof TxEditorInput)) + super.setInput(new TxEditorInput(((IFileEditorInput)input).getFile())); + setPartName(input.getName()); } - protected void loadDatabases(File file) throws Exception { - database=new WaveformDb(); - if(txDisplay !=null) database.addPropertyChangeListener(txDisplay); - if(database.load(file)){ + protected void loadDatabases() throws IOException, InvocationTargetException, InterruptedException { + IWorkbench wb = PlatformUI.getWorkbench(); + IProgressService ps = wb.getProgressService(); + IEditorInput input = getEditorInput(); + File file=null; + ArrayList filesToLoad=new ArrayList(); + if(input instanceof IFileEditorInput){ + file = ((IFileEditorInput) input).getFile().getLocation().toFile(); + } else if(input instanceof FileStoreEditorInput){ + file=new File(((FileStoreEditorInput) input).getURI().getPath()); + } + if(file.exists()){ + filesToLoad.add(file); String ext = getFileExtension(file.getName()); if("vcd".equals(ext.toLowerCase())){ - File txFile = new File(renameFileExtension(file.getCanonicalPath(), "txdb")); - if(txFile.exists() && database.load(txFile)) return; - txFile = new File(renameFileExtension(file.getCanonicalPath(), "txlog")); - if(txFile.exists()) database.load(txFile); + if(askIfToLoad(new File(renameFileExtension(file.getCanonicalPath(), "txdb")))) + filesToLoad.add(new File(renameFileExtension(file.getCanonicalPath(), "txdb"))); + else if(askIfToLoad(new File(renameFileExtension(file.getCanonicalPath(), "txlog")))) + filesToLoad.add(new File(renameFileExtension(file.getCanonicalPath(), "txlog"))); } else if("txdb".equals(ext.toLowerCase()) || "txlog".equals(ext.toLowerCase())){ - File txFile = new File(renameFileExtension(file.getCanonicalPath(), "vcd")); - if(txFile.exists()) database.load(txFile); + if(askIfToLoad(new File(renameFileExtension(file.getCanonicalPath(), "vcd")))) + filesToLoad.add(new File(renameFileExtension(file.getCanonicalPath(), "vcd"))); + } + + } + final File[] files=filesToLoad.toArray(new File[filesToLoad.size()]); + ps.busyCursorWhile(new IRunnableWithProgress() { + public void run(IProgressMonitor pm) throws InvocationTargetException { + pm.beginTask("Loading database "+files[0].getName(), files.length); + try { + database.load(files[0]); + database.addPropertyChangeListener(txDisplay); + pm.worked(1); + if(pm.isCanceled()) return; + if(files.length==2){ + database.load(files[1]); + pm.worked(1); + } + myParent.getDisplay().syncExec(new Runnable() { + @Override + public void run() { + updateTxDisplay(); + } + }); + } catch (Exception e) { + database=null; + throw new InvocationTargetException(e); + } + pm.done(); + } + }); + } + + protected boolean askIfToLoad(File txFile) { + if(txFile.exists() && + MessageDialog.openQuestion(myParent.getDisplay().getActiveShell(), "Database open", + "Would you like to open the adjacent database "+txFile.getName()+" as well?")){ + return true; + } + return false; + } + + protected void updateTxDisplay() { + txDisplay.setMaxTime(database.getMaxTime()); + if(TxEditorPart.this.getEditorInput() instanceof TxEditorInput && + ((TxEditorInput) TxEditorPart.this.getEditorInput()).getStreamNames().size()>0){ + for(String streamName:((TxEditorInput) TxEditorPart.this.getEditorInput()).getStreamNames()){ + IWaveform stream = database.getStreamByName(streamName); + if(stream!=null) + txDisplay.getStreamList().add(stream); } - } else { - MessageDialog.openError(PlatformUI.getWorkbench().getDisplay().getActiveShell(), - "Error loading database", "Could not find an usable and applicable database loader implementation"); - database=null; } } - + protected static String renameFileExtension(String source, String newExt) { - String target; - String currentExt = getFileExtension(source); - if (currentExt.equals("")){ - target=source+"."+newExt; - } else { - target=source.replaceFirst(Pattern.quote("."+currentExt)+"$", Matcher.quoteReplacement("."+newExt)); - } - return target; - } + String target; + String currentExt = getFileExtension(source); + if (currentExt.equals("")){ + target=source+"."+newExt; + } else { + target=source.replaceFirst(Pattern.quote("."+currentExt)+"$", Matcher.quoteReplacement("."+newExt)); + } + return target; + } protected static String getFileExtension(String f) { - String ext = ""; - int i = f.lastIndexOf('.'); - if (i > 0 && i < f.length() - 1) { - ext = f.substring(i + 1); - } - return ext; - } - + String ext = ""; + int i = f.lastIndexOf('.'); + if (i > 0 && i < f.length() - 1) { + ext = f.substring(i + 1); + } + return ext; + } + private void handleLoadException(Exception e) { + e.printStackTrace(); MessageDialog.openError(PlatformUI.getWorkbench().getDisplay().getActiveShell(), "Error loading database", e.getMessage()); database = null; @@ -169,7 +236,7 @@ public class TxEditorPart extends EditorPart implements ITabbedPropertySheetPage if (type == IContentOutlinePage.class) // outline page return new TxOutlinePage(this); else if (type == IPropertySheetPage.class) // use tabbed property sheet instead of standard one - return new TabbedPropertySheetPage(this); + return new TabbedPropertySheetPage(this); return super.getAdapter(type); } @@ -202,12 +269,12 @@ public class TxEditorPart extends EditorPart implements ITabbedPropertySheetPage public void addStreamToList(IWaveform obj){ if(getEditorInput() instanceof TxEditorInput && !((TxEditorInput) getEditorInput()).getStreamNames().contains(obj.getFullName())){ ((TxEditorInput) getEditorInput()).getStreamNames().add(obj.getFullName()); - txDisplay.addStream(obj); + txDisplay.getStreamList().add(obj); } else - txDisplay.addStream(obj); - + txDisplay.getStreamList().add(obj); + } - + public void addStreamsToList(IWaveform[] iWaveforms){ for(IWaveform stream:iWaveforms) addStreamToList(stream); @@ -216,16 +283,16 @@ public class TxEditorPart extends EditorPart implements ITabbedPropertySheetPage public void removeStreamFromList(IWaveform obj){ if(getEditorInput() instanceof TxEditorInput && ((TxEditorInput) getEditorInput()).getStreamNames().contains(obj.getFullName())){ ((TxEditorInput) getEditorInput()).getStreamNames().remove(obj.getFullName()); - txDisplay.removeStream(obj); + txDisplay.getStreamList().remove(obj); } else - txDisplay.removeStream(obj); + txDisplay.getStreamList().remove(obj); } - + public void removeStreamsFromList(IWaveform[] iWaveforms){ for(IWaveform stream:iWaveforms) removeStreamFromList(stream); } - + public List getStreamList(){ return txDisplay.getStreamList(); } @@ -238,7 +305,7 @@ public class TxEditorPart extends EditorPart implements ITabbedPropertySheetPage } }); } - + @Override public String getContributorId() { return getSite().getId(); diff --git a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/IPainter.java b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/IPainter.java new file mode 100644 index 0000000..15696c3 --- /dev/null +++ b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/IPainter.java @@ -0,0 +1,11 @@ +package com.minres.scviewer.ui.swt; + +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Rectangle; + +public interface IPainter { + + void paintArea(GC gc,Rectangle area); + +} \ No newline at end of file diff --git a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/IWaveformPainter.java b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/IWaveformPainter.java new file mode 100644 index 0000000..005f0b4 --- /dev/null +++ b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/IWaveformPainter.java @@ -0,0 +1,8 @@ +package com.minres.scviewer.ui.swt; + + +public interface IWaveformPainter extends IPainter { + + public int getMinHeight(); + +} \ No newline at end of file diff --git a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/IWaveformWidget.java b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/IWaveformWidget.java deleted file mode 100644 index 3d9caf3..0000000 --- a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/IWaveformWidget.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.minres.scviewer.ui.swt; - -public interface IWaveformWidget { - - Transaction highlight(Object sel); - -} diff --git a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/ObservableList.java b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/ObservableList.java new file mode 100644 index 0000000..ebeba34 --- /dev/null +++ b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/ObservableList.java @@ -0,0 +1,530 @@ +package com.minres.scviewer.ui.swt; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; + +public class ObservableList implements List { + private List delegate; + private PropertyChangeSupport pcs; + public static final String SIZE_PROPERTY = "size"; + public static final String CONTENT_PROPERTY = "content"; + + public ObservableList() { + this(new ArrayList()); + } + + public ObservableList(List delegate) { + this.delegate = delegate; + this.pcs = new PropertyChangeSupport(this); + } + + public List getContent() { + return Collections.unmodifiableList(this.delegate); + } + + protected List getDelegateList() { + return this.delegate; + } + + protected void fireElementAddedEvent(int index, Object element) { + fireElementEvent(new ElementAddedEvent(this, element, index)); + } + + protected void fireMultiElementAddedEvent(int index, List values) { + fireElementEvent(new MultiElementAddedEvent(this, index, values)); + } + + protected void fireElementClearedEvent(List values) { + fireElementEvent(new ElementClearedEvent(this, values)); + } + + protected void fireElementRemovedEvent(int index, Object element) { + fireElementEvent(new ElementRemovedEvent(this, element, index)); + } + + protected void fireMultiElementRemovedEvent(List values) { + fireElementEvent(new MultiElementRemovedEvent(this, values)); + } + + protected void fireElementUpdatedEvent(int index, Object oldValue, Object newValue) { + fireElementEvent(new ElementUpdatedEvent(this, oldValue, newValue, index)); + } + + protected void fireElementEvent(ElementEvent event) { + this.pcs.firePropertyChange(event); + } + + protected void fireSizeChangedEvent(int oldValue, int newValue) { + this.pcs.firePropertyChange(new PropertyChangeEvent(this, "size", Integer.valueOf(oldValue), Integer + .valueOf(newValue))); + } + + public void add(int index, E element) { + int oldSize = size(); + this.delegate.add(index, element); + fireElementAddedEvent(index, element); + fireSizeChangedEvent(oldSize, size()); + } + + public boolean add(E o) { + int oldSize = size(); + boolean success = this.delegate.add(o); + if (success) { + fireElementAddedEvent(size() - 1, o); + fireSizeChangedEvent(oldSize, size()); + } + return success; + } + + public boolean addAll(Collection c) { + int oldSize = size(); + int index = size() - 1; + index = (index < 0) ? 0 : index; + + boolean success = this.delegate.addAll(c); + if ((success) && (c != null)) { + List values = new ArrayList(); + for (Iterator i = c.iterator(); i.hasNext();) { + values.add(i.next()); + } + if (values.size() > 0) { + fireMultiElementAddedEvent(index, values); + fireSizeChangedEvent(oldSize, size()); + } + } + + return success; + } + + public boolean addAll(int index, Collection c) { + int oldSize = size(); + boolean success = this.delegate.addAll(index, c); + + if ((success) && (c != null)) { + List values = new ArrayList(); + for (Iterator i = c.iterator(); i.hasNext();) { + values.add(i.next()); + } + if (values.size() > 0) { + fireMultiElementAddedEvent(index, values); + fireSizeChangedEvent(oldSize, size()); + } + } + + return success; + } + + public void clear() { + int oldSize = size(); + List values = new ArrayList(); + values.addAll(this.delegate); + this.delegate.clear(); + if (!(values.isEmpty())) { + fireElementClearedEvent(values); + } + fireSizeChangedEvent(oldSize, size()); + } + + public boolean contains(Object o) { + return this.delegate.contains(o); + } + + public boolean containsAll(Collection c) { + return this.delegate.containsAll(c); + } + + public boolean equals(Object o) { + return this.delegate.equals(o); + } + + public E get(int index) { + return this.delegate.get(index); + } + + public int hashCode() { + return this.delegate.hashCode(); + } + + public int indexOf(Object o) { + return this.delegate.indexOf(o); + } + + public boolean isEmpty() { + return this.delegate.isEmpty(); + } + + public Iterator iterator() { + return new ObservableIterator(this.delegate.iterator()); + } + + public int lastIndexOf(Object o) { + return this.delegate.lastIndexOf(o); + } + + public ListIterator listIterator() { + return new ObservableListIterator(this.delegate.listIterator(), 0); + } + + public ListIterator listIterator(int index) { + return new ObservableListIterator(this.delegate.listIterator(index), index); + } + + public E remove(int index) { + int oldSize = size(); + E element = this.delegate.remove(index); + fireElementRemovedEvent(index, element); + fireSizeChangedEvent(oldSize, size()); + return element; + } + + public boolean remove(Object o) { + int index = this.delegate.indexOf(o); + if(index<0) return false; + return remove(index)!=null; + } + + public boolean remove(Collection o) { + int oldSize = size(); + int index = this.delegate.indexOf(o); + boolean success = this.delegate.remove(o); + if (success) { + fireElementRemovedEvent(index, o); + fireSizeChangedEvent(oldSize, size()); + } + return success; + } + public boolean removeAll(Collection c) { + if (c == null) { + return false; + } + + List values = new ArrayList(); + if (c != null) { + for (Iterator i = c.iterator(); i.hasNext();) { + E element = (E) i.next(); + if (this.delegate.contains(element)) { + values.add(element); + } + } + } + + int oldSize = size(); + boolean success = this.delegate.removeAll(c); + if ((success) && (!(values.isEmpty()))) { + fireMultiElementRemovedEvent(values); + fireSizeChangedEvent(oldSize, size()); + } + + return success; + } + + public boolean retainAll(Collection c) { + if (c == null) { + return false; + } + + List values = new ArrayList(); + Iterator i; + if (c != null) { + for (i = this.delegate.iterator(); i.hasNext();) { + E element = i.next(); + if (!(c.contains(element))) { + values.add(element); + } + } + } + + int oldSize = size(); + boolean success = this.delegate.retainAll(c); + if ((success) && (!(values.isEmpty()))) { + fireMultiElementRemovedEvent(values); + fireSizeChangedEvent(oldSize, size()); + } + + return success; + } + + public E set(int index, E o) { + E oldValue = this.delegate.set(index, o); + fireElementUpdatedEvent(index, oldValue, o); + return oldValue; + } + + public int size() { + return this.delegate.size(); + } + + public int getSize() { + return size(); + } + + public List subList(int fromIndex, int toIndex) { + return this.delegate.subList(fromIndex, toIndex); + } + + public Object[] toArray() { + return this.delegate.toArray(); + } + + public T[] toArray(T[] a){ + return this.delegate.toArray(a); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + this.pcs.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + this.pcs.addPropertyChangeListener(propertyName, listener); + } + + public PropertyChangeListener[] getPropertyChangeListeners() { + return this.pcs.getPropertyChangeListeners(); + } + + public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) { + return this.pcs.getPropertyChangeListeners(propertyName); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + this.pcs.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + this.pcs.removePropertyChangeListener(propertyName, listener); + } + + public boolean hasListeners(String propertyName) { + return this.pcs.hasListeners(propertyName); + } + + public static class MultiElementRemovedEvent extends ObservableList.ElementEvent { + /** + * + */ + private static final long serialVersionUID = 7819626246672640599L; + + private List values = new ArrayList(); + + public MultiElementRemovedEvent(Object source, List values) { + super(source, ObservableList.ChangeType.oldValue, ObservableList.ChangeType.newValue, 0, + ObservableList.ChangeType.MULTI_REMOVE); + if (values != null) + this.values.addAll(values); + } + + public List getValues() { + return Collections.unmodifiableList(this.values); + } + } + + public static class MultiElementAddedEvent extends ObservableList.ElementEvent { + /** + * + */ + private static final long serialVersionUID = -116376519087713082L; + private List values = new ArrayList(); + + public MultiElementAddedEvent(Object source, int index, List values) { + super(source, ObservableList.ChangeType.oldValue, ObservableList.ChangeType.newValue, index, + ObservableList.ChangeType.MULTI_ADD); + if (values != null) + this.values.addAll(values); + } + + public List getValues() { + return Collections.unmodifiableList(this.values); + } + } + + public static class ElementClearedEvent extends ObservableList.ElementEvent { + /** + * + */ + private static final long serialVersionUID = -8654027608903811577L; + private List values = new ArrayList(); + + public ElementClearedEvent(Object source, List values) { + super(source, ObservableList.ChangeType.oldValue, ObservableList.ChangeType.newValue, 0, + ObservableList.ChangeType.CLEARED); + if (values != null) + this.values.addAll(values); + } + + public List getValues() { + return Collections.unmodifiableList(this.values); + } + } + + public static class ElementRemovedEvent extends ObservableList.ElementEvent { + /** + * + */ + private static final long serialVersionUID = -6664217547528652003L; + + public ElementRemovedEvent(Object source, Object value, int index) { + super(source, value, null, index, ObservableList.ChangeType.REMOVED); + } + } + + public static class ElementUpdatedEvent extends ObservableList.ElementEvent { + /** + * + */ + private static final long serialVersionUID = 7793549621724991011L; + + public ElementUpdatedEvent(Object source, Object oldValue, Object newValue, int index) { + super(source, oldValue, newValue, index, ObservableList.ChangeType.UPDATED); + } + } + + public static class ElementAddedEvent extends ObservableList.ElementEvent { + /** + * + */ + private static final long serialVersionUID = -6990071468319043554L; + + public ElementAddedEvent(Object source, Object newValue, int index) { + super(source, null, newValue, index, ObservableList.ChangeType.ADDED); + } + } + + public static abstract class ElementEvent extends PropertyChangeEvent { + /** + * + */ + private static final long serialVersionUID = 964946867437728530L; + private final ObservableList.ChangeType type; + private final int index; + + public ElementEvent(Object source, Object oldValue, Object newValue, int index, ObservableList.ChangeType type) { + super(source, "content", oldValue, newValue); + this.type = type; + this.index = index; + } + + public int getIndex() { + return this.index; + } + + public int getType() { + return this.type.ordinal(); + } + + public ObservableList.ChangeType getChangeType() { + return this.type; + } + + public String getTypeAsString() { + return this.type.name().toUpperCase(); + } + } + + public static enum ChangeType { + ADDED, UPDATED, REMOVED, CLEARED, MULTI_ADD, MULTI_REMOVE, NONE; + + public static final Object oldValue; + public static final Object newValue; + + public static ChangeType resolve(int ordinal) { + switch (ordinal) { + case 0: + return ADDED; + case 2: + return REMOVED; + case 3: + return CLEARED; + case 4: + return MULTI_ADD; + case 5: + return MULTI_REMOVE; + case 6: + return NONE; + case 1: + } + return UPDATED; + } + + static { + oldValue = new Object(); + newValue = new Object(); + } + } + + protected class ObservableListIterator extends ObservableList.ObservableIterator implements ListIterator { + + public ObservableListIterator(ListIterator listIterator, int index) { + super(listIterator); + this.cursor = (index - 1); + } + + public ListIterator getListIterator() { + return ((ListIterator) getDelegate()); + } + + public void add(E o) { + ObservableList.this.add(o); + this.cursor += 1; + } + + public boolean hasPrevious() { + return getListIterator().hasPrevious(); + } + + public int nextIndex() { + return getListIterator().nextIndex(); + } + + public E previous() { + return getListIterator().previous(); + } + + public int previousIndex() { + return getListIterator().previousIndex(); + } + + public void set(E o) { + ObservableList.this.set(this.cursor, o); + } + } + + protected class ObservableIterator implements Iterator { + + private Iterator iterDelegate; + + protected int cursor = -1; + + public ObservableIterator(Iterator paramIterator) { + this.iterDelegate = paramIterator; + } + + public Iterator getDelegate() { + return this.iterDelegate; + } + + public boolean hasNext() { + return this.iterDelegate.hasNext(); + } + + public E next() { + this.cursor += 1; + return this.iterDelegate.next(); + } + + public void remove() { + int oldSize = ObservableList.this.size(); + Object element = ObservableList.this.get(this.cursor); + this.iterDelegate.remove(); + ObservableList.this.fireElementRemovedEvent(this.cursor, element); + ObservableList.this.fireSizeChangedEvent(oldSize, ObservableList.this.size()); + this.cursor -= 1; + } + } +} \ No newline at end of file diff --git a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/Ruler.java b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/Ruler.java index da81786..9464f26 100644 --- a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/Ruler.java +++ b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/Ruler.java @@ -16,6 +16,9 @@ import com.minres.scviewer.ui.TxEditorPlugin; public class Ruler extends Composite { static final int height = 20; + static final int tickY = 15; + static final int majorTickY = 5; + static final int rulerTickMinor = 10; static final int rulerTickMajor = 100; @@ -25,6 +28,8 @@ public class Ruler extends Composite { private TxEditorPlugin plugin; private Color headerBgColor; private Color headerFgColor; + private int bottom; + private int baselineY; Ruler(Composite parent, int style, int lenght) { super(parent, style | SWT.DOUBLE_BUFFERED); @@ -46,6 +51,9 @@ public class Ruler extends Composite { Ruler.this.paintControl(e); } }); + + bottom=height - 2; + baselineY=height - 1; } public int getLength() { @@ -66,23 +74,22 @@ public class Ruler extends Composite { int startMinorIncr = start; int modulo = start % rulerTickMinor; startMinorIncr+=rulerTickMinor-modulo; - int bottom=height - 2; int end=start+e.width; gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); gc.fillRectangle(new Rectangle(e.x, e.y, e.width, height)); gc.setBackground(headerBgColor); - gc.fillRectangle(new Rectangle(e.x, e.y, e.width, height - 1)); + gc.fillRectangle(new Rectangle(e.x, e.y, e.width, baselineY)); gc.setForeground(headerFgColor); gc.drawLine(0, bottom, e.width, bottom); for (int tick = startMinorIncr; tick < end; tick += rulerTickMinor) { int x0 = tick-start; if ((tick % rulerTickMajor) == 0) { - gc.drawLine(x0, 10, x0, bottom); gc.drawText(Integer.toString(tick), x0, 0); + gc.drawLine(x0, majorTickY, x0, bottom); } else { - gc.drawLine(x0, 15, x0, bottom); + gc.drawLine(x0, tickY, x0, bottom); } } } diff --git a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/SignalPainter.java b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/SignalPainter.java new file mode 100644 index 0000000..69f27b9 --- /dev/null +++ b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/SignalPainter.java @@ -0,0 +1,131 @@ +package com.minres.scviewer.ui.swt; + +import java.util.Map.Entry; +import java.util.NavigableMap; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Rectangle; + +import com.minres.scviewer.database.ISignal; +import com.minres.scviewer.database.ISignalChange; +import com.minres.scviewer.database.IWaveformEvent; +import com.minres.scviewer.database.ISignalChangeMulti; +import com.minres.scviewer.database.ISignalChangeSingle; + +class SignalPainter implements IWaveformPainter { + + /** + * + */ + private final WaveformCanvas waveCanvas; + private ISignal signal; + private int height; + private boolean even; + + public SignalPainter(WaveformCanvas txDisplay, boolean even, int height, ISignal signal) { + this.waveCanvas = txDisplay; + this.signal=signal; + this.height=height; + this.even=even; + } + + public void paintArea(GC gc, Rectangle area) { + gc.setBackground(this.waveCanvas.colors[even?WaveformCanvas.Colors.TRACK_BG_EVEN.ordinal():WaveformCanvas.Colors.TRACK_BG_ODD.ordinal()]); + gc.setFillRule(SWT.FILL_EVEN_ODD); + gc.fillRectangle(area); + Entry firstChange=signal.getEvents().floorEntry(area.x*this.waveCanvas.getScaleFactor()); + Entry lastTx=signal.getEvents().ceilingEntry((area.x+area.width)*this.waveCanvas.getScaleFactor()); + if(firstChange==null){ + if(lastTx==null) return; + firstChange = signal.getEvents().firstEntry(); + } else if(lastTx==null){ + lastTx=signal.getEvents().lastEntry(); + } + gc.setForeground(this.waveCanvas.colors[WaveformCanvas.Colors.LINE.ordinal()]); + gc.setLineStyle(SWT.LINE_SOLID); + gc.setLineWidth(1); + Entry left=firstChange; + if(left.getValue() instanceof ISignalChangeSingle){ + NavigableMap entries=signal.getEvents().subMap(firstChange.getKey(), false, lastTx.getKey(), true); + for(Entry right:entries.entrySet()){ + int yOffset = this.waveCanvas.getTrackHeight()/2; + Color color = this.waveCanvas.colors[WaveformCanvas.Colors.SIGNALX.ordinal()]; + switch(((ISignalChangeSingle) left.getValue()).getValue()){ + case '1': + color=this.waveCanvas.colors[WaveformCanvas.Colors.SIGNAL1.ordinal()]; + yOffset = this.waveCanvas.getTrackHeight()/5; + break; + case '0': + color=this.waveCanvas.colors[WaveformCanvas.Colors.SIGNAL0.ordinal()]; + yOffset = 4*this.waveCanvas.getTrackHeight()/5; + break; + case 'Z': + color=this.waveCanvas.colors[WaveformCanvas.Colors.SIGNALZ.ordinal()]; + break; + default: + } + yOffset+=area.y; + gc.setForeground(color); + int xEnd= (int)(right.getKey()/this.waveCanvas.getScaleFactor()); + gc.drawLine((int)(left.getKey()/this.waveCanvas.getScaleFactor()), yOffset, xEnd, yOffset); + int yNext = this.waveCanvas.getTrackHeight()/2; + switch(((ISignalChangeSingle) right.getValue()).getValue()){ + case '1': + yNext = this.waveCanvas.getTrackHeight()/5+area.y; + break; + case '0': + yNext = 4*this.waveCanvas.getTrackHeight()/5+area.y; + break; + default: + } + gc.drawLine(xEnd, yOffset, xEnd, yNext); + left=right; + } + } else if(left.getValue() instanceof ISignalChangeMulti){ + NavigableMap entries=signal.getEvents().subMap(firstChange.getKey(), false, lastTx.getKey(), true); + for(Entry right:entries.entrySet()){ + int yOffsetT = this.waveCanvas.getTrackHeight()/5+area.y; + int yOffsetM = this.waveCanvas.getTrackHeight()/2+area.y; + int yOffsetB = 4*this.waveCanvas.getTrackHeight()/5+area.y; + Color colorBorder = this.waveCanvas.colors[WaveformCanvas.Colors.SIGNAL0.ordinal()]; + ISignalChangeMulti last = (ISignalChangeMulti) left.getValue(); + if(last.getValue().toString().contains("X")){ + colorBorder=this.waveCanvas.colors[WaveformCanvas.Colors.SIGNALX.ordinal()]; + }else if(last.getValue().toString().contains("Z")){ + colorBorder=this.waveCanvas.colors[WaveformCanvas.Colors.SIGNALZ.ordinal()]; + } + int beginTime= (int)(left.getKey()/this.waveCanvas.getScaleFactor()); + int endTime= (int)(right.getKey()/this.waveCanvas.getScaleFactor()); + int[] points = { + beginTime,yOffsetM, + beginTime+1,yOffsetT, + endTime-1,yOffsetT, + endTime,yOffsetM, + endTime-1,yOffsetB, + beginTime+1,yOffsetB + }; + gc.setForeground(colorBorder); + gc.drawPolygon(points); + gc.setForeground(this.waveCanvas.colors[WaveformCanvas.Colors.SIGNAL_TEXT.ordinal()]); + int size = gc.getDevice().getDPI().y * gc.getFont().getFontData()[0].getHeight()/72; + if(beginTime6) { + Rectangle old = gc.getClipping(); + gc.setClipping(beginTime+3, yOffsetT, endTime-beginTime-5, yOffsetB-yOffsetT); + gc.drawText("h'"+last.getValue().toHexString(), beginTime+3, yOffsetM-size/2-1); + gc.setClipping(old); + } + left=right; + } + } + } + + @Override + public int getMinHeight() { + return height; + } + +} \ No newline at end of file diff --git a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/SignalWidget.java b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/SignalWidget.java deleted file mode 100644 index ac66609..0000000 --- a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/SignalWidget.java +++ /dev/null @@ -1,161 +0,0 @@ -package com.minres.scviewer.ui.swt; - -import java.util.NavigableSet; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.PaintEvent; -import org.eclipse.swt.events.PaintListener; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.GC; -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.wb.swt.SWTResourceManager; - -import com.minres.scviewer.database.EventTime; -import com.minres.scviewer.database.ISignal; -import com.minres.scviewer.database.ISignalChange; -import com.minres.scviewer.database.ISignalChangeMulti; -import com.minres.scviewer.database.ISignalChangeSingle; -import com.minres.scviewer.ui.TxEditorPlugin; - -public class SignalWidget extends Canvas implements IWaveformWidget{ - - static final int trackHeight = 50; - static final int trackInset = 1; - static final int txHeight = trackHeight - 2 * trackInset; - - static double zoomFactor = EventTime.getScalingFactor(EventTime.Unit.NS); - private Color lineColor; - private Color trackBgColor; - private Color color0; - private Color color1; - private Color colorZ; - private Color colorX; - private Color colorText; - private long length; - ISignal signal; - - public SignalWidget(Composite parent, int style) { - super(parent, style); - addPaintListener(new PaintListener() { - public void paintControl(PaintEvent e) { - SignalWidget.this.paintControl(e); - } - }); - TxEditorPlugin plugin=TxEditorPlugin.getDefault(); - lineColor=plugin.getColor(TxEditorPlugin.lineColor); - trackBgColor=plugin.getColor(TxEditorPlugin.trackBgDarkColor); - color0=SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN); - color1=SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN); - colorZ=SWTResourceManager.getColor(SWT.COLOR_GRAY); - colorX=SWTResourceManager.getColor(SWT.COLOR_RED); - colorText=SWTResourceManager.getColor(SWT.COLOR_WHITE); - } - - public void setTransactions(ISignal signal) { - this.signal=signal; - ISignalChange change = signal.getSignalChanges().last(); - length=(long) (change.getTime().getValue()/zoomFactor); - layout(true,true); - } - - @Override - public Point computeSize (int wHint, int hHint, boolean changed) { - return new Point((int) length, trackHeight); - } - - void paintControl(PaintEvent e) { - GC gc = e.gc; - gc.setForeground(lineColor); - gc.setFillRule(SWT.FILL_EVEN_ODD); - gc.setBackground(trackBgColor); - gc.setLineWidth(1); - gc.setLineStyle(SWT.LINE_SOLID); - gc.fillRectangle(new Rectangle(e.x, e.y, e.width, e.height)); - ISignalChange lastChange = null; - NavigableSet visibleChanges = signal.getSignalChangesByTimes( - new EventTime((long) (e.x*zoomFactor)), - new EventTime((long) ((e.x+e.width)*zoomFactor))); - for(ISignalChange actChange:visibleChanges){ - if(lastChange!=null){ - drawValues(e, gc, lastChange, actChange); - } - lastChange=actChange; - } - } - - protected void drawValues(PaintEvent e, GC gc, ISignalChange lastChange, ISignalChange actChange) { - if(lastChange instanceof ISignalChangeSingle){ - int yOffset = trackHeight/2; - Color color = colorX; - switch(((ISignalChangeSingle) lastChange).getValue()){ - case '1': - color=color1; - yOffset = trackHeight/5; - break; - case '0': - color=color0; - yOffset = 4*trackHeight/5; - break; - case 'Z': - color=colorZ; - break; - default: - } - gc.setForeground(color); - int endTime= (int)(actChange.getTime().getValue()/zoomFactor); - gc.drawLine((int)(lastChange.getTime().getValue()/zoomFactor), yOffset, endTime, yOffset); - int yNext = trackHeight/2; - switch(((ISignalChangeSingle) actChange).getValue()){ - case '1': - yNext = trackHeight/5; - break; - case '0': - yNext = 4*trackHeight/5; - break; - default: - } -// gc.setForeground(colorC); - if(yOffset stream; + private int height, upper, txHeight; + private int totalHeight; + private boolean even; + + public StreamPainter(WaveformCanvas txDisplay, boolean even, int height, ITxStream stream) { + this.waveCanvas = txDisplay; + this.stream=stream; + this.height=height; + this.upper=this.waveCanvas.getTrackHeight()/5; + this.txHeight=3*this.waveCanvas.getTrackHeight()/5; + this.totalHeight=stream.getMaxConcurrency()*this.waveCanvas.getTrackHeight(); + this.even=even; + } + + public void paintArea(GC gc, Rectangle area) { + gc.setBackground(this.waveCanvas.colors[even?WaveformCanvas.Colors.TRACK_BG_EVEN.ordinal():WaveformCanvas.Colors.TRACK_BG_ODD.ordinal()]); + gc.setFillRule(SWT.FILL_EVEN_ODD); + gc.fillRectangle(area); + Entry firstTx=stream.getEvents().floorEntry(area.x*waveCanvas.getScaleFactor()); + Entry lastTx=stream.getEvents().ceilingEntry((area.x+area.width)*waveCanvas.getScaleFactor()); + if(firstTx==null){ + if(lastTx==null) return; + firstTx = stream.getEvents().firstEntry(); + } else if(lastTx==null){ + lastTx=stream.getEvents().lastEntry(); + } + gc.setForeground(this.waveCanvas.colors[WaveformCanvas.Colors.LINE.ordinal()]); + gc.setBackground(this.waveCanvas.colors[WaveformCanvas.Colors.TX_BG.ordinal()]); + gc.setFillRule(SWT.FILL_EVEN_ODD); + gc.setLineStyle(SWT.LINE_SOLID); + gc.setLineWidth(1); + for(int y1=area.y+this.waveCanvas.getTrackHeight()/2; y1)firstTx.getValue()) + drawTx(gc, area, x.getTransaction()); + else{ + for(Entry tx: stream.getEvents().subMap(firstTx.getKey(), true, lastTx.getKey(), true).entrySet()) + for(ITxEvent x:(Collection)tx.getValue()) + if(x.getType()==ITxEvent.Type.END) drawTx(gc, area, x.getTransaction()); + } + } + + protected void drawTx(GC gc, Rectangle area, ITx tx) { + int offset = tx.getConcurrencyIndex()*this.waveCanvas.getTrackHeight(); + Rectangle bb = new Rectangle( + (int)(tx.getBeginTime()/this.waveCanvas.getScaleFactor()), area.y+offset+upper, + (int)((tx.getEndTime()-tx.getBeginTime())/this.waveCanvas.getScaleFactor()), txHeight); + if(bb.x+bb.widtharea.x+area.width) return; + if(bb.width<10){ + gc.fillRectangle(bb); + gc.drawRectangle(bb); + } else { + gc.fillRoundRectangle(bb.x, bb.y, bb.width, bb.height, 5, 5); + gc.drawRoundRectangle(bb.x, bb.y, bb.width, bb.height, 5, 5); + } + } + + @Override + public int getMinHeight() { + return height; + } + +} \ No newline at end of file diff --git a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/Track.java b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/Track.java deleted file mode 100644 index 4326684..0000000 --- a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/Track.java +++ /dev/null @@ -1,206 +0,0 @@ -package com.minres.scviewer.ui.swt; - -import java.util.HashMap; -import java.util.NavigableSet; -import java.util.Vector; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.MouseListener; -import org.eclipse.swt.events.PaintEvent; -import org.eclipse.swt.events.PaintListener; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Layout; - -import com.minres.scviewer.database.EventTime; -import com.minres.scviewer.database.ITx; -import com.minres.scviewer.ui.TxEditorPlugin; - -public class Track extends Composite implements IWaveformWidget, MouseListener { - - static final int trackHeight = 50; - static final int trackInset = 1; - static final int txHeight = trackHeight - 2 * trackInset; - - static double zoomFactor = EventTime.getScalingFactor(EventTime.Unit.NS); - private Color lineColor; - private Color trackBgColor; - - private ITx highlightedTx=null; - - private HashMap transactionMap = new HashMap(); - - class TrackLayoutData { - protected int x, y; - TrackLayoutData(int x, int y){ - this.x=x; - this.y=y; - } - public int getX() { - return x; - } - public int getY() { - return y; - } - - } - - class TrackLayout extends Layout { - Point extent; // the cached sizes - - protected Point computeSize(Composite composite, int wHint, int hHint, boolean changed) { - if (changed || extent == null) { - extent=new Point(0, 0); - for(Control child:composite.getChildren()){ - Point cExtent = child.computeSize(SWT.DEFAULT, SWT.DEFAULT, false); - TrackLayoutData dat = (TrackLayoutData) child.getLayoutData(); - extent.x=Math.max(extent.x, dat.x+cExtent.x); - extent.y=Math.max(extent.y, dat.y+cExtent.y); - } - } - return extent; - } - - protected void layout(Composite composite, boolean changed) { - if(extent==null){ - extent=new Point(0, 0); - changed=true; - } - for(Control child:composite.getChildren()){ - Point cExtent = child.computeSize(SWT.DEFAULT, SWT.DEFAULT, false); - TrackLayoutData dat = (TrackLayoutData) child.getLayoutData(); - if(changed){ - extent.x=Math.max(extent.x, dat.x+cExtent.x); - extent.y=Math.max(extent.y, dat.y+cExtent.y); - } - child.setBounds(dat.x, dat.y, cExtent.x, cExtent.y); - } - } - } - - Track(Composite parent, int style) { - super(parent, style); - setLayout(new TrackLayout()); - addDisposeListener(new DisposeListener() { - public void widgetDisposed(DisposeEvent e) { - Track.this.widgetDisposed(e); - } - }); - addPaintListener(new PaintListener() { - public void paintControl(PaintEvent e) { - Track.this.paintControl(e); - } - }); - TxEditorPlugin plugin=TxEditorPlugin.getDefault(); - lineColor=plugin.getColor(TxEditorPlugin.lineColor); - trackBgColor=plugin.getColor(TxEditorPlugin.trackBgDarkColor); - } - - - protected void widgetDisposed(DisposeEvent e) { - } - - void paintControl(PaintEvent e) { - GC gc = e.gc; - gc.setForeground(lineColor); - gc.setFillRule(SWT.FILL_EVEN_ODD); - gc.setBackground(trackBgColor); - gc.setLineWidth(3); - gc.setLineStyle(SWT.LINE_SOLID); - gc.fillRectangle(new Rectangle(e.x, e.y, e.width, e.height)); - for(int offset=trackHeight/2; offset transactions) { - Vector rowendtime = new Vector(); - for (ITx tx : transactions) { - int rowIdx = 0; - for (ITx lastTx : rowendtime) { - if((lastTx.getEndTime().getValue()-lastTx.getBeginTime().getValue())>0){ - if (lastTx.getEndTime().compareTo(tx.getBeginTime())<=0 ) - break; - } else { - if (lastTx.getEndTime().compareTo(tx.getBeginTime())<0 ) - break; - } - rowIdx++; - } - if (rowendtime.size() <= rowIdx) { - rowendtime.add(tx); - } else { - rowendtime.set(rowIdx, tx); - } - int width = (int) ((tx.getEndTime().getValue()-tx.getBeginTime().getValue())/zoomFactor); - if(width==0) width=1; - Transaction t = new Transaction(this, SWT.NONE, width); - t.setLayoutData(new Track.TrackLayoutData((int) (tx.getBeginTime().getValue()/zoomFactor), rowIdx*trackHeight)); - t.setData(tx); - t.addMouseListener(this); - transactionMap.put(tx, t); - } - layout(true,true); - } - - - @Override - public void mouseDoubleClick(MouseEvent e) { - Event event = new Event(); - event.type = SWT.MouseDoubleClick; - event.display=e.display; - event.data = e.widget; - event.button=e.button; - event.time=e.time; - this.notifyListeners(SWT.MouseDoubleClick, event); - } - - - @Override - public void mouseDown(MouseEvent e) { - Event event = new Event(); - event.type = SWT.MouseDown; - event.display=e.display; - event.data = e.widget; - event.button=e.button; - event.time=e.time; - this.notifyListeners(SWT.MouseDown, event); - } - - - @Override - public void mouseUp(MouseEvent e) { - Event event = new Event(); - event.type = SWT.MouseUp; - event.display=e.display; - event.data = e.widget; - event.button=e.button; - event.time=e.time; - this.notifyListeners(SWT.MouseUp, event); - } - - public Transaction highlight(Object obj){ - if(obj==null || obj instanceof ITx){ - ITx tx = (ITx) obj; - if(highlightedTx!=null){ - transactionMap.get(highlightedTx).highlight(false); - highlightedTx=null; - } - if(tx!=null && transactionMap.containsKey(tx)){ - Transaction trans = transactionMap.get(tx); - trans.highlight(true); - highlightedTx=tx; - return trans; - } - } - return null; - } -} diff --git a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/TrackPainter.java b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/TrackPainter.java new file mode 100644 index 0000000..569d92d --- /dev/null +++ b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/TrackPainter.java @@ -0,0 +1,43 @@ +package com.minres.scviewer.ui.swt; + +import java.util.Map.Entry; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Rectangle; + +class TrackPainter implements IPainter { + + /** + * + */ + private final WaveformCanvas waveCanvas; + + /** + * @param txDisplay + */ + TrackPainter(WaveformCanvas waveCanvas) { + this.waveCanvas = waveCanvas; + } + + public void paintArea(GC gc, Rectangle area) { + if(this.waveCanvas.streams.size()>0){ + Integer firstKey=this.waveCanvas.trackVerticalOffset.floorKey(area.y); + if(firstKey==null) firstKey=this.waveCanvas.trackVerticalOffset.firstKey(); + Integer lastKey = this.waveCanvas.trackVerticalOffset.floorKey(area.y+area.height); + Rectangle subArea = new Rectangle(area.x, 0, area.width, 0); + if(lastKey==firstKey){ + subArea.y=firstKey; + IWaveformPainter p = this.waveCanvas.trackVerticalOffset.get(firstKey); + subArea.height=p.getMinHeight(); + p.paintArea(gc, subArea); + }else{ + for(Entry entry : this.waveCanvas.trackVerticalOffset.subMap(firstKey, true, lastKey, true).entrySet()){ + subArea.y=entry.getKey(); + subArea.height=entry.getValue().getMinHeight(); + entry.getValue().paintArea(gc, subArea); + } + } + } + } +} \ No newline at end of file diff --git a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/Transaction.java b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/Transaction.java deleted file mode 100644 index 4265ace..0000000 --- a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/Transaction.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.minres.scviewer.ui.swt; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.PaintEvent; -import org.eclipse.swt.events.PaintListener; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Composite; - -import com.minres.scviewer.ui.TxEditorPlugin; - -public class Transaction extends Composite { - - public static int height = 50; - public static Color lineColor; - public static Color txBgColor; - public static Color highliteLineColor; - public static Color txHighliteBgColor; - public static Color trackBgColor; - private int length; - private boolean highlighted=false; - - Transaction(Composite parent, int style, int lenght) { - super(parent, style|SWT.NO_BACKGROUND); - this.length=lenght; - addDisposeListener(new DisposeListener() { - public void widgetDisposed(DisposeEvent e) { - Transaction.this.widgetDisposed(e); - } - }); - addPaintListener(new PaintListener() { - public void paintControl(PaintEvent e) { - Transaction.this.paintControl(e); - } - }); - TxEditorPlugin plugin=TxEditorPlugin.getDefault(); - lineColor=plugin.getColor(TxEditorPlugin.lineColor); - txBgColor=plugin.getColor(TxEditorPlugin.txBgColor); - trackBgColor=plugin.getColor(TxEditorPlugin.trackBgDarkColor); - highliteLineColor=plugin.getColor(TxEditorPlugin.highliteLineColor); - txHighliteBgColor=plugin.getColor(TxEditorPlugin.txHighliteBgColor); - setBackground(trackBgColor); - } - - protected void widgetDisposed(DisposeEvent e) { - } - - void paintControl(PaintEvent e) { - GC gc = e.gc; - gc.setBackground(trackBgColor); - gc.fillRectangle(new Rectangle(0, 0, length, height)); - gc.setForeground(highlighted?highliteLineColor:lineColor); - gc.setFillRule(SWT.FILL_EVEN_ODD); - gc.setBackground(highlighted?txHighliteBgColor:txBgColor); - gc.setLineWidth(1); - gc.setLineStyle(SWT.LINE_SOLID); - Rectangle bb = new Rectangle(0, height/5, length-1, 3*height/5); - if(bb.width<10){ - gc.fillRectangle(bb); - gc.drawRectangle(bb); - } else { - gc.fillRoundRectangle(bb.x, bb.y, bb.width, bb.height, 5, 5); - gc.drawRoundRectangle(bb.x, bb.y, bb.width, bb.height, 5, 5); - } - } - - @Override - public Point computeSize(int wHint, int hHint, boolean changed) { - return new Point(length, height); - } - - public void highlight(boolean highlight) { - highlighted=highlight; - redraw(); - } -} diff --git a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/TxDisplay.java b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/TxDisplay.java index c2d018f..375adf2 100644 --- a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/TxDisplay.java +++ b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/TxDisplay.java @@ -12,15 +12,15 @@ package com.minres.scviewer.ui.swt; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; +import java.util.NavigableMap; +import java.util.Map.Entry; +import java.util.TreeMap; import org.eclipse.core.runtime.ListenerList; +import org.eclipse.jface.resource.FontDescriptor; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; @@ -33,52 +33,82 @@ import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.ControlListener; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.graphics.TextLayout; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.layout.RowData; import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.ScrollBar; import org.eclipse.wb.swt.SWTResourceManager; import swing2swt.layout.BorderLayout; import com.minres.scviewer.database.ISignal; -import com.minres.scviewer.database.ISignalChange; import com.minres.scviewer.database.ITx; +import com.minres.scviewer.database.ITxEvent; import com.minres.scviewer.database.ITxStream; import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.ui.handler.GotoDirection; public class TxDisplay implements PropertyChangeListener, ISelectionProvider, MouseListener{ - - private static final String VALUEWIDGET = "VALUEWIDGET"; - private static final String NAMEWIDGET = "NAMEWIDGET"; - private static final String WAVEFORM = "WAVEFORM"; private ListenerList listeners = new ListenerList(); private IWaveform currentStreamSelection; private ITx currentSelection; + private IWaveform currentWaveformSelection; + + private ScrolledComposite nameListScrolled; private ScrolledComposite valueListScrolled; - private ScrolledComposite nameListScrolled; - private Composite nameList; - private Composite valueList; - private ScrolledComposite trackListScrolled; - private Composite trackList; + + private Canvas nameList; + private Canvas valueList; + private WaveformCanvas trackList; + private Composite top; - private ArrayList streams=new ArrayList(); + ObservableList streams; private Composite trackPane; private Ruler ruler; - private HashMap trackMap = new HashMap(); - + TreeMap trackVerticalOffset; + +// private long maxTime=0; + private Font nameFont; + private Font valueFont; + public TxDisplay(Composite parent) { + trackVerticalOffset = new TreeMap(); + Display d =parent.getDisplay(); + parent.addDisposeListener(new DisposeListener() { + @Override + public void widgetDisposed(DisposeEvent e) { + dispose(); + } + }); + FontDescriptor fontDescriptor = FontDescriptor.createFrom(d.getSystemFont()).setStyle(SWT.BOLD); + nameFont = fontDescriptor.createFont(d); + valueFont = fontDescriptor.createFont(d); + + streams=new ObservableList(); + streams.addPropertyChangeListener(this); + top = new Composite(parent, SWT.NONE); top.setLayout(new FillLayout(SWT.HORIZONTAL)); @@ -90,97 +120,114 @@ public class TxDisplay implements PropertyChangeListener, ISelectionProvider, Mo SashForm leftSash = new SashForm(composite, SWT.SMOOTH); leftSash.setBackground(leftSash.getDisplay().getSystemColor( SWT.COLOR_GRAY)); -// leftSash.addControlListener(new ControlAdapter() { -// public void controlResized(ControlEvent e) { -// recalculateNameBounds(); -// recalculateValueBounds(); -// } -// }); + Composite namePane = createTextPane(leftSash, "Name"); namePane.setBackground(namePane.getDisplay().getSystemColor( SWT.COLOR_WIDGET_BACKGROUND)); - namePane.addControlListener(new ControlAdapter() { - public void controlResized(ControlEvent e) { - recalculateNameBounds(); - } - }); nameListScrolled = new ScrolledComposite(namePane, SWT.H_SCROLL | SWT.V_SCROLL); nameListScrolled.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); - nameListScrolled.setExpandHorizontal(true); - nameListScrolled.setExpandVertical(true); - nameList = new Composite(nameListScrolled, SWT.NONE); - nameList.setLayout(createScrolledLayoutData(false)); - + nameListScrolled.setAlwaysShowScrollBars(true); + nameListScrolled.addControlListener(new ControlAdapter(){ + @Override + public void controlResized(ControlEvent e) { + nameListScrolled.getVerticalBar().setVisible(false); + + } + }); + nameList = new Canvas(nameListScrolled, SWT.NONE){ + @Override + public Point computeSize(int wHint, int hHint, boolean changed) { + Rectangle bounds= super.getClientArea(); + return new Point(bounds.width, bounds.height); + } + }; + nameList.addListener(SWT.Paint, new Listener() { + @Override + public void handleEvent(Event event) { + GC gc = event.gc; + Rectangle rect = ((Canvas)event.widget).getClientArea(); + paintNames(gc, rect); + } + }); + nameList.addMouseListener(this); nameListScrolled.setContent(nameList); Composite valuePane = createTextPane(leftSash, "Value"); valuePane.setBackground(valuePane.getDisplay().getSystemColor( SWT.COLOR_WIDGET_BACKGROUND)); - valuePane.addControlListener(new ControlAdapter() { - public void controlResized(ControlEvent e) { - recalculateValueBounds(); - } - }); valueListScrolled = new ScrolledComposite(valuePane, SWT.H_SCROLL | SWT.V_SCROLL); valueListScrolled.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); - valueListScrolled.setExpandHorizontal(true); - valueListScrolled.setExpandVertical(true); - valueList = new Composite(valueListScrolled, SWT.NONE); - valueList.setLayout(createScrolledLayoutData(true)); + valueListScrolled.setAlwaysShowScrollBars(true); + valueListScrolled.addControlListener(new ControlAdapter(){ + @Override + public void controlResized(ControlEvent e) { + valueListScrolled.getVerticalBar().setVisible(false); + + } + }); + valueList = new Canvas(valueListScrolled, SWT.NONE){ + @Override + public Point computeSize(int wHint, int hHint, boolean changed) { + Rectangle bounds= super.getClientArea(); + return new Point(bounds.width, bounds.height); + } + }; + valueList.addListener(SWT.Paint, new Listener() { + @Override + public void handleEvent(Event event) { + GC gc = event.gc; + Rectangle rect = ((Canvas)event.widget).getClientArea(); + paintValues(gc, rect); + } + }); + valueList.addMouseListener(this); valueListScrolled.setContent(valueList); - trackPane = new Composite(topSash, SWT.NONE); trackPane.setLayout(new BorderLayout(0, 0)); ruler = new Ruler(trackPane, SWT.NONE, 0); ruler.setLayoutData(BorderLayout.NORTH); + + trackList = new WaveformCanvas(trackPane, SWT.NONE); + trackList.setLayoutData(BorderLayout.CENTER); + trackList.streams=streams; + trackList.addTrackPainter(new TrackPainter(trackList)); + trackList.setMaxTime(1); + trackList.addMouseListener(this); - trackListScrolled = new ScrolledComposite(trackPane, SWT.H_SCROLL | SWT.V_SCROLL); - trackListScrolled.setExpandVertical(true); - trackListScrolled.setExpandHorizontal(true); - trackList = new Composite(trackListScrolled, SWT.NONE); - trackList.setLayout(createScrolledLayoutData(false)); - trackListScrolled.setContent(trackList); - nameListScrolled.getVerticalBar().addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { + nameListScrolled.getVerticalBar().addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { int y = ((ScrollBar) e.widget).getSelection(); valueListScrolled.setOrigin(valueListScrolled.getOrigin().x, y); - trackListScrolled.setOrigin(trackListScrolled.getOrigin().x, y); + trackList.scrollToY(y); } }); valueListScrolled.getVerticalBar().addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { int y = ((ScrollBar) e.widget).getSelection(); nameListScrolled.setOrigin(nameListScrolled.getOrigin().x, y); - trackListScrolled.setOrigin(trackListScrolled.getOrigin().x, y); + trackList.scrollToY(y); } }); - trackListScrolled.getContent().addControlListener(new ControlAdapter() { - @Override - public void controlMoved(ControlEvent e) { - ruler.setStartPoint(trackListScrolled.getHorizontalBar().getSelection()); - int y = trackListScrolled.getVerticalBar().getSelection(); + trackList.getHorizontalBar().addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + ruler.setStartPoint(trackList.getHorizontalBar().getSelection()); + } + }); + trackList.getVerticalBar().addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + int y = trackList.getVerticalBar().getSelection(); nameListScrolled.setOrigin(nameListScrolled.getOrigin().x, y); valueListScrolled.setOrigin(valueListScrolled.getOrigin().x, y); - } + } }); topSash.setWeights(new int[] {30, 70}); leftSash.setWeights(new int[] {75, 25}); - - top.layout(true, true); - streamListChanged(); } - protected RowLayout createScrolledLayoutData(boolean center) { - RowLayout nameListLayout = new RowLayout(SWT.VERTICAL); - nameListLayout.spacing = 2; - nameListLayout.marginTop = 0; - nameListLayout.marginRight = 0; - nameListLayout.marginLeft = 0; - nameListLayout.marginBottom = 0; - nameListLayout.fill = true; - nameListLayout.wrap = false; - nameListLayout.center=center; - return nameListLayout; + + protected void dispose() { + nameFont.dispose(); + valueFont.dispose(); } private Composite createTextPane(SashForm leftSash, String text) { @@ -207,109 +254,45 @@ public class TxDisplay implements PropertyChangeListener, ISelectionProvider, Mo return namePane; } - public void streamListChanged() { - LinkedListtoAdd = new LinkedList(); - toAdd.addAll(streams); - for(Control child:trackList.getChildren()){ - IWaveform stream=(IWaveform) child.getData(WAVEFORM); - if(!streams.contains(stream)){ - child.setVisible(false); - ((Control)(child.getData(NAMEWIDGET))).setVisible(false); - ((Control)(child.getData(VALUEWIDGET))).setVisible(false); - }else{ - toAdd.remove(stream); - child.setVisible(true); - ((Control)(child.getData(NAMEWIDGET))).setVisible(true); - ((Control)(child.getData(VALUEWIDGET))).setVisible(true); - } - } - for(IWaveform wave: toAdd){ - if(wave instanceof ITxStream){ - ITxStream stream = (ITxStream) wave; - Track track = new Track(trackList,SWT.NONE); - track.setTransactions(stream.getTransactions()); - track.setData(WAVEFORM, stream); - track.addMouseListener(this); - Point trackSize = track.computeSize(SWT.DEFAULT,SWT.DEFAULT); - - Label trackName = new Label(nameList, SWT.NONE); - trackName.setText(stream.getFullName()); - RowData trackNamelayoutData = new RowData(SWT.DEFAULT, trackSize.y); - trackName.setLayoutData(trackNamelayoutData); - trackName.setData(WAVEFORM, stream); - trackName.addMouseListener(this); - track.setData(NAMEWIDGET, trackName); - - Label trackValue = new Label(valueList, SWT.NONE); - trackValue.setText("-"); - RowData trackValuelayoutData = new RowData(SWT.DEFAULT, trackSize.y); - trackValue.setLayoutData(trackValuelayoutData); - trackValue.setData(WAVEFORM, stream); - trackValue.addMouseListener(this); - track.setData(VALUEWIDGET, trackValue); - trackMap.put(stream, track); - } else if(wave instanceof ISignal){ - @SuppressWarnings("unchecked") - ISignal isignal = (ISignal) wave; - SignalWidget signal = new SignalWidget(trackList, SWT.NONE); - signal.setTransactions(isignal); - signal.setData(WAVEFORM, isignal); - signal.addMouseListener(this); - Point trackSize = signal.computeSize(SWT.DEFAULT,SWT.DEFAULT); - - Label trackName = new Label(nameList, SWT.NONE); - trackName.setText(isignal.getFullName()); - RowData trackNamelayoutData = new RowData(SWT.DEFAULT, trackSize.y); - trackName.setLayoutData(trackNamelayoutData); - trackName.setData(WAVEFORM, isignal); - trackName.addMouseListener(this); - signal.setData(NAMEWIDGET, trackName); - - Label trackValue = new Label(valueList, SWT.NONE); - trackValue.setText("-"); - RowData trackValuelayoutData = new RowData(SWT.DEFAULT, trackSize.y); - trackValue.setLayoutData(trackValuelayoutData); - trackValue.setData(WAVEFORM, isignal); - trackValue.addMouseListener(this); - signal.setData(VALUEWIDGET, trackValue); - trackMap.put(isignal, signal); - } - } - recalculateNameBounds(); - recalculateValueBounds(); - Point trackSize=trackList.computeSize(SWT.DEFAULT, SWT.DEFAULT); - trackListScrolled.setMinSize(trackSize); - top.layout(true, true); - } - - protected void recalculateValueBounds() { - if(streams.size()>0){ - Point size = valueList.computeSize(SWT.DEFAULT, SWT.DEFAULT); - valueListScrolled.setMinSize(size); - valueListScrolled.setAlwaysShowScrollBars(true); - valueListScrolled.getVerticalBar().setVisible(false); - } - } - - protected void recalculateNameBounds() { - if(streams.size()>0){ - Point size = nameList.computeSize(SWT.DEFAULT, SWT.DEFAULT); - nameListScrolled.setMinSize(size); - nameListScrolled.setAlwaysShowScrollBars(true); - nameListScrolled.getVerticalBar().setVisible(false); - } - } - @Override public void propertyChange(PropertyChangeEvent pce) { - currentSelection=null; - ITxStream str = (ITxStream)pce.getNewValue(); - if(str instanceof ITxStream) - currentStreamSelection=(ITxStream)str; - if(currentStreamSelection!=null) - setSelection(getSelection()); - else - setSelection(StructuredSelection.EMPTY); + if("size".equals(pce.getPropertyName())) { + updateTracklist(); + } + } + + protected void updateTracklist() { + int yoffs=0; + int nameMaxWidth=0; + int valueMaxWidth=0; + + IWaveformPainter painter=null; + trackVerticalOffset.clear(); + trackList.clearAllWavefromPainter(); + boolean even=true; + TextLayout tl = new TextLayout(trackList.getDisplay()); + for(IWaveform waveform:streams){ + int height=trackList.getTrackHeight(); + if(waveform instanceof ITxStream){ + height*=((ITxStream)waveform).getMaxConcurrency(); + painter= new StreamPainter(trackList, even, height, (ITxStream) waveform); + } else if(waveform instanceof ISignal){ + painter= new SignalPainter(trackList, even, height, (ISignal) waveform); + } + trackList.addWavefromPainter(yoffs, painter); + trackVerticalOffset.put(yoffs, waveform); + tl.setText(waveform.getFullName()); + nameMaxWidth=Math.max(nameMaxWidth, tl.getBounds().width); + valueMaxWidth=nameMaxWidth; + yoffs+=height; + even=!even; + } + valueList.setSize(nameMaxWidth, yoffs); + nameList.setSize(valueMaxWidth, yoffs); + valueList.redraw(); + nameList.redraw(); + trackList.redraw(); + top.layout(new Control[]{valueList, nameList, trackList}); } @Override @@ -317,6 +300,11 @@ public class TxDisplay implements PropertyChangeListener, ISelectionProvider, Mo listeners.add(listener); } + @Override + public void removeSelectionChangedListener(ISelectionChangedListener listener) { + listeners.remove(listener); + } + @Override public ISelection getSelection() { if(currentSelection!=null) @@ -327,31 +315,48 @@ public class TxDisplay implements PropertyChangeListener, ISelectionProvider, Mo return null; } - @Override - public void removeSelectionChangedListener(ISelectionChangedListener listener) { - listeners.remove(listener); - } - @Override public void setSelection(ISelection selection) { + boolean selectionChanged=false; if(selection instanceof IStructuredSelection){ Object sel =((IStructuredSelection)selection).getFirstElement(); if(sel instanceof ITx && currentSelection!=sel){ - if(currentSelection!=null){ - ITxStream stream = currentSelection.getStream(); - if(trackMap.containsKey(stream)) trackMap.get(stream).highlight(null); - } currentSelection=(ITx) sel; - ITxStream stream = currentSelection.getStream(); - if(trackMap.containsKey(stream)){ - Transaction trans = trackMap.get(stream).highlight(sel); - trackListScrolled.showControl(trans); - } - Object[] list = listeners.getListeners(); - for (int i = 0; i < list.length; i++) { - ((ISelectionChangedListener) list[i]).selectionChanged(new SelectionChangedEvent(this, selection)); - } + currentWaveformSelection = currentSelection.getStream(); + selectionChanged=true; + } else if(sel instanceof IWaveform && currentStreamSelection!=sel){ + currentSelection=null; + currentWaveformSelection = (IWaveform) sel; + selectionChanged=true; } + } else { + if(currentSelection!=null || currentWaveformSelection!=null) selectionChanged=true; + currentSelection=null; + currentWaveformSelection = null; + } + if(selectionChanged){ + Object[] list = listeners.getListeners(); + for (int i = 0; i < list.length; i++) { + ((ISelectionChangedListener) list[i]).selectionChanged(new SelectionChangedEvent(this, selection)); + } + } + } + + public void moveSelection(GotoDirection direction) { + if(currentStreamSelection instanceof ITxStream){ + ITxStream stream = (ITxStream) currentStreamSelection; + ITx transaction=null; + if(direction==GotoDirection.NEXT){ + Entry> entry = stream.getEvents().higherEntry(currentSelection.getBeginTime()); + if(entry!=null) + transaction = entry.getValue().iterator().next().getTransaction(); + }else if(direction==GotoDirection.PREV){ + Entry> entry = stream.getEvents().lowerEntry(currentSelection.getBeginTime()); + if(entry!=null) + transaction = entry.getValue().iterator().next().getTransaction(); + } + if(transaction!=null) + setSelection(new StructuredSelection(transaction)); } } @@ -361,15 +366,12 @@ public class TxDisplay implements PropertyChangeListener, ISelectionProvider, Mo @Override public void mouseDown(MouseEvent e) { - if(e.data!=null){ - StructuredSelection sel = new StructuredSelection(((Transaction)e.data).getData()); - setSelection(sel); - }else if(e.widget instanceof Track){ - StructuredSelection sel = new StructuredSelection(new Object[]{ e.widget.getData(WAVEFORM)}); - setSelection(sel); - }else if(e.widget instanceof Label){ - StructuredSelection sel = new StructuredSelection(new Object[]{ e.widget.getData(WAVEFORM)}); - setSelection(sel); + if(e.widget==trackList){ + + }else if(e.widget==valueList){ + + }else if(e.widget==nameList){ + } } @@ -377,56 +379,53 @@ public class TxDisplay implements PropertyChangeListener, ISelectionProvider, Mo public void mouseUp(MouseEvent e) { } - public boolean addStream(IWaveform stream){ - boolean res = streams.add(stream); - streamListChanged(); - return res; - } - - public boolean addAllStreams(ITxStream[] streams) { - boolean res = this.streams.addAll(Arrays.asList(streams)); - streamListChanged(); - return res; - } - - public boolean addAllStreams(Collection paramCollection){ - boolean res = streams.addAll(paramCollection); - streamListChanged(); - return res; - } - - public boolean removeStream(IWaveform obj){ - boolean res = streams.remove(obj); - streamListChanged(); - return res; - } - - public boolean removeAllStreams(Collection paramCollection){ - boolean res = streams.removeAll(paramCollection); - streamListChanged(); - return res; - } - public List getStreamList(){ - return Collections.unmodifiableList(streams); + return streams; } - public boolean removeAllStreams(ITxStream[] streams) { - boolean res = this.streams.removeAll(Arrays.asList(streams)); - streamListChanged(); - return res; + protected void paintNames(GC gc, Rectangle rect) { + if(streams.size()>0){ + Integer firstKey=trackVerticalOffset.floorKey(rect.y); + if(firstKey==null) firstKey=trackVerticalOffset.firstKey(); + Integer lastKey = trackVerticalOffset.floorKey(rect.y+rect.height); + Rectangle subArea = new Rectangle(rect.x, 0, rect.width, 0); + if(lastKey==firstKey){ + drawTextFormat(gc, subArea, firstKey, trackVerticalOffset.get(firstKey).getFullName()); + }else{ + for(Entry entry : trackVerticalOffset.subMap(firstKey, true, lastKey, true).entrySet()){ + drawTextFormat(gc, subArea, entry.getKey(), entry.getValue().getFullName()); + } + } + } } - public void moveSelection(GotoDirection direction) { - if(currentStreamSelection instanceof ITxStream){ - ITx transaction=null; - if(direction==GotoDirection.NEXT) - transaction = ((ITxStream)currentStreamSelection).getTransactions().higher(currentSelection); - else if(direction==GotoDirection.PREV) - transaction = ((ITxStream)currentStreamSelection).getTransactions().lower(currentSelection); - if(transaction!=null) - setSelection(new StructuredSelection(transaction)); - } + protected void paintValues(GC gc, Rectangle rect) { + if(streams.size()>0){ + Integer firstKey=trackVerticalOffset.floorKey(rect.y); + if(firstKey==null) firstKey=trackVerticalOffset.firstKey(); + Integer lastKey = trackVerticalOffset.floorKey(rect.y+rect.height); + Rectangle subArea = new Rectangle(rect.x, 0, rect.width, 0); + if(lastKey==firstKey){ + drawTextFormat(gc, subArea, firstKey, trackVerticalOffset.get(firstKey).getFullName()); + }else{ + for(Entry entry : trackVerticalOffset.subMap(firstKey, true, lastKey, true).entrySet()){ + drawTextFormat(gc, subArea, entry.getKey(), "---"); + } + } + } + } + + protected void drawTextFormat(GC gc, Rectangle subArea, int yOffset, String p) { + Point size = gc.textExtent(p); + gc.drawText(p, subArea.x, subArea.y + yOffset+(trackList.getTrackHeight()-size.y)/2, true); + } + + public long getMaxTime() { + return trackList.getMaxTime(); + } + + public void setMaxTime(long maxTime) { + this.trackList.setMaxTime(maxTime); } } diff --git a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/WaveformCanvas.java b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/WaveformCanvas.java new file mode 100644 index 0000000..105cdcb --- /dev/null +++ b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/swt/WaveformCanvas.java @@ -0,0 +1,297 @@ +/******************************************************************************* + * Copyright (c) 2015 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: + * MINRES Technologies GmbH - initial API and implementation + *******************************************************************************/ +package com.minres.scviewer.ui.swt; + +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.TreeMap; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ControlAdapter; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.graphics.Region; +import org.eclipse.swt.graphics.Transform; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.ScrollBar; +import org.eclipse.wb.swt.SWTResourceManager; + +import com.minres.scviewer.database.IWaveform; + +public class WaveformCanvas extends Canvas { + public enum Colors { + LINE, + LINE_HIGHLITE, + TRACK_BG_EVEN, + TRACK_BG_HIGHLITE, + TRACK_BG_ODD, + TX_BG, + TX_BG_HIGHLITE, + TX_BORDER, + SIGNAL0, + SIGNAL1, + SIGNALZ, + SIGNALX, + SIGNAL_TEXT + } + + Color[] colors=new Color[Colors.values().length]; + + /* zooming rates in x and y direction are equal.*/ + final float ZOOMIN_RATE = 1.1f; /* zoomin rate */ + final float ZOOMOUT_RATE = 0.9f; /* zoomout rate */ + + private int trackHeight = 50; + private long scaleFactor = 1000000L; + private long maxTime; + + protected Point origin; /* original size */ + protected Transform transform; + + protected List painterList; + TreeMap trackVerticalOffset; + List streams; + + /** + * Constructor for ScrollableCanvas. + * @param parent the parent of this control. + * @param style the style of this control. + */ + public WaveformCanvas(final Composite parent, int style) { + super( parent, style |SWT.NO_BACKGROUND|SWT.NO_REDRAW_RESIZE|SWT.V_SCROLL|SWT.H_SCROLL); + addControlListener(new ControlAdapter() { /* resize listener. */ + public void controlResized(ControlEvent event) { + syncScrollBars(); + } + }); + addPaintListener(new PaintListener() { /* paint listener. */ + public void paintControl(final PaintEvent event) { + paint(event.gc); + } + }); + painterList=new LinkedList(); + origin=new Point(0,0); + transform = new Transform(getDisplay()); + trackVerticalOffset=new TreeMap(); + initScrollBars(); + initColors(null); + } + + private void initColors(HashMap colourMap){ + Display d = getDisplay(); + if(colourMap!=null){ + for(Colors c:Colors.values()){ + if(colourMap.containsKey(c)){ + colors[c.ordinal()].dispose(); + colors[c.ordinal()]=new Color(d, colourMap.get(c)); + } + } + } else { + colors[Colors.LINE.ordinal()]=SWTResourceManager.getColor(SWT.COLOR_RED); + colors[Colors.LINE_HIGHLITE.ordinal()]=SWTResourceManager.getColor(SWT.COLOR_CYAN); + colors[Colors.TRACK_BG_EVEN.ordinal()]=SWTResourceManager.getColor(SWT.COLOR_BLACK); + colors[Colors.TRACK_BG_ODD.ordinal()]=SWTResourceManager.getColor(25,25,25); + colors[Colors.TRACK_BG_HIGHLITE.ordinal()]=SWTResourceManager.getColor(SWT.COLOR_GRAY); + colors[Colors.TX_BG.ordinal()]=SWTResourceManager.getColor(SWT.COLOR_GREEN); + colors[Colors.TX_BG_HIGHLITE.ordinal()]=SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN); + colors[Colors.TX_BORDER.ordinal()]=SWTResourceManager.getColor(SWT.COLOR_RED); + colors[Colors.SIGNAL0.ordinal()]=SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN); + colors[Colors.SIGNAL1.ordinal()]=SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN); + colors[Colors.SIGNALZ.ordinal()]=SWTResourceManager.getColor(SWT.COLOR_GRAY); + colors[Colors.SIGNALX.ordinal()]=SWTResourceManager.getColor(SWT.COLOR_RED); + colors[Colors.SIGNAL_TEXT.ordinal()]=SWTResourceManager.getColor(SWT.COLOR_WHITE); + } + } + + public long getMaxTime() { + return maxTime; + } + + public void setMaxTime(long maxTime){ + this.maxTime=maxTime; + syncScrollBars(); + } + + public int getTrackHeight() { + return trackHeight; + } + + public void setTrackHeight(int trackHeight) { + this.trackHeight = trackHeight; + syncScrollBars(); + } + + public long getScaleFactor() { + return scaleFactor; + } + + public void setScaleFactor(long scaleFactor) { + this.scaleFactor = scaleFactor; + } + + public void addTrackPainter(IPainter painter) { + painterList.add(painter); + redraw(); + } + + public void removeTrackPainter(IPainter painter){ + painterList.remove(painter); + redraw(); + } + + public void clearAllWavefromPainter() { + trackVerticalOffset.clear(); + syncScrollBars(); + } + + public void addWavefromPainter(int yoffs, IWaveformPainter painter) { + trackVerticalOffset.put(yoffs, painter); + syncScrollBars(); + } + + /** + * Dispose the garbage here + */ + public void dispose() { + transform.dispose(); + for(Colors c:Colors.values()) colors[c.ordinal()].dispose(); + super.dispose(); + } + + public void scrollToY(int y){ + ScrollBar vBar = getVerticalBar(); + vBar.setSelection(y); + scrollVertically(vBar); + } + + public void scrollToX(int x){ + ScrollBar hBar = getHorizontalBar(); + hBar.setSelection(x); + scrollHorizontally(hBar); + } + + /* Scroll horizontally */ + private void scrollHorizontally(ScrollBar scrollBar) { + if (painterList.size()==0) return; + origin.x= -scrollBar.getSelection(); + syncScrollBars(); + } + + /* Scroll vertically */ + private void scrollVertically(ScrollBar scrollBar) { + if (painterList.size()==0) return; + origin.y = -scrollBar.getSelection(); + syncScrollBars(); + } + + /* Initalize the scrollbar and register listeners. */ + private void initScrollBars() { + ScrollBar horizontal = getHorizontalBar(); + horizontal.setEnabled(false); + horizontal.setVisible(true); + horizontal.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + scrollHorizontally((ScrollBar) event.widget); + } + }); + ScrollBar vertical = getVerticalBar(); + vertical.setEnabled(false); + vertical.setVisible(true); + vertical.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + scrollVertically((ScrollBar) event.widget); + } + }); + } + + /** + * Synchronize the scrollbar with the image. If the transform is out + * of range, it will correct it. This function considers only following + * factors : transform, image size, client area. + */ + private void syncScrollBars() { + if (painterList.size()==0) { + redraw(); + return; + } + int height=1; + if(trackVerticalOffset.size()>0) + height=trackVerticalOffset.lastKey()+trackVerticalOffset.lastEntry().getValue().getMinHeight(); + + int width = (int) (maxTime/scaleFactor); + ScrollBar horizontal = getHorizontalBar(); + horizontal.setIncrement((int) (getClientArea().width / 100)); + horizontal.setPageIncrement(getClientArea().width); + int cw = getClientArea().width; + if (width > cw) { /* image is wider than client area */ + horizontal.setMaximum(width); + horizontal.setEnabled(true); + if (((int) - origin.x) > horizontal.getMaximum() - cw) + origin.x = -horizontal.getMaximum() + cw; + } else { /* image is narrower than client area */ + horizontal.setEnabled(false); + } + horizontal.setSelection(-origin.x); + horizontal.setThumb(cw); + + ScrollBar vertical = getVerticalBar(); + vertical.setIncrement((int) (getClientArea().height / 100)); + vertical.setPageIncrement((int) (getClientArea().height)); + int ch = getClientArea().height; + if (height> ch) { /* image is higher than client area */ + vertical.setMaximum(height); + vertical.setEnabled(true); + if (((int) - origin.y) > vertical.getMaximum() - ch) + origin.y = -vertical.getMaximum() + ch; + } else { /* image is less higher than client area */ + vertical.setMaximum((int) (ch)); + vertical.setEnabled(false); + } + vertical.setSelection(-origin.y); + vertical.setThumb(ch); + redraw(); + } + + /* Paint function */ + private void paint(GC gc) { + Rectangle clientRect = getClientArea(); /* Canvas' painting area */ + clientRect.x=-origin.x; + clientRect.y=-origin.y; + // reset the transform + transform.identity(); + // shift the content + transform.translate(origin.x, origin.y); + gc.setTransform(transform); + gc.setClipping(clientRect); + if (painterList.size()>0 && trackVerticalOffset.size()>0) { + for(IPainter painter: painterList) + painter.paintArea(gc, clientRect); + } else { + gc.fillRectangle(clientRect); + initScrollBars(); + } + } + +} diff --git a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/views/TxOutlinePage.java b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/views/TxOutlinePage.java index ffbaa0d..68d41df 100644 --- a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/views/TxOutlinePage.java +++ b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/views/TxOutlinePage.java @@ -10,6 +10,8 @@ *******************************************************************************/ package com.minres.scviewer.ui.views; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.util.LinkedList; import org.eclipse.jface.action.Action; @@ -46,7 +48,7 @@ import com.minres.scviewer.ui.views.provider.TxDbTreeLabelProvider; /** * Creates an outline pagebook for this editor. */ -public class TxOutlinePage extends ContentOutlinePage implements ISelectionListener, ISelectionProvider { +public class TxOutlinePage extends ContentOutlinePage implements ISelectionListener, ISelectionProvider, PropertyChangeListener { public static final int ADD_TO_WAVE = 0; public static final int ADD_ALL_TO_WAVE = 1; @@ -54,7 +56,8 @@ public class TxOutlinePage extends ContentOutlinePage implements ISelectionList public static final int REMOVE_ALL_FROM_WAVE = 3; private TxEditorPart editor; - + TreeViewer contentOutlineViewer ; + public TxOutlinePage(TxEditorPart editor) { this.editor = editor; } @@ -68,7 +71,7 @@ public class TxOutlinePage extends ContentOutlinePage implements ISelectionList */ public void createControl(Composite parent) { super.createControl(parent); - TreeViewer contentOutlineViewer = getTreeViewer(); + contentOutlineViewer = getTreeViewer(); contentOutlineViewer.addSelectionChangedListener(this); // Set up the tree viewer contentOutlineViewer.setContentProvider(new TxDbTreeContentProvider()); @@ -89,6 +92,7 @@ public class TxOutlinePage extends ContentOutlinePage implements ISelectionList getSite().getPage().addSelectionListener((ISelectionListener) this); //getSite().getPage().addSelectionListener("SampleViewId",(ISelectionListener)this); getSite().setSelectionProvider(this); + editor.getDatabase().addPropertyChangeListener(this); } /* @@ -211,4 +215,11 @@ public class TxOutlinePage extends ContentOutlinePage implements ISelectionList return action; } + @Override + public void propertyChange(PropertyChangeEvent evt) { + if("CHILDS".equals(evt.getPropertyName())) { + contentOutlineViewer.refresh(); + } + } + }