Merge branch 'release/2.0'
This commit is contained in:
		| @@ -15,3 +15,4 @@ Bundle-ActivationPolicy: lazy | ||||
| Embed-Dependency: sqlite-jdbc | ||||
| Embedded-Artifacts: sqlite-jdbc-3.8.7.jar;g="org.xerial"; | ||||
|  a="sqlite-jdbc";v="3.8.7" | ||||
| Automatic-Module-Name: com.minres.scviewer.database.sqlite | ||||
|   | ||||
| @@ -31,7 +31,7 @@ | ||||
| <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/> | ||||
| <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.minres.scviewer.database.test"/> | ||||
| <stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/> | ||||
| <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms40m -Xmx512m -Xdock:icon=../Resources/Eclipse.icns -XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts"/> | ||||
| <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms40m -Xmx512m"/> | ||||
| <stringAttribute key="pde.version" value="3.3"/> | ||||
| <stringAttribute key="product" value="com.minres.scviewer.e4.product"/> | ||||
| <booleanAttribute key="run_in_ui_thread" value="true"/> | ||||
|   | ||||
| @@ -12,3 +12,4 @@ Require-Bundle: org.junit, | ||||
|  com.minres.scviewer.database.vcd;bundle-version="1.0.0" | ||||
| Bundle-ActivationPolicy: lazy | ||||
| Service-Component: OSGI-INF/component.xml | ||||
| Automatic-Module-Name: com.minres.scviewer.database.test | ||||
|   | ||||
| @@ -45,6 +45,7 @@ $var wire    1  aaabd  s_gpio_29       $end | ||||
| $var wire    1  aaabe  s_gpio_30       $end | ||||
| $var wire    1  aaabf  s_gpio_31       $end | ||||
| $var wire    1  aaabg  s_rst_n       $end | ||||
| $var real    1  bbbbb  a_real        $end | ||||
| $scope module i_platform $end | ||||
| $var wire    1  aaabh  erst_n       $end | ||||
| $var wire   64  aabdc  s_tlclk [63:0]  $end | ||||
| @@ -1621,6 +1622,7 @@ b1110100011010100101001010 aabdd | ||||
| 0aabdv | ||||
| 0aabdw | ||||
| 0aabdx | ||||
| r0.0 bbbbb | ||||
| $end | ||||
|  | ||||
| #10000 | ||||
| @@ -1638,6 +1640,28 @@ $end | ||||
| 0aabcq | ||||
| 0aabcy | ||||
| 0aabde | ||||
| r1.0 bbbbb | ||||
|  | ||||
| #20000 | ||||
| r2.0 bbbbb | ||||
|  | ||||
| #30000 | ||||
| r2.5 bbbbb | ||||
|  | ||||
| #40000 | ||||
| r1.5 bbbbb | ||||
|  | ||||
| #50000 | ||||
| r-1.0 bbbbb | ||||
|  | ||||
| #60000 | ||||
| r-2.5 bbbbb | ||||
|  | ||||
| #70000 | ||||
| r-1.0 bbbbb | ||||
|  | ||||
| #80000 | ||||
| r0.0 bbbbb | ||||
|  | ||||
| #1287121272 | ||||
| b1000000000100000000000000000100 aabcr | ||||
|   | ||||
| @@ -92,7 +92,7 @@ public class DatabaseServicesTest { | ||||
| 		assertTrue(f.exists()); | ||||
| 		waveformDb.load(f); | ||||
| 		assertNotNull(waveformDb); | ||||
| 		assertEquals(778,  waveformDb.getAllWaves().size()); | ||||
| 		assertEquals(779,  waveformDb.getAllWaves().size()); | ||||
| 		assertEquals(1,  waveformDb.getChildNodes().size()); | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -15,3 +15,4 @@ Require-Bundle: com.minres.scviewer.database;bundle-version="1.0.0", | ||||
|  com.google.guava;bundle-version="15.0.0" | ||||
| Service-Component: OSGI-INF/component.xml | ||||
| Bundle-ActivationPolicy: lazy | ||||
| Automatic-Module-Name: com.minres.scviewer.database.text | ||||
|   | ||||
| @@ -13,8 +13,6 @@ package com.minres.scviewer.database.text; | ||||
| import java.nio.charset.CharsetDecoder; | ||||
| import java.util.Collection; | ||||
| import java.util.zip.GZIPInputStream | ||||
| import org.apache.jdbm.DB | ||||
| import org.apache.jdbm.DBMaker | ||||
| import groovy.io.FileType | ||||
|  | ||||
| import com.minres.scviewer.database.AssociationType | ||||
| @@ -32,8 +30,6 @@ public class TextDbLoader implements IWaveformDbLoader{ | ||||
|  | ||||
| 	IWaveformDb db; | ||||
|  | ||||
| 	DB backingDb; | ||||
|  | ||||
| 	def streams = [] | ||||
|  | ||||
| 	def relationTypes=[:] | ||||
| @@ -65,20 +61,6 @@ public class TextDbLoader implements IWaveformDbLoader{ | ||||
| 		this.streams=[] | ||||
| 		def gzipped = isGzipped(file) | ||||
| 		if(isTxfile(gzipped?new GZIPInputStream(new FileInputStream(file)):new FileInputStream(file))){ | ||||
| 			if(true) { | ||||
| 				def parentDir=file.absoluteFile.parent | ||||
| 				def filename=file.name | ||||
| 				new File(parentDir).eachFileRecurse (FileType.FILES) { f -> if(f.name=~/^\.${filename}/) f.delete() } | ||||
| 				this.backingDb = DBMaker.openFile(parentDir+File.separator+"."+filename+"_bdb") | ||||
| 						.deleteFilesAfterClose() | ||||
| 						.useRandomAccessFile() | ||||
| 						.setMRUCacheSize(4096)  | ||||
| 						//.disableTransactions() | ||||
| 						.disableLocking() | ||||
| 						.make(); | ||||
| 			} else { | ||||
| 				this.backingDb = DBMaker.openMemory().disableLocking().make() | ||||
| 			} | ||||
| 			parseInput(gzipped?new GZIPInputStream(new FileInputStream(file)):new FileInputStream(file)) | ||||
| 			calculateConcurrencyIndicees() | ||||
| 			return true | ||||
| @@ -140,7 +122,7 @@ public class TextDbLoader implements IWaveformDbLoader{ | ||||
| 				case "end_attribute": | ||||
| 					if ((matcher = line =~ /^scv_tr_stream\s+\(ID (\d+),\s+name\s+"([^"]+)",\s+kind\s+"([^"]+)"\)$/)) { | ||||
| 						def id = Integer.parseInt(matcher[0][1]) | ||||
| 						def stream = new TxStream(db, id, matcher[0][2], matcher[0][3], backingDb) | ||||
| 						def stream = new TxStream(db, id, matcher[0][2], matcher[0][3]) | ||||
| 						streams<<stream | ||||
| 						streamsById[id]=stream | ||||
| 					} else if ((matcher = line =~ /^scv_tr_generator\s+\(ID\s+(\d+),\s+name\s+"([^"]+)",\s+scv_tr_stream\s+(\d+),$/)) { | ||||
| @@ -204,9 +186,6 @@ public class TextDbLoader implements IWaveformDbLoader{ | ||||
|  | ||||
| 			} | ||||
| 			lineCnt++ | ||||
| 			if((lineCnt%1000) == 0) { | ||||
| 				backingDb.commit() | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -43,15 +43,14 @@ class TxStream extends HierNode implements ITxStream { | ||||
| 	 | ||||
| 	private TreeMap<Long, List<ITxEvent>> events | ||||
| 	 | ||||
| 	TxStream(IWaveformDb db, int id, String name, String kind, DB backingStore){ | ||||
| 	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<Long, List<ITxEvent>>() | ||||
| 		events=backingStore.createTreeMap("stream-"+name) | ||||
| 		events = new TreeMap<Long, List<ITxEvent>>() | ||||
| 	} | ||||
|  | ||||
| 	List<ITxGenerator> getGenerators(){ | ||||
|   | ||||
| @@ -2,7 +2,7 @@ Manifest-Version: 1.0 | ||||
| Bundle-ManifestVersion: 2 | ||||
| Bundle-Name: SWT widget | ||||
| Bundle-SymbolicName: com.minres.scviewer.database.ui.swt | ||||
| Bundle-Version: 1.1.0.qualifier | ||||
| Bundle-Version: 2.0.0.qualifier | ||||
| Bundle-Vendor: MINRES Technologies GmbH | ||||
| Bundle-RequiredExecutionEnvironment: JavaSE-1.8 | ||||
| Require-Bundle: org.eclipse.swt;bundle-version="3.103.1", | ||||
| @@ -17,3 +17,4 @@ Export-Package: com.minres.scviewer.database.swt | ||||
| Bundle-ClassPath: . | ||||
| Bundle-ActivationPolicy: lazy | ||||
| Bundle-Activator: com.minres.scviewer.database.swt.DatabaseUiPlugin | ||||
| Automatic-Module-Name: com.minres.scviewer.database.ui.swt | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||
|   <modelVersion>4.0.0</modelVersion> | ||||
|   <artifactId>com.minres.scviewer.database.ui.swt</artifactId> | ||||
|   <version>2.0.0-SNAPSHOT</version> | ||||
|   <packaging>eclipse-plugin</packaging> | ||||
|   <parent> | ||||
|   	<groupId>com.minres.scviewer</groupId> | ||||
| @@ -8,5 +9,4 @@ | ||||
|   	<version>1.0.0-SNAPSHOT</version> | ||||
|   	<relativePath>../com.minres.scviewer.parent</relativePath> | ||||
|   </parent> | ||||
|   <version>1.1.0-SNAPSHOT</version> | ||||
| </project> | ||||
| @@ -10,6 +10,7 @@ | ||||
|  *******************************************************************************/ | ||||
| package com.minres.scviewer.database.swt.internal; | ||||
|  | ||||
| import java.util.Collection; | ||||
| import java.util.Map.Entry; | ||||
| import java.util.NavigableMap; | ||||
|  | ||||
| @@ -24,8 +25,9 @@ import org.eclipse.swt.graphics.Rectangle; | ||||
|  | ||||
| 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.ISignalChangeBit; | ||||
| import com.minres.scviewer.database.ISignalChangeBitVector; | ||||
| import com.minres.scviewer.database.ISignalChangeReal; | ||||
| import com.minres.scviewer.database.ui.TrackEntry; | ||||
| import com.minres.scviewer.database.ui.WaveformColors; | ||||
|  | ||||
| @@ -65,7 +67,6 @@ public class SignalPainter extends TrackPainter { | ||||
| 	private static final JPanel DUMMY_PANEL = new JPanel(); | ||||
|  | ||||
| 	private final WaveformCanvas waveCanvas; | ||||
| 	private ISignal<? extends ISignalChange> signal; | ||||
|  | ||||
| 	int yOffsetT; | ||||
| 	int yOffsetM; | ||||
| @@ -75,7 +76,6 @@ public class SignalPainter extends TrackPainter { | ||||
| 	public SignalPainter(WaveformCanvas txDisplay, boolean even, TrackEntry trackEntry) { | ||||
| 		super(trackEntry, even); | ||||
| 		this.waveCanvas = txDisplay; | ||||
| 		this.signal = trackEntry.getSignal(); | ||||
| 	} | ||||
|  | ||||
| 	private int getXEnd(long time) { | ||||
| @@ -84,6 +84,7 @@ public class SignalPainter extends TrackPainter { | ||||
| 	} | ||||
|  | ||||
| 	public void paintArea(GC gc, Rectangle area) { | ||||
| 		ISignal<? extends ISignalChange> signal = trackEntry.getSignal(); | ||||
| 		if (trackEntry.selected) | ||||
| 			gc.setBackground(this.waveCanvas.colors[WaveformColors.TRACK_BG_HIGHLITE.ordinal()]); | ||||
| 		else | ||||
| @@ -107,8 +108,6 @@ public class SignalPainter extends TrackPainter { | ||||
| 		NavigableMap<Long, ? extends ISignalChange> entries = signal.getEvents().subMap(first.getKey(), false, last.getKey(), true); | ||||
| 		SignalChange left = new SignalChange(first); | ||||
| 		SignalChange right = new SignalChange(entries.size() > 0 ? entries.firstEntry() : first); | ||||
| 		SignalStencil stencil = left.value instanceof ISignalChangeSingle ? new SingleBitStencil() : new MultiBitStencil(gc); | ||||
|  | ||||
| 		maxX = area.x + area.width; | ||||
| 		yOffsetT = this.waveCanvas.getTrackHeight() / 5 + area.y; | ||||
| 		yOffsetM = this.waveCanvas.getTrackHeight() / 2 + area.y; | ||||
| @@ -122,7 +121,6 @@ public class SignalPainter extends TrackPainter { | ||||
| 			// b) left to close to right | ||||
| 			if (left.time == right.time) { | ||||
| 				right.time = endTime; | ||||
|  | ||||
| 			} else { | ||||
| 				multiple = true; | ||||
| 				long eTime = (xBegin + 1) * this.waveCanvas.getScaleFactor(); | ||||
| @@ -132,6 +130,7 @@ public class SignalPainter extends TrackPainter { | ||||
| 			xEnd = getXEnd(right.time); | ||||
| 		} | ||||
|  | ||||
| 		SignalStencil stencil = getStencil(gc, left, entries); | ||||
| 		do { | ||||
| 			stencil.draw(gc, area, left.value, right.value, xBegin, xEnd, multiple); | ||||
| 			if (right.time >= endTime) | ||||
| @@ -144,12 +143,30 @@ public class SignalPainter extends TrackPainter { | ||||
| 			if (xEnd == xBegin) { | ||||
| 				multiple = true; | ||||
| 				long eTime = (xBegin + 1) * this.waveCanvas.getScaleFactor(); | ||||
| 				right.set(entries.floorEntry(eTime), endTime); | ||||
| 				Entry<Long, ? extends ISignalChange> entry = entries.floorEntry(eTime); | ||||
| 				if(entry!=null && entry.getKey()> right.time) | ||||
| 					right.set(entry, endTime); | ||||
| 				xEnd = getXEnd(eTime); | ||||
| 			} | ||||
| 		} while (left.time < endTime); | ||||
| 	} | ||||
|  | ||||
| 	private SignalStencil getStencil(GC gc, SignalChange left, NavigableMap<Long, ? extends ISignalChange> entries) { | ||||
| 		if(left.value instanceof ISignalChangeBit) | ||||
| 			return new SingleBitStencil(); | ||||
| 		else if (left.value instanceof ISignalChangeBitVector) | ||||
| 			if(trackEntry.waveDisplay==TrackEntry.WaveDisplay.DEFAULT) | ||||
| 				return new MultiBitStencil(gc); | ||||
| 			else | ||||
| 				return new MultiBitStencilAnalog(entries, left.value,  | ||||
| 						trackEntry.waveDisplay==TrackEntry.WaveDisplay.CONTINOUS, | ||||
| 						trackEntry.valueDisplay==TrackEntry.ValueDisplay.SIGNED); | ||||
| 		else if (left.value instanceof ISignalChangeReal) | ||||
| 			return new RealStencil(entries, left.value, trackEntry.waveDisplay==TrackEntry.WaveDisplay.CONTINOUS); | ||||
| 		else | ||||
| 			return null; | ||||
| 	} | ||||
|  | ||||
| 	private interface SignalStencil { | ||||
|  | ||||
| 		public void draw(GC gc, Rectangle area, ISignalChange left, ISignalChange right, int xBegin, int xEnd, boolean multiple); | ||||
| @@ -168,7 +185,7 @@ public class SignalPainter extends TrackPainter { | ||||
|  | ||||
| 		public void draw(GC gc, Rectangle area, ISignalChange left, ISignalChange right, int xBegin, int xEnd, boolean multiple) { | ||||
| 			Color colorBorder = waveCanvas.colors[WaveformColors.SIGNAL0.ordinal()]; | ||||
| 			ISignalChangeMulti last = (ISignalChangeMulti) left; | ||||
| 			ISignalChangeBitVector last = (ISignalChangeBitVector) left; | ||||
| 			if (last.getValue().toString().contains("X")) { | ||||
| 				colorBorder = waveCanvas.colors[WaveformColors.SIGNALX.ordinal()]; | ||||
| 			} else if (last.getValue().toString().contains("Z")) { | ||||
| @@ -187,7 +204,18 @@ public class SignalPainter extends TrackPainter { | ||||
| 				gc.setForeground(colorBorder); | ||||
| 				gc.drawPolygon(points); | ||||
| 				gc.setForeground(waveCanvas.colors[WaveformColors.SIGNAL_TEXT.ordinal()]); | ||||
| 				String label = "h'" + last.getValue().toHexString(); | ||||
| 				//TODO: this code should be provided from a central location | ||||
| 				String label = null; | ||||
| 				switch(trackEntry.valueDisplay) { | ||||
| 				case SIGNED: | ||||
| 					label=Long.toString(last.getValue().toSignedValue()); | ||||
| 					break; | ||||
| 				case UNSIGNED: | ||||
| 					label=Long.toString(last.getValue().toUnsignedValue()); | ||||
| 					break; | ||||
| 				default: | ||||
| 					label="h'"+last.getValue().toHexString(); | ||||
| 				} | ||||
| 				Point bb = getBoxWidth(gc, label); | ||||
| 				if (xBegin < area.x) { | ||||
| 					xBegin = area.x; | ||||
| @@ -211,16 +239,71 @@ public class SignalPainter extends TrackPainter { | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	private class MultiBitStencilAnalog implements SignalStencil { | ||||
|  | ||||
| 		final boolean continous; | ||||
| 		private long minVal; | ||||
| 		private long range; | ||||
|  | ||||
| 		@SuppressWarnings("unchecked") | ||||
| 		public MultiBitStencilAnalog(NavigableMap<Long, ? extends ISignalChange> entries, ISignalChange left, boolean continous, boolean signed) { | ||||
| 			this.continous=continous; | ||||
| 			Collection<ISignalChangeBitVector> values = ((NavigableMap<Long, ISignalChangeBitVector>) entries).values(); | ||||
| 			minVal=((ISignalChangeBitVector) left).getValue().toUnsignedValue(); | ||||
| 			range=2; | ||||
| 			if(!values.isEmpty()) { | ||||
| 				long maxVal=minVal; | ||||
| 				for (ISignalChange e : entries.values()) { | ||||
| 					long v = ((ISignalChangeBitVector)e).getValue().toUnsignedValue(); | ||||
| 					maxVal=Math.max(maxVal, v); | ||||
| 					minVal=Math.min(minVal, v); | ||||
| 				} | ||||
| 				if(maxVal==minVal) { | ||||
| 					maxVal--; | ||||
| 					minVal++; | ||||
| 				} | ||||
| 				range = maxVal-minVal; | ||||
| 			} else | ||||
| 				minVal--; | ||||
| 			 | ||||
| 		} | ||||
|  | ||||
| 		public void draw(GC gc, Rectangle area, ISignalChange left, ISignalChange right, int xBegin, int xEnd, boolean multiple) { | ||||
| 			long leftVal = ((ISignalChangeBitVector) left).getValue().toUnsignedValue(); | ||||
| 			long rightVal= ((ISignalChangeBitVector) right).getValue().toUnsignedValue(); | ||||
| 			gc.setForeground(waveCanvas.colors[WaveformColors.SIGNAL_REAL.ordinal()]); | ||||
| 			int yOffsetLeft = (int) ((leftVal-minVal) / range * (yOffsetB-yOffsetT)); | ||||
| 			int yOffsetRight = (int) ((rightVal-minVal) / range * (yOffsetB-yOffsetT)); | ||||
| 			if(continous) { | ||||
| 				if (xEnd > maxX) { | ||||
| 					gc.drawLine(xBegin, yOffsetB-yOffsetLeft, maxX, yOffsetB-yOffsetRight); | ||||
| 				} else { | ||||
| 					gc.drawLine(xBegin, yOffsetB-yOffsetLeft, xEnd, yOffsetB-yOffsetRight); | ||||
| 				} | ||||
| 			} else { | ||||
| 				if (xEnd > maxX) { | ||||
| 					gc.drawLine(xBegin, yOffsetB-yOffsetLeft, maxX, yOffsetB-yOffsetLeft); | ||||
| 				} else { | ||||
| 					gc.drawLine(xBegin, yOffsetB-yOffsetLeft, xEnd, yOffsetB-yOffsetLeft); | ||||
| 					if(yOffsetRight!=yOffsetLeft) { | ||||
| 						gc.drawLine(xEnd, yOffsetB-yOffsetLeft, xEnd, yOffsetB-yOffsetRight); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	private class SingleBitStencil implements SignalStencil { | ||||
| 		public void draw(GC gc, Rectangle area, ISignalChange left, ISignalChange right, int xBegin, int xEnd, boolean multiple) { | ||||
| 			if (multiple) { | ||||
| 				gc.setForeground(waveCanvas.colors[WaveformColors.SIGNALU.ordinal()]); | ||||
| 				gc.drawLine(xBegin, yOffsetT, xBegin, yOffsetB); | ||||
| 				gc.drawLine(xEnd, yOffsetT, xEnd, yOffsetB); | ||||
| 				if(xEnd>xBegin)  | ||||
| 					gc.drawLine(xEnd, yOffsetT, xEnd, yOffsetB); | ||||
| 			} else { | ||||
| 				Color color = waveCanvas.colors[WaveformColors.SIGNALX.ordinal()]; | ||||
| 				int yOffset = yOffsetM; | ||||
| 				switch (((ISignalChangeSingle) left).getValue()) { | ||||
| 				switch (((ISignalChangeBit) left).getValue()) { | ||||
| 				case '1': | ||||
| 					color = waveCanvas.colors[WaveformColors.SIGNAL1.ordinal()]; | ||||
| 					yOffset = yOffsetT; | ||||
| @@ -240,7 +323,7 @@ public class SignalPainter extends TrackPainter { | ||||
| 				} else { | ||||
| 					gc.drawLine(xBegin, yOffset, xEnd, yOffset); | ||||
| 					int yNext = yOffsetM; | ||||
| 					switch (((ISignalChangeSingle) right).getValue()) { | ||||
| 					switch (((ISignalChangeBit) right).getValue()) { | ||||
| 					case '1': | ||||
| 						yNext = yOffsetT; | ||||
| 						break; | ||||
| @@ -254,11 +337,87 @@ public class SignalPainter extends TrackPainter { | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	public ISignal<? extends ISignalChange> getSignal() { | ||||
| 		return signal; | ||||
| 	private class RealStencil implements SignalStencil { | ||||
|  | ||||
| 		double minVal, range; | ||||
| 		 | ||||
| 		final double scaleFactor = 1.05; | ||||
| 		 | ||||
| 		boolean continous=true; | ||||
| 		 | ||||
| 		@SuppressWarnings("unchecked") | ||||
| 		public RealStencil(NavigableMap<Long, ? extends ISignalChange> entries, ISignalChange left, boolean continous) { | ||||
| 			this.continous=continous; | ||||
| 			Collection<ISignalChangeReal> values = ((NavigableMap<Long, ISignalChangeReal>) entries).values(); | ||||
| 			minVal=((ISignalChangeReal) left).getValue(); | ||||
| 			range=2.0; | ||||
| 			if(!values.isEmpty()) { | ||||
| 				double maxVal=minVal; | ||||
| 				for (ISignalChange e : entries.values()) { | ||||
| 					double v = ((ISignalChangeReal)e).getValue(); | ||||
| 					if(Double.isNaN(maxVal)) | ||||
| 						maxVal=v; | ||||
| 					else if(!Double.isNaN(v)) | ||||
| 						maxVal=Math.max(maxVal, v); | ||||
| 					if(Double.isNaN(minVal)) | ||||
| 						minVal=v; | ||||
| 					else if(!Double.isNaN(v)) | ||||
| 						minVal=Math.min(minVal, v); | ||||
| 				} | ||||
| 				if(Double.isNaN(maxVal)){ | ||||
| 					maxVal=minVal=0.0; | ||||
| 				} | ||||
| 				range = (maxVal-minVal)*scaleFactor; | ||||
| 				double avg = (maxVal+minVal)/2.0; | ||||
| 				minVal=avg-(avg-minVal)*scaleFactor; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		public void draw(GC gc, Rectangle area, ISignalChange left, ISignalChange right, int xBegin, int xEnd, boolean multiple) { | ||||
| 			double leftVal = ((ISignalChangeReal) left).getValue(); | ||||
| 			double rightVal= ((ISignalChangeReal) right).getValue(); | ||||
| 			if(Double.isNaN(leftVal)) { | ||||
| 				Color color = waveCanvas.colors[WaveformColors.SIGNAL_NAN.ordinal()]; | ||||
| 				int width = xEnd - xBegin; | ||||
| 				if (width > 1) { | ||||
| 					int[] points = {  | ||||
| 							xBegin, yOffsetT,  | ||||
| 							xEnd,   yOffsetT,  | ||||
| 							xEnd,   yOffsetB,  | ||||
| 							xBegin, yOffsetB | ||||
| 					}; | ||||
| 					gc.setForeground(color); | ||||
| 					gc.drawPolygon(points); | ||||
| 					gc.setBackground(color); | ||||
| 					gc.fillPolygon(points); | ||||
| 				} else { | ||||
| 					gc.setForeground(color); | ||||
| 					gc.drawLine(xEnd, yOffsetT, xEnd, yOffsetB); | ||||
| 				} | ||||
| 			} else {				 | ||||
| 				gc.setForeground(waveCanvas.colors[WaveformColors.SIGNAL_REAL.ordinal()]); | ||||
| 				int yOffsetLeft = (int) ((leftVal-minVal) / range * (yOffsetB-yOffsetT)); | ||||
| 				int yOffsetRight = Double.isNaN(rightVal)?yOffsetLeft:(int) ((rightVal-minVal) / range * (yOffsetB-yOffsetT)); | ||||
| 				if(continous) { | ||||
| 					if (xEnd > maxX) { | ||||
| 						gc.drawLine(xBegin, yOffsetB-yOffsetLeft, maxX, yOffsetB-yOffsetRight); | ||||
| 					} else { | ||||
| 						gc.drawLine(xBegin, yOffsetB-yOffsetLeft, xEnd, yOffsetB-yOffsetRight); | ||||
| 					} | ||||
| 				} else { | ||||
| 					if (xEnd > maxX) { | ||||
| 						gc.drawLine(xBegin, yOffsetB-yOffsetLeft, maxX, yOffsetB-yOffsetLeft); | ||||
| 					} else { | ||||
| 						gc.drawLine(xBegin, yOffsetB-yOffsetLeft, xEnd, yOffsetB-yOffsetLeft); | ||||
| 						if(yOffsetRight!=yOffsetLeft) { | ||||
| 							gc.drawLine(xEnd, yOffsetB-yOffsetLeft, xEnd, yOffsetB-yOffsetRight); | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -110,6 +110,17 @@ public class StreamPainter extends TrackPainter{ | ||||
| 			gc.fillRectangle(bb); | ||||
| 			gc.drawRectangle(bb); | ||||
| 		} else { | ||||
| 			// adjusting drawing width to circumvent issues in canvas algos | ||||
| 			if(bb.x < area.x) { | ||||
| 				bb.width = bb.width-(area.x-bb.x)+5; | ||||
| 				bb.x=area.x-5; | ||||
| 			} | ||||
| 			int bb_x2 = bb.x+bb.width; | ||||
| 			int area_x2 = area.x+area.width; | ||||
| 			if(bb_x2>area_x2){ | ||||
| 				bb_x2=area_x2+5; | ||||
| 				bb.width= bb_x2-bb.x; | ||||
| 			} | ||||
| 		    gc.fillRoundRectangle(bb.x, bb.y, bb.width, bb.height, 5, 5); | ||||
| 		    gc.drawRoundRectangle(bb.x, bb.y, bb.width, bb.height, 5, 5); | ||||
| 		} | ||||
|   | ||||
| @@ -42,6 +42,7 @@ import com.minres.scviewer.database.IWaveform; | ||||
| import com.minres.scviewer.database.IWaveformEvent; | ||||
| import com.minres.scviewer.database.RelationType; | ||||
| import com.minres.scviewer.database.ui.IWaveformViewer; | ||||
| import com.minres.scviewer.database.ui.TrackEntry; | ||||
| import com.minres.scviewer.database.ui.WaveformColors; | ||||
|  | ||||
| public class WaveformCanvas extends Canvas { | ||||
| @@ -56,7 +57,7 @@ public class WaveformCanvas extends Canvas { | ||||
|      | ||||
|     private int level = 12; | ||||
|      | ||||
|     public final static String[] unitString={"fs", "ps", "ns", "µs", "ms"};//, "s"}; | ||||
|     public final static String[] unitString={"fs", "ps", "ns", "us", "ms"};//, "s"}; | ||||
|      | ||||
|     public final static int[] unitMultiplier={1, 3, 10, 30, 100, 300}; | ||||
|      | ||||
| @@ -126,6 +127,31 @@ public class WaveformCanvas extends Canvas { | ||||
| 		painterList.add(marker); | ||||
| 		cursorPainters.add(marker); | ||||
| 		wave2painterMap=new HashMap<>(); | ||||
|     	// fall back initialization | ||||
|         colors[WaveformColors.LINE.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED); | ||||
|         colors[WaveformColors.LINE_HIGHLITE.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_CYAN); | ||||
|         colors[WaveformColors.TRACK_BG_EVEN.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_BLACK); | ||||
|         colors[WaveformColors.TRACK_BG_ODD.ordinal()] = SWTResourceManager.getColor(40, 40, 40); | ||||
|         colors[WaveformColors.TRACK_BG_HIGHLITE.ordinal()] = SWTResourceManager.getColor(40, 40, 80); | ||||
|         colors[WaveformColors.TX_BG.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GREEN); | ||||
|         colors[WaveformColors.TX_BG_HIGHLITE.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN); | ||||
|         colors[WaveformColors.TX_BORDER.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED); | ||||
|         colors[WaveformColors.SIGNAL0.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GREEN); | ||||
|         colors[WaveformColors.SIGNAL1.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GREEN); | ||||
|         colors[WaveformColors.SIGNALZ.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_YELLOW); | ||||
|         colors[WaveformColors.SIGNALX.ordinal()] = SWTResourceManager.getColor(255,  51,  51); | ||||
|         colors[WaveformColors.SIGNALU.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_YELLOW); | ||||
|         colors[WaveformColors.SIGNAL_TEXT.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_WHITE); | ||||
|         colors[WaveformColors.SIGNAL_REAL.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_YELLOW); | ||||
|         colors[WaveformColors.SIGNAL_NAN.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED); | ||||
|         colors[WaveformColors.CURSOR.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED); | ||||
|         colors[WaveformColors.CURSOR_DRAG.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GRAY); | ||||
|         colors[WaveformColors.CURSOR_TEXT.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_WHITE); | ||||
|         colors[WaveformColors.MARKER.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_GRAY); | ||||
|         colors[WaveformColors.MARKER_TEXT.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_WHITE); | ||||
|         colors[WaveformColors.REL_ARROW.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_MAGENTA); | ||||
|         colors[WaveformColors.REL_ARROW_HIGHLITE.ordinal()] = SWTResourceManager.getColor(255, 128, 255); | ||||
|  | ||||
|     } | ||||
|  | ||||
| 	public void addCursoPainter(CursorPainter cursorPainter){ | ||||
| @@ -137,33 +163,10 @@ public class WaveformCanvas extends Canvas { | ||||
|         Display d = getDisplay(); | ||||
|         if (colourMap != null) { | ||||
|             for (WaveformColors c : WaveformColors.values()) { | ||||
|                 if (colourMap.containsKey(c)) { | ||||
|                 if (colourMap.containsKey(c)) | ||||
|                     colors[c.ordinal()] = new Color(d, colourMap.get(c)); | ||||
|                 } | ||||
|             } | ||||
|             redraw(); | ||||
|         } else { | ||||
|             colors[WaveformColors.LINE.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED); | ||||
|             colors[WaveformColors.LINE_HIGHLITE.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_CYAN); | ||||
|             colors[WaveformColors.TRACK_BG_EVEN.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_BLACK); | ||||
|             colors[WaveformColors.TRACK_BG_ODD.ordinal()] = SWTResourceManager.getColor(40, 40, 40); | ||||
|             colors[WaveformColors.TRACK_BG_HIGHLITE.ordinal()] = SWTResourceManager.getColor(40, 40, 80); | ||||
|             colors[WaveformColors.TX_BG.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GREEN); | ||||
|             colors[WaveformColors.TX_BG_HIGHLITE.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN); | ||||
|             colors[WaveformColors.TX_BORDER.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED); | ||||
|             colors[WaveformColors.SIGNAL0.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN); | ||||
|             colors[WaveformColors.SIGNAL1.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN); | ||||
|             colors[WaveformColors.SIGNALZ.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_YELLOW); | ||||
|             colors[WaveformColors.SIGNALX.ordinal()] = SWTResourceManager.getColor(255,  51,  51); | ||||
|             colors[WaveformColors.SIGNALU.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_YELLOW); | ||||
|             colors[WaveformColors.SIGNAL_TEXT.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_WHITE); | ||||
|             colors[WaveformColors.CURSOR.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED); | ||||
|             colors[WaveformColors.CURSOR_DRAG.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GRAY); | ||||
|             colors[WaveformColors.CURSOR_TEXT.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_WHITE); | ||||
|             colors[WaveformColors.MARKER.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_GRAY); | ||||
|             colors[WaveformColors.MARKER_TEXT.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_WHITE); | ||||
|             colors[WaveformColors.REL_ARROW.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_MAGENTA); | ||||
|             colors[WaveformColors.REL_ARROW_HIGHLITE.ordinal()] = SWTResourceManager.getColor(255, 128, 255); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -179,6 +182,9 @@ public class WaveformCanvas extends Canvas { | ||||
|         return origin; | ||||
|     } | ||||
|  | ||||
|     public int getWidth() { | ||||
|     	return getClientArea().width;  | ||||
|     } | ||||
|     public void setOrigin(Point origin) { | ||||
|         setOrigin(origin.x, origin.y); | ||||
|     } | ||||
| @@ -290,9 +296,13 @@ public class WaveformCanvas extends Canvas { | ||||
|     } | ||||
|  | ||||
|     public void addWaveformPainter(IWaveformPainter painter) { | ||||
|     	addWaveformPainter(painter, true); | ||||
|     } | ||||
|      | ||||
|     void addWaveformPainter(IWaveformPainter painter, boolean update) { | ||||
|         trackAreaPainter.addTrackPainter(painter); | ||||
|         wave2painterMap.put(painter.getTrackEntry().waveform, painter); | ||||
|         syncScrollBars(); | ||||
|         if(update) syncScrollBars(); | ||||
|     } | ||||
|  | ||||
|     public List<CursorPainter> getCursorPainters() { | ||||
| @@ -309,7 +319,7 @@ public class WaveformCanvas extends Canvas { | ||||
|         super.dispose(); | ||||
|     } | ||||
|  | ||||
|     /* Initalize the scrollbar and register listeners. */ | ||||
|     /* Initialize the scrollbar and register listeners. */ | ||||
|     private void initScrollBars() { | ||||
|         ScrollBar horizontal = getHorizontalBar(); | ||||
|         horizontal.setEnabled(false); | ||||
| @@ -467,6 +477,27 @@ public class WaveformCanvas extends Canvas { | ||||
|         } | ||||
|     } | ||||
|      | ||||
| 	public void reveal(IWaveform<? extends IWaveformEvent> waveform) { | ||||
|         for (IWaveformPainter painter : wave2painterMap.values()) { | ||||
|         	TrackEntry te = painter.getTrackEntry(); | ||||
|         	if(te.waveform == waveform) { | ||||
|                 Point size = getSize(); | ||||
|                 //size.x -= getVerticalBar().getSize().x + 2; | ||||
|                 size.y -=+rulerHeight; | ||||
|                 ScrollBar sb = getHorizontalBar(); | ||||
|                 if((sb.getStyle()&SWT.SCROLLBAR_OVERLAY)!=0 && sb.isVisible()) // TODO: check on other platform than MacOSX | ||||
|                 	size.y-=  getHorizontalBar().getSize().y; | ||||
|                 int top = te.vOffset; | ||||
|                 int bottom = top + trackHeight; | ||||
|                 if (top < -origin.y) { | ||||
|                     setOrigin(origin.x, -(top-trackHeight)); | ||||
|                 } else if (bottom > (size.y - origin.y)) { | ||||
|                     setOrigin(origin.x, size.y - bottom); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 	} | ||||
|  | ||||
|     public void reveal(long time) { | ||||
|         int scaledTime = (int) (time / scaleFactor); | ||||
|         Point size = getSize(); | ||||
| @@ -511,4 +542,11 @@ public class WaveformCanvas extends Canvas { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     long getMaxVisibleTime() { | ||||
|     	return (getClientArea().width+origin.x)*scaleFactor; | ||||
|     } | ||||
|  | ||||
|     long getOriginTime() { | ||||
|     	return origin.x * scaleFactor; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -66,13 +66,15 @@ import org.eclipse.swt.widgets.Label; | ||||
| import org.eclipse.swt.widgets.Listener; | ||||
| import org.eclipse.swt.widgets.Menu; | ||||
| import org.eclipse.swt.widgets.ScrollBar; | ||||
| import org.eclipse.swt.widgets.Widget; | ||||
| import org.eclipse.wb.swt.SWTResourceManager; | ||||
|  | ||||
| import com.google.common.collect.Lists; | ||||
| 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.ISignalChangeBitVector; | ||||
| import com.minres.scviewer.database.ISignalChangeReal; | ||||
| import com.minres.scviewer.database.ISignalChangeBit; | ||||
| import com.minres.scviewer.database.ITx; | ||||
| import com.minres.scviewer.database.ITxEvent; | ||||
| import com.minres.scviewer.database.ITxRelation; | ||||
| @@ -102,12 +104,14 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
|  | ||||
| 	private Control namePaneHeader; | ||||
|  | ||||
| 	private Canvas nameList; | ||||
| 	final private Canvas nameList; | ||||
|  | ||||
| 	private Canvas valueList; | ||||
| 	final private Canvas valueList; | ||||
|  | ||||
| 	WaveformCanvas waveformCanvas; | ||||
| 	final WaveformCanvas waveformCanvas; | ||||
|  | ||||
| 	private boolean revealSelected=false; | ||||
| 	 | ||||
| 	private Composite top; | ||||
|  | ||||
| 	protected ObservableList<TrackEntry> streams; | ||||
| @@ -118,19 +122,16 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
|  | ||||
| 	private TreeMap<Integer, TrackEntry> trackVerticalOffset; | ||||
|  | ||||
| 	private HashMap<IWaveform<? extends IWaveformEvent>, String> actualValues; | ||||
|  | ||||
| 	private Font nameFont, nameFontB; | ||||
|  | ||||
| 	protected MouseListener nameValueMouseListener = new MouseAdapter() { | ||||
| 		@Override | ||||
| 		public void mouseDown(MouseEvent e) { | ||||
| 			if ((e.button == 1 || e.button == 3)) { | ||||
| 			if (e.button == 1) { | ||||
| 				Entry<Integer, TrackEntry> entry = trackVerticalOffset.floorEntry(e.y); | ||||
| 				if (entry != null) | ||||
| 					setSelection(new StructuredSelection(entry.getValue())); | ||||
| 			}  | ||||
| 			if (e.button == 3) { | ||||
| 			} else if (e.button == 3) { | ||||
| 				Menu topMenu= top.getMenu(); | ||||
| 				if(topMenu!=null) topMenu.setVisible(true); | ||||
| 			} | ||||
| @@ -144,12 +145,10 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
| 		@Override | ||||
| 		public void mouseDown(MouseEvent e) { | ||||
| 			start=new Point(e.x, e.y); | ||||
| 			if((e.stateMask&SWT.MODIFIER_MASK)!=0) return; //don't react on modifier | ||||
| 			if (e.button ==  1) {	 | ||||
| 				initialSelected = waveformCanvas.getClicked(start); | ||||
| 			} else if (e.button == 3) { | ||||
| 				List<Object> hitted = waveformCanvas.getClicked(start); | ||||
| 				if(hitted!=null && hitted.size()>0) | ||||
| 					setSelection(new StructuredSelection(hitted)); | ||||
| 				Menu topMenu= top.getMenu(); | ||||
| 				if(topMenu!=null) topMenu.setVisible(true); | ||||
| 			} | ||||
| @@ -157,29 +156,18 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
|  | ||||
| 		@Override | ||||
| 		public void mouseUp(MouseEvent e) { | ||||
| 			if (e.button ==  1) { | ||||
| 			if((e.stateMask&SWT.MODIFIER_MASK&~SWT.SHIFT)!=0) return; //don't react on modifier | ||||
| 			if (e.button ==  1 && ((e.stateMask&SWT.SHIFT)==0)) { | ||||
| 				if(Math.abs(e.x-start.x)<3 && Math.abs(e.y-start.y)<3){				 | ||||
| 					// first set time | ||||
| 					// first set cursor time | ||||
| 					setCursorTime(snapOffsetToEvent(e)); | ||||
| 					// then set selection and reveal | ||||
| 					setSelection(new StructuredSelection(initialSelected)); | ||||
| 					e.widget.getDisplay().asyncExec(new Runnable() { | ||||
| 						@Override | ||||
| 						public void run() { | ||||
| 							waveformCanvas.redraw(); | ||||
| 							updateValueList(); | ||||
| 						} | ||||
| 					}); | ||||
| 					asyncUpdate(e.widget); | ||||
| 				} | ||||
| 			}else	if (e.button ==  2) { | ||||
| 			}else if (e.button ==  2 ||(e.button==1 && (e.stateMask&SWT.SHIFT)!=0)) { | ||||
| 				setMarkerTime(snapOffsetToEvent(e), selectedMarker); | ||||
| 				e.widget.getDisplay().asyncExec(new Runnable() { | ||||
| 					@Override | ||||
| 					public void run() { | ||||
| 						waveformCanvas.redraw(); | ||||
| 						updateValueList(); | ||||
| 					} | ||||
| 				}); | ||||
| 				asyncUpdate(e.widget); | ||||
| 			}         | ||||
| 		} | ||||
|  | ||||
| @@ -225,7 +213,6 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
|  | ||||
| 		trackVerticalOffset = new TreeMap<Integer, TrackEntry>(); | ||||
| 		trackVerticalHeight=0; | ||||
| 		actualValues = new HashMap<IWaveform<? extends IWaveformEvent>, String>(); | ||||
|  | ||||
| 		nameFont = parent.getDisplay().getSystemFont(); | ||||
| 		nameFontB = SWTResourceManager.getBoldFont(nameFont); | ||||
| @@ -273,9 +260,11 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
| 		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); | ||||
| 				if(!trackVerticalOffset.isEmpty()) { | ||||
| 					GC gc = event.gc; | ||||
| 					Rectangle rect = ((Canvas) event.widget).getClientArea(); | ||||
| 					paintNames(gc, rect); | ||||
| 				} | ||||
| 			} | ||||
| 		}); | ||||
| 		nameList.addMouseListener(nameValueMouseListener); | ||||
| @@ -305,9 +294,11 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
| 		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); | ||||
| 				if(!trackVerticalOffset.isEmpty()) { | ||||
| 					GC gc = event.gc; | ||||
| 					Rectangle rect = ((Canvas) event.widget).getClientArea(); | ||||
| 					paintValues(gc, rect); | ||||
| 				} | ||||
| 			} | ||||
| 		}); | ||||
| 		valueList.addMouseListener(nameValueMouseListener); | ||||
| @@ -315,7 +306,7 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
|  | ||||
| 		waveformCanvas.setMaxTime(1); | ||||
| 		waveformCanvas.addMouseListener(waveformMouseListener); | ||||
|  | ||||
| 		 | ||||
| 		nameListScrolled.getVerticalBar().addSelectionListener(new SelectionAdapter() { | ||||
| 			public void widgetSelected(SelectionEvent e) { | ||||
| 				int y = ((ScrollBar) e.widget).getSelection(); | ||||
| @@ -377,22 +368,33 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
| 	@Override | ||||
| 	public void propertyChange(PropertyChangeEvent pce) { | ||||
| 		if ("size".equals(pce.getPropertyName()) || "content".equals(pce.getPropertyName())) { | ||||
| 			if(revealSelected) { | ||||
| 				waveformCanvas.getDisplay().asyncExec(new Runnable() { | ||||
| 					@Override | ||||
| 					public void run() { | ||||
| 						update(); | ||||
| 						waveformCanvas.reveal(currentWaveformSelection.waveform); | ||||
| 						valueList.redraw(); | ||||
| 						nameList.redraw(); | ||||
| 					} | ||||
| 				}); | ||||
| 				revealSelected=false; | ||||
| 			} else  | ||||
| 			waveformCanvas.getDisplay().asyncExec(new Runnable() { | ||||
| 				@Override | ||||
| 				public void run() { | ||||
| 					updateTracklist(); | ||||
| 					update(); | ||||
| 				} | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	protected void updateTracklist() { | ||||
| 	public void update() { | ||||
| 		trackVerticalHeight = 0; | ||||
| 		int nameMaxWidth = 0; | ||||
| 		int previousHeight = trackVerticalOffset.size() == 0 ? 0 : trackVerticalOffset.lastKey(); | ||||
| 		IWaveformPainter painter = null; | ||||
| 		trackVerticalOffset.clear(); | ||||
| 		actualValues.clear(); | ||||
| 		waveformCanvas.clearAllWaveformPainter(); | ||||
| 		boolean even = true; | ||||
| 		boolean clearSelection = true; | ||||
| @@ -403,20 +405,21 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
| 			streamEntry.vOffset=trackVerticalHeight; | ||||
| 			clearSelection &= currentWaveformSelection!=null && (streamEntry.waveform != currentWaveformSelection.waveform); | ||||
| 			if (streamEntry.isStream()) { | ||||
| 				streamEntry.currentValue=""; | ||||
| 				streamEntry.height *= streamEntry.getStream().getMaxConcurrency(); | ||||
| 				painter = new StreamPainter(waveformCanvas, even, streamEntry); | ||||
| 				actualValues.put(streamEntry.waveform, ""); | ||||
| 			} else if (streamEntry.isSignal()) { | ||||
| 				streamEntry.currentValue="---"; | ||||
| 				painter = new SignalPainter(waveformCanvas, even, streamEntry); | ||||
| 				actualValues.put(streamEntry.waveform, "---"); | ||||
| 			} | ||||
| 			waveformCanvas.addWaveformPainter(painter); | ||||
| 			waveformCanvas.addWaveformPainter(painter, false); | ||||
| 			trackVerticalOffset.put(trackVerticalHeight, streamEntry); | ||||
| 			tl.setText(streamEntry.waveform.getFullName()); | ||||
| 			nameMaxWidth = Math.max(nameMaxWidth, tl.getBounds().width); | ||||
| 			trackVerticalHeight += streamEntry.height; | ||||
| 			even = !even; | ||||
| 		} | ||||
| 		waveformCanvas.syncScrollBars(); | ||||
| 		nameList.setSize(nameMaxWidth + 15, trackVerticalHeight); | ||||
| 		nameListScrolled.setMinSize(nameMaxWidth + 15, trackVerticalHeight); | ||||
| 		valueList.setSize(calculateValueWidth(), trackVerticalHeight); | ||||
| @@ -436,14 +439,15 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
|         for(Entry<Integer, IWaveform<? extends IWaveformEvent>> entry: trackVerticalOffset.entrySet()){ | ||||
|         	System.out.println("    "+entry.getKey()+": " +entry.getValue().getFullName()); | ||||
|         } | ||||
| 		 */    } | ||||
| 		 */     | ||||
| 	} | ||||
|  | ||||
| 	private int calculateValueWidth() { | ||||
| 		TextLayout tl = new TextLayout(waveformCanvas.getDisplay()); | ||||
| 		tl.setFont(nameFontB); | ||||
| 		int valueMaxWidth = 0; | ||||
| 		for (String v : actualValues.values()) { | ||||
| 			tl.setText(v); | ||||
| 		for (TrackEntry v : streams) { | ||||
| 			tl.setText(v.currentValue); | ||||
| 			valueMaxWidth = Math.max(valueMaxWidth, tl.getBounds().width); | ||||
| 		} | ||||
| 		return valueMaxWidth + 15; | ||||
| @@ -451,16 +455,32 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
|  | ||||
| 	private void updateValueList(){ | ||||
| 		final Long time = getCursorTime(); | ||||
| 		for(Entry<IWaveform<? extends IWaveformEvent>, String> entry:actualValues.entrySet()){ | ||||
| 			if(entry.getKey() instanceof ISignal){     | ||||
| 				ISignalChange event = ((ISignal<?>)entry.getKey()).getWaveformEventsBeforeTime(time); | ||||
| 				if(event instanceof ISignalChangeSingle){ | ||||
| 					entry.setValue("b'"+((ISignalChangeSingle)event).getValue()); | ||||
| 				} else if(event instanceof ISignalChangeMulti){ | ||||
| 					entry.setValue("h'"+((ISignalChangeMulti)event).getValue().toHexString()); | ||||
| 		for(TrackEntry entry:streams){ | ||||
| 			if(entry.isSignal()){     | ||||
| 				ISignalChange event = ((ISignal<?>)entry.waveform).getWaveformEventsBeforeTime(time); | ||||
| 				if(event instanceof ISignalChangeBit){ | ||||
| 					entry.currentValue="b'"+((ISignalChangeBit)event).getValue(); | ||||
| 				} else if(event instanceof ISignalChangeBitVector){ | ||||
| 					// TODO: same code resides in SignalPainter, fix it | ||||
| 					switch(entry.valueDisplay) { | ||||
| 					case SIGNED: | ||||
| 						entry.currentValue=Long.toString(((ISignalChangeBitVector)event).getValue().toSignedValue()); | ||||
| 						break;						 | ||||
| 					case UNSIGNED: | ||||
| 						entry.currentValue=Long.toString(((ISignalChangeBitVector)event).getValue().toUnsignedValue()); | ||||
| 						break; | ||||
| 					default: | ||||
| 						entry.currentValue="h'"+((ISignalChangeBitVector)event).getValue().toHexString(); | ||||
| 					} | ||||
| 				} else if(event instanceof ISignalChangeReal){ | ||||
| 					double val = ((ISignalChangeReal)event).getValue(); | ||||
| 					if(val>0.001) | ||||
| 						entry.currentValue=String.format("%1$,.3f", val); | ||||
| 					else | ||||
| 						entry.currentValue=Double.toString(val); | ||||
| 				} | ||||
| 			} else if(entry.getKey() instanceof ITxStream<?>){ | ||||
| 				ITxStream<?> stream = (ITxStream<?>) entry.getKey(); | ||||
| 			} else if(entry.isStream()){ | ||||
| 				ITxStream<?> stream = (ITxStream<?>) entry.waveform; | ||||
| 				ITx[] resultsList = new ITx[stream.getMaxConcurrency()]; | ||||
| 				Entry<Long, List<ITxEvent>> firstTx=stream.getEvents().floorEntry(time); | ||||
| 				if(firstTx!=null){ | ||||
| @@ -482,7 +502,7 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
| 							value+="|"; | ||||
| 						if(o!=null) value+=((ITx)o).getGenerator().getName(); | ||||
| 					} | ||||
| 					entry.setValue(value); | ||||
| 					entry.currentValue=value; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| @@ -549,11 +569,13 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
| 	 */ | ||||
| 	@Override | ||||
| 	public ISelection getSelection() { | ||||
| 		if (currentTxSelection != null) | ||||
| 			return new StructuredSelection(currentTxSelection); | ||||
| 		else if (currentWaveformSelection != null) | ||||
| 			return new StructuredSelection(currentWaveformSelection.waveform); | ||||
| 		else | ||||
| 		if (currentTxSelection != null) { | ||||
| 			Object[] elem = {currentTxSelection, currentWaveformSelection}; | ||||
| 			return new StructuredSelection(elem); | ||||
| 		} else if (currentWaveformSelection != null) { | ||||
| 			Object[] elem = {currentWaveformSelection.waveform, currentWaveformSelection}; | ||||
| 			return new StructuredSelection(elem); | ||||
| 		} else | ||||
| 			return new StructuredSelection(); | ||||
| 	} | ||||
|  | ||||
| @@ -593,6 +615,7 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
| 						currentWaveformSelection = (TrackEntry) sel; | ||||
| 						if(currentTxSelection!=null && currentTxSelection.getStream()!=currentWaveformSelection) | ||||
| 							currentTxSelection=null; | ||||
| 						 | ||||
| 						selectionChanged = true; | ||||
| 					}            		 | ||||
| 				} | ||||
| @@ -605,6 +628,7 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
| 		} | ||||
| 		if(currentWaveformSelection!=null) currentWaveformSelection.selected=true; | ||||
| 		if (selectionChanged) { | ||||
| 			waveformCanvas.reveal(currentWaveformSelection.waveform); | ||||
| 			waveformCanvas.setSelected(currentTxSelection); | ||||
| 			valueList.redraw(); | ||||
| 			nameList.redraw(); | ||||
| @@ -628,7 +652,16 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
| 	 */ | ||||
| 	@Override | ||||
| 	public void moveSelection(GotoDirection direction) { | ||||
| 		moveSelection(direction, NEXT_PREV_IN_STREAM) ; | ||||
| 		if(direction==GotoDirection.NEXT || direction==GotoDirection.PREV) | ||||
| 			moveSelection(direction, NEXT_PREV_IN_STREAM) ; | ||||
| 		else { | ||||
| 			int idx = streams.indexOf(currentWaveformSelection); | ||||
| 			if(direction==GotoDirection.UP && idx>0) { | ||||
| 				setSelection(new StructuredSelection(streams.get(idx-1))); | ||||
| 			} else if(direction==GotoDirection.DOWN && idx<(streams.size()-1)) { | ||||
| 				setSelection(new StructuredSelection(streams.get(idx+1))); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* (non-Javadoc) | ||||
| @@ -738,6 +771,7 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
| 				setCursorTime(time); | ||||
| 				waveformCanvas.reveal(time); | ||||
| 				waveformCanvas.redraw(); | ||||
| 				updateValueList(); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| @@ -757,17 +791,21 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
| 	@Override | ||||
| 	public void moveSelectedTrack(int i) { | ||||
| 		if(currentWaveformSelection!=null){ | ||||
| 			ITx selectedTx=currentTxSelection; | ||||
| 			TrackEntry selectedWaveform=currentWaveformSelection; | ||||
| 			int idx = streams.indexOf(currentWaveformSelection); | ||||
| 			int newIdx=idx+i; | ||||
| 			if(newIdx>=0 && newIdx<streams.size()){ | ||||
| 				Collections.swap(streams,idx,newIdx); | ||||
| 				updateTracklist(); | ||||
| 				if(selectedTx!=null){ | ||||
| 					setSelection(new StructuredSelection(new Object[]{selectedTx, selectedWaveform.waveform})); | ||||
| 				} else | ||||
| 					setSelection(new StructuredSelection(selectedWaveform.waveform)); | ||||
| 				revealSelected=true; | ||||
| //				update(); | ||||
| //				ITx selectedTx=currentTxSelection; | ||||
| //				if(selectedTx!=null){ | ||||
| //					setSelection(new StructuredSelection(new Object[]{selectedTx, currentWaveformSelection.waveform})); | ||||
| //				} else { | ||||
| //					setSelection(new StructuredSelection(currentWaveformSelection.waveform)); | ||||
| //				} | ||||
| //				waveformCanvas.reveal(currentWaveformSelection.waveform); | ||||
| //				valueList.redraw(); | ||||
| //				nameList.redraw(); | ||||
| 			} | ||||
| 		}	 | ||||
| 	} | ||||
| @@ -813,7 +851,7 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
| 					IWaveform<? extends IWaveformEvent> w = trackEntry.waveform; | ||||
| 					if (w instanceof ITxStream<?>) | ||||
| 						subArea.height *= ((ITxStream<?>) w).getMaxConcurrency(); | ||||
| 					drawValue(gc, subArea, firstKey, actualValues.get(w), trackEntry.selected); | ||||
| 					drawValue(gc, subArea, firstKey, trackEntry.currentValue, trackEntry.selected); | ||||
| 				} else { | ||||
| 					for (Entry<Integer, TrackEntry> entry : trackVerticalOffset.subMap(firstKey, true, lastKey, true) | ||||
| 							.entrySet()) { | ||||
| @@ -821,7 +859,7 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
| 						subArea.height = waveformCanvas.getTrackHeight(); | ||||
| 						if (w instanceof ITxStream<?>) | ||||
| 							subArea.height *= ((ITxStream<?>) w).getMaxConcurrency(); | ||||
| 						drawValue(gc, subArea, entry.getKey(), actualValues.get(w), entry.getValue().selected); | ||||
| 						drawValue(gc, subArea, entry.getKey(), entry.getValue().currentValue, entry.getValue().selected); | ||||
| 					} | ||||
| 				} | ||||
| 			}catch(NoSuchElementException e){} | ||||
| @@ -989,7 +1027,7 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
| 							else | ||||
| 								streams.add(tgtIdx, srcWave); | ||||
| 							currentWaveformSelection=srcWave; | ||||
| 							updateTracklist(); | ||||
| 							update(); | ||||
| 						} else if(source instanceof CursorPainter){ | ||||
| 							((CursorPainter)source).setTime(0); | ||||
| 							updateValueList(); | ||||
| @@ -1182,4 +1220,31 @@ public class WaveformViewer implements IWaveformViewer  { | ||||
| 		origin.x=(int) (-time/waveformCanvas.getScaleFactorPow10());	 | ||||
| 		waveformCanvas.setOrigin(origin); | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public void scrollHorizontal(int percent) { | ||||
| 		if(percent<-100) percent=-100; | ||||
| 		if(percent>100) percent=100; | ||||
| 		int diff = (waveformCanvas.getWidth()*percent)/100; | ||||
| //		ScrollBar sb = waveformCanvas.getHorizontalBar(); | ||||
| //		int x = sb.getSelection(); | ||||
| //		System.out.println("Setting sb to "+ (x+diff)); | ||||
| //		if((x+diff)>0) | ||||
| //			sb.setSelection(x+diff); | ||||
| //		else | ||||
| //			sb.setSelection(0); | ||||
| 		Point o = waveformCanvas.getOrigin(); | ||||
| 		waveformCanvas.setOrigin(o.x-diff, o.y); | ||||
| 		waveformCanvas.redraw(); | ||||
| 	} | ||||
|  | ||||
| 	public void asyncUpdate(Widget widget) { | ||||
| 		widget.getDisplay().asyncExec(new Runnable() { | ||||
| 			@Override | ||||
| 			public void run() { | ||||
| 				waveformCanvas.redraw(); | ||||
| 				updateValueList(); | ||||
| 			} | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -2,9 +2,10 @@ Manifest-Version: 1.0 | ||||
| Bundle-ManifestVersion: 2 | ||||
| Bundle-Name: Database UI | ||||
| Bundle-SymbolicName: com.minres.scviewer.database.ui | ||||
| Bundle-Version: 1.0.0.qualifier | ||||
| Bundle-Version: 2.0.0.qualifier | ||||
| Bundle-Vendor: MINRES Technologies GmbH | ||||
| Bundle-RequiredExecutionEnvironment: JavaSE-1.8 | ||||
| Export-Package: com.minres.scviewer.database.ui | ||||
| Require-Bundle: com.minres.scviewer.database, | ||||
|  org.eclipse.jface | ||||
| Automatic-Module-Name: com.minres.scviewer.database.ui | ||||
|   | ||||
| @@ -1,12 +1,12 @@ | ||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||
|   <modelVersion>4.0.0</modelVersion> | ||||
|   <artifactId>com.minres.scviewer.database.ui</artifactId> | ||||
|   <version>1.0.0-SNAPSHOT</version> | ||||
|   <version>2.0.0-SNAPSHOT</version> | ||||
|   <packaging>eclipse-plugin</packaging> | ||||
|   <parent> | ||||
|   	<groupId>com.minres.scviewer</groupId> | ||||
|   	<artifactId>com.minres.scviewer.parent</artifactId> | ||||
|   	<version>1.0.0-SNAPSHOT</version> | ||||
|   	<version>2.0.0-SNAPSHOT</version> | ||||
|   	<relativePath>../com.minres.scviewer.parent</relativePath> | ||||
|   </parent> | ||||
|   </project> | ||||
| @@ -34,6 +34,8 @@ public interface IWaveformViewer extends PropertyChangeListener, ISelectionProvi | ||||
| 	public void addSelectionChangedListener(ISelectionChangedListener listener); | ||||
|  | ||||
| 	public void removeSelectionChangedListener(ISelectionChangedListener listener); | ||||
| 	 | ||||
| 	public void update(); | ||||
|  | ||||
| 	public Control getControl(); | ||||
|  | ||||
| @@ -100,4 +102,6 @@ public interface IWaveformViewer extends PropertyChangeListener, ISelectionProvi | ||||
| 	public long getBaselineTime(); | ||||
|  | ||||
| 	public void setBaselineTime(Long scale); | ||||
| 	 | ||||
| 	public void scrollHorizontal(int percent); | ||||
| } | ||||
| @@ -17,7 +17,17 @@ import com.minres.scviewer.database.ITxStream; | ||||
| import com.minres.scviewer.database.IWaveform; | ||||
| import com.minres.scviewer.database.IWaveformEvent; | ||||
|  | ||||
|  | ||||
| public class TrackEntry { | ||||
| 	public enum ValueDisplay { | ||||
| 		DEFAULT, SIGNED, UNSIGNED | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	public enum WaveDisplay { | ||||
| 		DEFAULT, STEP_WISE, CONTINOUS | ||||
| 	} | ||||
|  | ||||
| 	final public IWaveform<? extends IWaveformEvent> waveform; | ||||
|  | ||||
| 	public int vOffset; | ||||
| @@ -26,6 +36,12 @@ public class TrackEntry { | ||||
|  | ||||
| 	public boolean selected; | ||||
| 	 | ||||
| 	public String currentValue=""; | ||||
| 	 | ||||
| 	public ValueDisplay valueDisplay = ValueDisplay.DEFAULT; | ||||
| 	 | ||||
| 	public WaveDisplay waveDisplay = WaveDisplay.DEFAULT; | ||||
| 	 | ||||
| 	public TrackEntry(IWaveform<? extends IWaveformEvent> waveform) { | ||||
| 		this.waveform = waveform; | ||||
| 		vOffset=0; | ||||
|   | ||||
| @@ -14,7 +14,7 @@ public enum WaveformColors { | ||||
|     LINE, LINE_HIGHLITE,  | ||||
|     TRACK_BG_EVEN, TRACK_BG_ODD, TRACK_BG_HIGHLITE,  | ||||
|     TX_BG, TX_BG_HIGHLITE, TX_BORDER, | ||||
|     SIGNAL0, SIGNAL1, SIGNALZ, SIGNALX, SIGNALU, SIGNAL_TEXT,  | ||||
|     SIGNAL0, SIGNAL1, SIGNALZ, SIGNALX, SIGNALU, SIGNAL_TEXT, SIGNAL_REAL, SIGNAL_NAN, | ||||
|     CURSOR, CURSOR_DRAG, CURSOR_TEXT, | ||||
|     MARKER, MARKER_TEXT, REL_ARROW, REL_ARROW_HIGHLITE | ||||
| } | ||||
| @@ -2,7 +2,7 @@ Manifest-Version: 1.0 | ||||
| Bundle-ManifestVersion: 2 | ||||
| Bundle-Name: VCD signal database | ||||
| Bundle-SymbolicName: com.minres.scviewer.database.vcd | ||||
| Bundle-Version: 1.0.0.qualifier | ||||
| Bundle-Version: 2.0.0.qualifier | ||||
| Bundle-Vendor: MINRES Technologies GmbH | ||||
| Bundle-RequiredExecutionEnvironment: JavaSE-1.8 | ||||
| Require-Bundle: com.minres.scviewer.database;bundle-version="1.0.0", | ||||
| @@ -13,3 +13,4 @@ Require-Bundle: com.minres.scviewer.database;bundle-version="1.0.0", | ||||
| Service-Component: OSGI-INF/component.xml | ||||
| Bundle-ActivationPolicy: lazy | ||||
| Import-Package: com.google.common.collect | ||||
| Automatic-Module-Name: com.minres.scviewer.database.vcd | ||||
|   | ||||
| @@ -4,8 +4,9 @@ | ||||
|   <parent> | ||||
|   	<groupId>com.minres.scviewer</groupId> | ||||
|   	<artifactId>com.minres.scviewer.parent</artifactId> | ||||
|   	<version>1.0.0-SNAPSHOT</version> | ||||
|   	<version>2.0.0-SNAPSHOT</version> | ||||
|   	<relativePath>../com.minres.scviewer.parent</relativePath> | ||||
|   </parent> | ||||
|   <packaging>eclipse-plugin</packaging> | ||||
|   </project> | ||||
|   <version>2.0.0-SNAPSHOT</version> | ||||
| </project> | ||||
| @@ -34,26 +34,44 @@ public interface IVCDDatabaseBuilder { | ||||
| 	 * | ||||
| 	 * @param netName the net name | ||||
| 	 * @param i the index of the net, -1 if a new one, otherwise the id if the referenced | ||||
| 	 * @param width the width | ||||
| 	 * @return the integer | ||||
| 	 * @param width the width, -1 equals real, 0... is a bit vector | ||||
| 	 * @return the net id | ||||
| 	 */ | ||||
| 	public Integer newNet(String netName, int i, int width) ; | ||||
|  | ||||
| 	/** | ||||
| 	 * Gets the net width. | ||||
| 	 * | ||||
| 	 * @param intValue the int value | ||||
| 	 * @return the net width | ||||
| 	 * @param intValue the net id | ||||
| 	 * @return the net width, -1 means a real-valued net | ||||
| 	 */ | ||||
| 	public int getNetWidth(int intValue); | ||||
| 	public int getNetWidth(int netId); | ||||
|  | ||||
| 	/** | ||||
| 	 * Append transition. | ||||
| 	 * | ||||
| 	 * @param signalId the int value | ||||
| 	 * @param netId the int value | ||||
| 	 * @param currentTime the current time in ps | ||||
| 	 * @param decodedValues the decoded bit values | ||||
| 	 */ | ||||
| 	public void appendTransition(int netId, long currentTime, char decodedValue); | ||||
|  | ||||
| 	/** | ||||
| 	 * Append transition. | ||||
| 	 * | ||||
| 	 * @param netId the int value | ||||
| 	 * @param currentTime the current time in ps | ||||
| 	 * @param decodedValues the decoded values | ||||
| 	 */ | ||||
| 	public void appendTransition(int signalId, long currentTime, BitVector decodedValues); | ||||
| 	public void appendTransition(int netId, long currentTime, BitVector decodedValue); | ||||
|  | ||||
| 	/** | ||||
| 	 * Append transition. | ||||
| 	 * | ||||
| 	 * @param netId the int value | ||||
| 	 * @param currentTime the current time in ps | ||||
| 	 * @param decodedValue the decoded values | ||||
| 	 */ | ||||
| 	public void appendTransition(int netId, long currentTime, double decodedValue); | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -15,6 +15,7 @@ import java.io.FileInputStream; | ||||
| import java.util.Collection; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| import java.util.NavigableMap; | ||||
| import java.util.Stack; | ||||
| import java.util.TreeMap; | ||||
| import java.util.Vector; | ||||
| @@ -22,8 +23,9 @@ import java.util.Vector; | ||||
| import com.minres.scviewer.database.BitVector; | ||||
| 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.ISignalChangeBitVector; | ||||
| import com.minres.scviewer.database.ISignalChangeReal; | ||||
| import com.minres.scviewer.database.ISignalChangeBit; | ||||
| import com.minres.scviewer.database.IWaveform; | ||||
| import com.minres.scviewer.database.IWaveformDb; | ||||
| import com.minres.scviewer.database.IWaveformDbLoader; | ||||
| @@ -83,20 +85,25 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder { | ||||
| 		moduleStack=null; | ||||
| 		if(!res) throw new InputFormatException(); | ||||
| 		// calculate max time of database | ||||
| 		for(IWaveform<? extends IWaveformEvent> waveform:signals) | ||||
| 			maxTime= Math.max(maxTime, ((ISignal<? extends ISignalChange>)waveform).getEvents().lastKey()); | ||||
| 		for(IWaveform<? extends IWaveformEvent> waveform:signals) { | ||||
| 			NavigableMap<Long, ? extends ISignalChange> events =((ISignal<? extends ISignalChange>)waveform).getEvents(); | ||||
| 			if(events.size()>0) | ||||
| 				maxTime= Math.max(maxTime, events.lastKey()); | ||||
| 		} | ||||
| 		// extend signals to hav a last value set at max time | ||||
| 		for(IWaveform<? extends IWaveformEvent> waveform:signals){ | ||||
| 			TreeMap<Long,? extends ISignalChange> events = ((VCDSignal<? extends ISignalChange>)waveform).values; | ||||
| 			if(events.lastKey()<maxTime){ | ||||
| 			if(events.size()>0 && events.lastKey()<maxTime){ | ||||
| 				ISignalChange x = events.lastEntry().getValue(); | ||||
| 				if(x instanceof ISignalChangeSingle) | ||||
| 					((VCDSignal<ISignalChangeSingle>)waveform).values.put(maxTime,  | ||||
| 							new VCDSignalChangeSingle(maxTime, ((ISignalChangeSingle)x).getValue())); | ||||
| 				else | ||||
| 					if(x instanceof ISignalChangeMulti) | ||||
| 						((VCDSignal<ISignalChangeMulti>)waveform).values.put(maxTime,  | ||||
| 								new VCDSignalChangeMulti(maxTime, ((ISignalChangeMulti)x).getValue())); | ||||
| 				if(x instanceof ISignalChangeBit) | ||||
| 					((VCDSignal<ISignalChangeBit>)waveform).values.put(maxTime,  | ||||
| 							new VCDSignalChangeBit(maxTime, ((ISignalChangeBit)x).getValue())); | ||||
| 				else if(x instanceof ISignalChangeBitVector) | ||||
| 						((VCDSignal<ISignalChangeBitVector>)waveform).values.put(maxTime,  | ||||
| 								new VCDSignalChangeBitVector(maxTime, ((ISignalChangeBitVector)x).getValue())); | ||||
| 				else if(x instanceof ISignalChangeReal) | ||||
| 					((VCDSignal<ISignalChangeReal>)waveform).values.put(maxTime,  | ||||
| 							new VCDSignalChangeReal(maxTime, ((ISignalChangeReal)x).getValue())); | ||||
| 			} | ||||
| 		} | ||||
| 		return true; | ||||
| @@ -147,12 +154,15 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder { | ||||
| 		String netName = moduleStack.empty()? name: moduleStack.lastElement()+"."+name; | ||||
| 		int id = signals.size(); | ||||
| 		VCDSignal<? extends IWaveformEvent> signal; | ||||
| 		if(width==1){ | ||||
| 			signal = i<0 ? new VCDSignal<ISignalChangeSingle>(db, id, netName) : | ||||
| 				new VCDSignal<ISignalChangeSingle>((VCDSignal<ISignalChangeSingle>)signals.get(i), id, netName); | ||||
| 		if(width<0) { | ||||
| 			signal = i<0 ? new VCDSignal<ISignalChangeReal>(db, id, netName, width) : | ||||
| 				new VCDSignal<ISignalChangeReal>((VCDSignal<ISignalChangeReal>)signals.get(i), id, netName);			 | ||||
| 		} else if(width==1){ | ||||
| 			signal = i<0 ? new VCDSignal<ISignalChangeBit>(db, id, netName) : | ||||
| 				new VCDSignal<ISignalChangeBit>((VCDSignal<ISignalChangeBit>)signals.get(i), id, netName); | ||||
| 		} else { | ||||
| 			signal = i<0 ? new VCDSignal<ISignalChangeMulti>(db, id, netName, width) : | ||||
| 				new VCDSignal<ISignalChangeMulti>((VCDSignal<VCDSignalChangeMulti>)signals.get(i), id, netName); | ||||
| 			signal = i<0 ? new VCDSignal<ISignalChangeBitVector>(db, id, netName, width) : | ||||
| 				new VCDSignal<ISignalChangeBitVector>((VCDSignal<VCDSignalChangeBitVector>)signals.get(i), id, netName); | ||||
| 		}; | ||||
| 		signals.add(signal); | ||||
| 		return id; | ||||
| @@ -167,6 +177,19 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder { | ||||
| 		return signal.getWidth(); | ||||
| 	} | ||||
|  | ||||
| 	/* (non-Javadoc) | ||||
| 	 * @see com.minres.scviewer.database.vcd.ITraceBuilder#appendTransition(int, long, com.minres.scviewer.database.vcd.BitVector) | ||||
| 	 */ | ||||
| 	@SuppressWarnings("unchecked") | ||||
| 	@Override | ||||
| 	public void appendTransition(int signalId, long currentTime, char decodedValues) { | ||||
| 		VCDSignal<? extends IWaveformEvent> signal = (VCDSignal<? extends IWaveformEvent>) signals.get(signalId); | ||||
| 		Long time = currentTime*TIME_RES; | ||||
| 		if(signal.getWidth()==1){ | ||||
| 			((VCDSignal<ISignalChangeBit>)signal).values.put(time, new VCDSignalChangeBit(time, decodedValues)); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	/* (non-Javadoc) | ||||
| 	 * @see com.minres.scviewer.database.vcd.ITraceBuilder#appendTransition(int, long, com.minres.scviewer.database.vcd.BitVector) | ||||
| 	 */ | ||||
| @@ -175,10 +198,21 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder { | ||||
| 	public void appendTransition(int signalId, long currentTime, BitVector decodedValues) { | ||||
| 		VCDSignal<? extends IWaveformEvent> signal = (VCDSignal<? extends IWaveformEvent>) signals.get(signalId); | ||||
| 		Long time = currentTime* TIME_RES; | ||||
| 		if(signal.getWidth()==1){ | ||||
| 			((VCDSignal<ISignalChangeSingle>)signal).values.put(time, new VCDSignalChangeSingle(time, decodedValues.getValue()[0])); | ||||
| 		} else { | ||||
| 			((VCDSignal<VCDSignalChangeMulti>)signal).values.put(time, new VCDSignalChangeMulti(time, decodedValues)); | ||||
| 		if(signal.getWidth()>1){ | ||||
| 			((VCDSignal<VCDSignalChangeBitVector>)signal).values.put(time, new VCDSignalChangeBitVector(time, decodedValues)); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	/* (non-Javadoc) | ||||
| 	 * @see com.minres.scviewer.database.vcd.ITraceBuilder#appendTransition(int, long, com.minres.scviewer.database.vcd.BitVector) | ||||
| 	 */ | ||||
| 	@SuppressWarnings("unchecked") | ||||
| 	@Override | ||||
| 	public void appendTransition(int signalId, long currentTime, double decodedValue) { | ||||
| 		VCDSignal<? extends IWaveformEvent> signal = (VCDSignal<? extends IWaveformEvent>) signals.get(signalId); | ||||
| 		Long time = currentTime* TIME_RES; | ||||
| 		if(signal.getWidth()<0){ | ||||
| 			((VCDSignal<ISignalChangeReal>)signal).values.put(time, new VCDSignalChangeReal(time, decodedValue)); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
|   | ||||
| @@ -61,9 +61,11 @@ class VCDFileParser { | ||||
|  | ||||
| 	private void parseVar() throws Exception { | ||||
| 		nextToken(); // type | ||||
| 		String type = tokenizer.sval; | ||||
| 		nextToken(); // size | ||||
| 		int width = Integer.parseInt(tokenizer.sval); | ||||
|  | ||||
| 		if("real".equals(type)) | ||||
| 			width*=-1; | ||||
| 		nextToken(); | ||||
| 		String id = tokenizer.sval; | ||||
| 		nextToken(); | ||||
| @@ -153,7 +155,8 @@ class VCDFileParser { | ||||
| 				} while (!tokenizer.sval.equals("$end")); | ||||
| 				return true; | ||||
| 			} | ||||
| 			if (tokenizer.sval.equals("$dumpvars") || tokenizer.sval.equals("$end")) return true; | ||||
| 			if (tokenizer.sval.equals("$dumpvars") || tokenizer.sval.equals("$end")) | ||||
| 				return true; | ||||
| 			String value, id; | ||||
| 			if (tokenizer.sval.charAt(0) == 'b') { | ||||
| 				// Multiple value net. Value appears first, followed by space, | ||||
| @@ -161,6 +164,12 @@ class VCDFileParser { | ||||
| 				value = tokenizer.sval.substring(1); | ||||
| 				nextToken(); | ||||
| 				id = tokenizer.sval; | ||||
| 			}else if (tokenizer.sval.charAt(0) == 'r') { | ||||
| 					// Multiple value net. Value appears first, followed by space, | ||||
| 					// then identifier | ||||
| 					value = tokenizer.sval.substring(1); | ||||
| 					nextToken(); | ||||
| 					id = tokenizer.sval; | ||||
| 			} else { | ||||
| 				// Single value net. identifier first, then value, no space. | ||||
| 				value = tokenizer.sval.substring(0, 1); | ||||
| @@ -174,39 +183,46 @@ class VCDFileParser { | ||||
| 			} | ||||
|  | ||||
| 			int netWidth = traceBuilder.getNetWidth(net); | ||||
| 			BitVector decodedValues = new BitVector(netWidth); | ||||
| 			if (value.equals("z") && netWidth > 1) { | ||||
| 				for (int i = 0; i < netWidth; i++) | ||||
| 					decodedValues.setValue(i, BitVector.VALUE_Z); | ||||
| 			} else if (value.equals("x") && netWidth > 1) { | ||||
| 				for (int i = 0; i < netWidth; i++) | ||||
| 					decodedValues.setValue(i, BitVector.VALUE_X); | ||||
| 			if(netWidth<0) { | ||||
| 				traceBuilder.appendTransition(net, currentTime, Double.parseDouble(value)); | ||||
| 			} else { | ||||
| 				int stringIndex = 0; | ||||
| 				for (int convertedIndex = netWidth - value.length(); convertedIndex < netWidth; convertedIndex++) { | ||||
| 					switch (value.charAt(stringIndex++)) { | ||||
| 					case 'z': | ||||
| 						decodedValues.setValue(convertedIndex, BitVector.VALUE_Z); | ||||
| 						break; | ||||
|  | ||||
| 					case '1': | ||||
| 						decodedValues.setValue(convertedIndex, BitVector.VALUE_1); | ||||
| 						break; | ||||
|  | ||||
| 					case '0': | ||||
| 						decodedValues.setValue(convertedIndex, BitVector.VALUE_0); | ||||
| 						break; | ||||
|  | ||||
| 					case 'x': | ||||
| 						decodedValues.setValue(convertedIndex, BitVector.VALUE_X); | ||||
| 						break; | ||||
|  | ||||
| 					default: | ||||
| 						decodedValues.setValue(convertedIndex, BitVector.VALUE_X); | ||||
| 				BitVector decodedValues = new BitVector(netWidth); | ||||
| 				if (value.equals("z") && netWidth > 1) { | ||||
| 					for (int i = 0; i < netWidth; i++) | ||||
| 						decodedValues.setValue(i, BitVector.VALUE_Z); | ||||
| 				} else if (value.equals("x") && netWidth > 1) { | ||||
| 					for (int i = 0; i < netWidth; i++) | ||||
| 						decodedValues.setValue(i, BitVector.VALUE_X); | ||||
| 				} else { | ||||
| 					int stringIndex = 0; | ||||
| 					for (int convertedIndex = netWidth - value.length(); convertedIndex < netWidth; convertedIndex++) { | ||||
| 						switch (value.charAt(stringIndex++)) { | ||||
| 						case 'z': | ||||
| 							decodedValues.setValue(convertedIndex, BitVector.VALUE_Z); | ||||
| 							break; | ||||
| 	 | ||||
| 						case '1': | ||||
| 							decodedValues.setValue(convertedIndex, BitVector.VALUE_1); | ||||
| 							break; | ||||
| 	 | ||||
| 						case '0': | ||||
| 							decodedValues.setValue(convertedIndex, BitVector.VALUE_0); | ||||
| 							break; | ||||
| 	 | ||||
| 						case 'x': | ||||
| 							decodedValues.setValue(convertedIndex, BitVector.VALUE_X); | ||||
| 							break; | ||||
| 	 | ||||
| 						default: | ||||
| 							decodedValues.setValue(convertedIndex, BitVector.VALUE_X); | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 				if(netWidth==1) | ||||
| 					traceBuilder.appendTransition(net, currentTime, decodedValues.getValue()[0]); | ||||
| 				else | ||||
| 					traceBuilder.appendTransition(net, currentTime, decodedValues); | ||||
| 			} | ||||
| 			traceBuilder.appendTransition(net, currentTime, decodedValues); | ||||
| 		} | ||||
| 		return true; | ||||
| 	} | ||||
|   | ||||
| @@ -10,14 +10,14 @@ | ||||
|  *******************************************************************************/ | ||||
| package com.minres.scviewer.database.vcd; | ||||
| 
 | ||||
| import com.minres.scviewer.database.ISignalChangeSingle; | ||||
| import com.minres.scviewer.database.ISignalChangeBit; | ||||
| import com.minres.scviewer.database.SignalChange; | ||||
| 
 | ||||
| public class VCDSignalChangeSingle extends SignalChange implements ISignalChangeSingle, Cloneable { | ||||
| public class VCDSignalChangeBit extends SignalChange implements ISignalChangeBit, Cloneable { | ||||
| 
 | ||||
| 	private char value; | ||||
| 
 | ||||
| 	public VCDSignalChangeSingle(Long time, char value) { | ||||
| 	public VCDSignalChangeBit(Long time, char value) { | ||||
| 		super(time); | ||||
| 		this.value=value; | ||||
| 	} | ||||
| @@ -11,18 +11,18 @@ | ||||
| package com.minres.scviewer.database.vcd; | ||||
| 
 | ||||
| import com.minres.scviewer.database.BitVector; | ||||
| import com.minres.scviewer.database.ISignalChangeMulti; | ||||
| import com.minres.scviewer.database.ISignalChangeBitVector; | ||||
| import com.minres.scviewer.database.SignalChange; | ||||
| 
 | ||||
| public class VCDSignalChangeMulti extends SignalChange implements ISignalChangeMulti, Cloneable  { | ||||
| public class VCDSignalChangeBitVector extends SignalChange implements ISignalChangeBitVector, Cloneable  { | ||||
| 
 | ||||
| 	private BitVector value; | ||||
| 	 | ||||
| 	public VCDSignalChangeMulti(Long time) { | ||||
| 	public VCDSignalChangeBitVector(Long time) { | ||||
| 		super(time); | ||||
| 	} | ||||
| 
 | ||||
| 	public VCDSignalChangeMulti(Long time, BitVector decodedValues) { | ||||
| 	public VCDSignalChangeBitVector(Long time, BitVector decodedValues) { | ||||
| 		super(time); | ||||
| 		this.value=decodedValues; | ||||
| 	} | ||||
| @@ -0,0 +1,37 @@ | ||||
| /******************************************************************************* | ||||
|  * Copyright (c) 2015 MINRES Technologies GmbH and others. | ||||
|  * 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.database.vcd; | ||||
|  | ||||
| import com.minres.scviewer.database.ISignalChangeReal; | ||||
| import com.minres.scviewer.database.SignalChange; | ||||
|  | ||||
| public class VCDSignalChangeReal extends SignalChange implements ISignalChangeReal, Cloneable { | ||||
|  | ||||
| 	private double value; | ||||
|  | ||||
| 	public VCDSignalChangeReal(Long time, double value) { | ||||
| 		super(time); | ||||
| 		this.value=value; | ||||
| 	} | ||||
|  | ||||
| 	public double getValue() { | ||||
| 		return value; | ||||
| 	} | ||||
|  | ||||
| 	public void setValue(double value) { | ||||
| 		this.value = value; | ||||
| 	} | ||||
| 	 | ||||
| 	@Override | ||||
| 	public String toString() { | ||||
| 		return value+"@"+getTime(); | ||||
| 	} | ||||
| } | ||||
| @@ -11,3 +11,4 @@ Service-Component: OSGI-INF/component.xml,OSGI-INF/component2.xml | ||||
| Require-Bundle: org.eclipse.equinox.ds;bundle-version="1.4.200", | ||||
|  org.eclipse.equinox.util;bundle-version="1.0.500", | ||||
|  org.eclipse.osgi.services;bundle-version="3.4.0" | ||||
| Automatic-Module-Name: com.minres.scviewer.database | ||||
|   | ||||
| @@ -63,4 +63,49 @@ public class BitVector { | ||||
| 		} | ||||
| 		return new String(res);		 | ||||
| 	} | ||||
| 	 | ||||
| 	public long toUnsignedValue() { | ||||
| 		long res = 0; | ||||
| 		for(char c:value) { | ||||
| 			res<<=1; | ||||
| 			switch (c) { | ||||
| 			case VALUE_1: | ||||
| 				res++; | ||||
| 				break; | ||||
| 			case VALUE_X: | ||||
| 			case VALUE_Z: | ||||
| 				return 0; | ||||
| 			default: | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		return res; | ||||
| 	} | ||||
| 	 | ||||
| 	public long toSignedValue() { | ||||
| 		Boolean negative=null; | ||||
| 		long res = 0; | ||||
| 		for(char c:value) { | ||||
| 			if(negative == null) { | ||||
| 				switch (c) { | ||||
| 				case VALUE_1: negative=true; break; | ||||
| 				case VALUE_0: negative=false; break; | ||||
| 				case VALUE_X: | ||||
| 				case VALUE_Z: return 0; | ||||
| 				default: | ||||
| 				}				 | ||||
| 			} else { | ||||
| 				res<<=1; | ||||
| 				switch (c) { | ||||
| 				case VALUE_1: if(!negative)	res++; break; | ||||
| 				case VALUE_0: if(negative)	res++; break; | ||||
| 				case VALUE_X: | ||||
| 				case VALUE_Z: return 0; | ||||
| 				default: | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		return negative?-1*(res+1):res; | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -10,7 +10,7 @@ | ||||
|  *******************************************************************************/ | ||||
| package com.minres.scviewer.database; | ||||
| 
 | ||||
| public interface ISignalChangeSingle extends ISignalChange{ | ||||
| public interface ISignalChangeBit extends ISignalChange{ | ||||
| 
 | ||||
| 	public char getValue(); | ||||
| 	 | ||||
| @@ -10,8 +10,7 @@ | ||||
|  *******************************************************************************/ | ||||
| package com.minres.scviewer.database; | ||||
| 
 | ||||
| 
 | ||||
| public interface ISignalChangeMulti extends ISignalChange { | ||||
| public interface ISignalChangeBitVector extends ISignalChange { | ||||
| 	 | ||||
| 	public BitVector getValue(); | ||||
| 
 | ||||
| @@ -0,0 +1,17 @@ | ||||
| /******************************************************************************* | ||||
|  * Copyright (c) 2015 MINRES Technologies GmbH and others. | ||||
|  * 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.database; | ||||
|  | ||||
| public interface ISignalChangeReal extends ISignalChange{ | ||||
|  | ||||
| 	public double getValue(); | ||||
| 	 | ||||
| } | ||||
| @@ -108,7 +108,7 @@ | ||||
|           <parameters xmi:id="_cuGAkHcjEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.parameter.12" name="com.minres.scviewer.e4.application.command.navigateTransCommand.parameter.dir" value="prev"/> | ||||
|         </children> | ||||
|         <children xsi:type="menu:ToolControl" xmi:id="_LtQhcIuKEeWid7xO48ZBXw" elementId="com.minres.scviewer.e4.application.toolcontrol.0" contributionURI="bundleclass://com.minres.scviewer.e4.application/com.minres.scviewer.e4.application.elements.RelationTypeToolControl"/> | ||||
|         <children xsi:type="menu:DirectToolItem" xmi:id="_Z7ZQkIuJEeWid7xO48ZBXw" elementId="com.minres.scviewer.e4.application.directtoolitem.nextprevinstream" toBeRendered="false" visible="false" label="Next/Prev in stream" enabled="false"> | ||||
|         <children xsi:type="menu:DirectToolItem" xmi:id="_Z7ZQkIuJEeWid7xO48ZBXw" elementId="com.minres.scviewer.e4.application.directtoolitem.nextprevinstream" toBeRendered="false" visible="false" label="Next/Prev in stream"> | ||||
|           <menu xmi:id="_aPyMMIuJEeWid7xO48ZBXw" elementId="com.minres.scviewer.e4.application.menu.2"> | ||||
|             <children xsi:type="menu:DynamicMenuContribution" xmi:id="_cnNWkIuJEeWid7xO48ZBXw" elementId="com.minres.scviewer.e4.application.dynamicmenucontribution.2" contributionURI="bundleclass://com.minres.scviewer.e4.application/com.minres.scviewer.e4.application.parts.NavigateContribution"/> | ||||
|           </menu> | ||||
| @@ -142,7 +142,7 @@ | ||||
|       </children> | ||||
|     </trimBars> | ||||
|   </children> | ||||
|   <children xsi:type="basic:Dialog" xmi:id="_8BTkQIytEeWid7xO48ZBXw" elementId="com.minres.scviewer.e4.application.dialog.aboutscviewer" toBeRendered="false" visible="false" selectedElement="__VNlAIytEeWid7xO48ZBXw" label="About SCViewer" y="600"> | ||||
|   <children xsi:type="basic:Window" xmi:id="_8BTkQIytEeWid7xO48ZBXw" elementId="com.minres.scviewer.e4.application.dialog.aboutscviewer" toBeRendered="false" visible="false" selectedElement="__VNlAIytEeWid7xO48ZBXw" label="About SCViewer" x="200" y="200"> | ||||
|     <children xsi:type="basic:Part" xmi:id="__VNlAIytEeWid7xO48ZBXw" elementId="com.minres.scviewer.e4.application.part.0" contributionURI="bundleclass://com.minres.scviewer.e4.application/com.minres.scviewer.e4.application.parts.AboutDialog"/> | ||||
|   </children> | ||||
|   <handlers xmi:id="_95PfvXNmEeWBq8z1Dv39LA" elementId="com.minres.scviewer.e4.application.handler.quitCommand" contributionURI="bundleclass://com.minres.scviewer.e4.application/com.minres.scviewer.e4.application.handlers.QuitHandler" command="_95PfvHNmEeWBq8z1Dv39LA"/> | ||||
| @@ -171,6 +171,8 @@ | ||||
|     <handlers xmi:id="_297tsHXHEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.handler.deletewaveformCommand" contributionURI="bundleclass://com.minres.scviewer.e4.application/com.minres.scviewer.e4.application.handlers.DeleteWaveformHandler" command="_WUZ2wHXHEeWwZ-9vrAR2UQ"/> | ||||
|     <handlers xmi:id="_2Ai4YHXHEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.handler.movewaveformupCommand" contributionURI="bundleclass://com.minres.scviewer.e4.application/com.minres.scviewer.e4.application.handlers.MoveWaveformHandler" command="_N_sOkHXHEeWwZ-9vrAR2UQ"/> | ||||
|     <handlers xmi:id="_Du1NAHcrEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.handler.zoomCommand" contributionURI="bundleclass://com.minres.scviewer.e4.application/com.minres.scviewer.e4.application.handlers.ZoomHandler" command="_693GoHcqEeWwZ-9vrAR2UQ"/> | ||||
|     <handlers xmi:id="_bxt4QM3rEei6rfTGo88R-w" elementId="com.minres.scviewer.e4.application.handler.changeWaveDisplay" contributionURI="bundleclass://com.minres.scviewer.e4.application/com.minres.scviewer.e4.application.handlers.ChangeWaveformDisplay" command="_FZunYM2PEei6rfTGo88R-w"/> | ||||
|     <handlers xmi:id="_bxw7kM3rEei6rfTGo88R-w" elementId="com.minres.scviewer.e4.application.handler.changeValueDisplay" contributionURI="bundleclass://com.minres.scviewer.e4.application/com.minres.scviewer.e4.application.handlers.ChangeValueDisplay" command="_4C_asM3ZEei6rfTGo88R-w"/> | ||||
|     <menus xsi:type="menu:PopupMenu" xmi:id="_TwzrsHWSEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.popupmenu.namecontext" label="Name Menu"> | ||||
|       <children xsi:type="menu:HandledMenuItem" xmi:id="_Vco7YHWSEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.handledmenuitem.moveup" label="Move up" iconURI="platform:/plugin/com.minres.scviewer.e4.application/icons/up_blue.png" tooltip="Move stream/waveform in list up" command="_N_sOkHXHEeWwZ-9vrAR2UQ"> | ||||
|         <visibleWhen xsi:type="ui:CoreExpression" xmi:id="_elFdcHr_EeWVM_sKoXvptg" coreExpressionId="com.minres.scviewer.e4.application.oneWaveSeleted"/> | ||||
| @@ -204,40 +206,51 @@ | ||||
|       <children xsi:type="menu:HandledMenuItem" xmi:id="_4ZeEQHabEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.handledmenuitem.previouschange" label="Previous Tx" iconURI="platform:/plugin/com.minres.scviewer.e4.application/icons/reverse_green.png" command="_Gn3lEHXKEeWwZ-9vrAR2UQ"> | ||||
|         <parameters xmi:id="_4ZeEQXabEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.parameter.5" name="com.minres.scviewer.e4.application.command.navigateTransCommand.parameter.dir" value="prev"/> | ||||
|       </children> | ||||
|       <children xsi:type="menu:MenuSeparator" xmi:id="__Ubd4M1eEei6rfTGo88R-w" elementId="com.minres.scviewer.e4.application.menuseparator.0"/> | ||||
|       <children xsi:type="menu:Menu" xmi:id="_mAA6sM1bEei6rfTGo88R-w" elementId="com.minres.scviewer.e4.application.menu.view" label="View"> | ||||
|         <visibleWhen xsi:type="ui:ImperativeExpression" xmi:id="_psvR0M1gEei6rfTGo88R-w" contributionURI="bundleclass://com.minres.scviewer.e4.application/com.minres.scviewer.e4.application.elements.WaveformPopupMenuContribution"/> | ||||
|         <children xsi:type="menu:DynamicMenuContribution" xmi:id="_IQZZQM3hEei6rfTGo88R-w" elementId="com.minres.scviewer.e4.application.dynamicmenucontribution.0" contributionURI="bundleclass://com.minres.scviewer.e4.application/com.minres.scviewer.e4.application.elements.WaveformPopupMenuContribution"/> | ||||
|       </children> | ||||
|     </menus> | ||||
|   </descriptors> | ||||
|   <commands xmi:id="_95PfvHNmEeWBq8z1Dv39LA" elementId="org.eclipse.ui.file.exit" commandName="quitCommand"/> | ||||
|   <commands xmi:id="_95PfwHNmEeWBq8z1Dv39LA" elementId="com.minres.scviewer.e4.application.open" commandName="openCommand"/> | ||||
|   <commands xmi:id="_95Pfw3NmEeWBq8z1Dv39LA" elementId="org.eclipse.ui.file.save" commandName="saveCommand"/> | ||||
|   <commands xmi:id="_95PfxnNmEeWBq8z1Dv39LA" elementId="org.eclipse.ui.help.aboutAction" commandName="aboutCommand"/> | ||||
|   <commands xmi:id="_N_sOkHXHEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.command.movewaveformupCommand" commandName="moveWaveformCommand"> | ||||
|   <commands xmi:id="_95PfvHNmEeWBq8z1Dv39LA" elementId="org.eclipse.ui.file.exit" commandName="Quit Command"/> | ||||
|   <commands xmi:id="_95PfwHNmEeWBq8z1Dv39LA" elementId="com.minres.scviewer.e4.application.open" commandName="Open Command"/> | ||||
|   <commands xmi:id="_95Pfw3NmEeWBq8z1Dv39LA" elementId="org.eclipse.ui.file.save" commandName="Save Command"/> | ||||
|   <commands xmi:id="_95PfxnNmEeWBq8z1Dv39LA" elementId="org.eclipse.ui.help.aboutAction" commandName="About Command"/> | ||||
|   <commands xmi:id="_N_sOkHXHEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.command.movewaveformupCommand" commandName="Move Waveform Command"> | ||||
|     <parameters xmi:id="_lMv-EHZWEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.command.movewaveformupCommand.parameter.dir" name="direction" optional="false"/> | ||||
|   </commands> | ||||
|   <commands xmi:id="_WUZ2wHXHEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.command.deletewaveformCommand" commandName="deleteWaveformCommand"/> | ||||
|   <commands xmi:id="_bV-TMHXHEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.command.selectallCommand" commandName="selectAllCommand"/> | ||||
|   <commands xmi:id="_Gn3lEHXKEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.command.navigateTransCommand" commandName="navigateTransCommand" description="Navigate to related transaction"> | ||||
|   <commands xmi:id="_WUZ2wHXHEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.command.deletewaveformCommand" commandName="Delete Waveform Command"/> | ||||
|   <commands xmi:id="_bV-TMHXHEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.command.selectallCommand" commandName="Select All Command"/> | ||||
|   <commands xmi:id="_Gn3lEHXKEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.command.navigateTransCommand" commandName="Navigate Transaction Command" description="Navigate to related transaction"> | ||||
|     <parameters xmi:id="_howw0HXQEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.command.navigateTransCommand.parameter.dir" name="direction" optional="false"/> | ||||
|   </commands> | ||||
|   <commands xmi:id="_79rx4HabEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.command.navigateEventCommand" commandName="navigateEventCommand"> | ||||
|   <commands xmi:id="_79rx4HabEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.command.navigateEventCommand" commandName="Navigate Event Command"> | ||||
|     <parameters xmi:id="_79rx4XabEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.command.navigateEventCommand.parameter.dir" name="direction" optional="false"/> | ||||
|   </commands> | ||||
|   <commands xmi:id="_693GoHcqEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.command.zoomcommand" commandName="zoomCommand"> | ||||
|   <commands xmi:id="_693GoHcqEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.command.zoomcommand" commandName="Zoom Command"> | ||||
|     <parameters xmi:id="_8tbm0HcqEeWwZ-9vrAR2UQ" elementId="com.minres.scviewer.e4.application.command.zoomcommand.parameter.level" name="level" optional="false"/> | ||||
|   </commands> | ||||
|   <commands xmi:id="_2PehEHr9EeWVM_sKoXvptg" elementId="com.minres.scviewer.e4.application.command.addwaveform" commandName="addWaveformCommand"> | ||||
|   <commands xmi:id="_2PehEHr9EeWVM_sKoXvptg" elementId="com.minres.scviewer.e4.application.command.addwaveform" commandName="Add Waveform Command"> | ||||
|     <parameters xmi:id="_6KsZcHr9EeWVM_sKoXvptg" elementId="com.minres.scviewer.e4.application.command.addwaveform.where" name="where" optional="false"/> | ||||
|     <parameters xmi:id="_7T1TcHwIEeWv0Y5uF2QN5w" elementId="com.minres.scviewer.e4.application.command.addwaveform.all" name="all" typeId="" optional="false"/> | ||||
|   </commands> | ||||
|   <commands xmi:id="_AxH6sIl_EeWxJ_wPkM6yGQ" elementId="org.eclipse.ui.window.preferences" commandName="Preferences"/> | ||||
|   <commands xmi:id="_KlGlsIoNEeWxJ_wPkM6yGQ" elementId="com.minres.scviewer.e4.application.command.set_them" commandName="Set Theme"> | ||||
|   <commands xmi:id="_KlGlsIoNEeWxJ_wPkM6yGQ" elementId="com.minres.scviewer.e4.application.command.set_them" commandName="Set Theme Command"> | ||||
|     <parameters xmi:id="_O8Z9IIoNEeWxJ_wPkM6yGQ" elementId="com.minres.scviewer.e4.application.command.theme.parameter.id" name="themeId" optional="false"/> | ||||
|   </commands> | ||||
|   <commands xmi:id="_E9lUgIt2EeWid7xO48ZBXw" elementId="com.minres.scviewer.e4.application.command.setrelationtype" commandName="SetRelationType"> | ||||
|   <commands xmi:id="_E9lUgIt2EeWid7xO48ZBXw" elementId="com.minres.scviewer.e4.application.command.setrelationtype" commandName="Set Relation Type Command"> | ||||
|     <parameters xmi:id="_xnW7IIt_EeWid7xO48ZBXw" elementId="com.minres.scviewer.e4.application.commandparameter.relationName" name="relationName" optional="false"/> | ||||
|   </commands> | ||||
|   <commands xmi:id="_7-AIMJebEeW09eyIbHsdvg" elementId="com.minres.scviewer.e4.application.command.loadStoreSettings" commandName="loadStoreSettings"> | ||||
|   <commands xmi:id="_7-AIMJebEeW09eyIbHsdvg" elementId="com.minres.scviewer.e4.application.command.loadStoreSettings" commandName="Load-Store Settings Command"> | ||||
|     <parameters xmi:id="_wxY3EJehEeW09eyIbHsdvg" elementId="com.minres.scviewer.e4.application.commandparameter.loadStore" name="loadStore"/> | ||||
|   </commands> | ||||
|   <commands xmi:id="_FZunYM2PEei6rfTGo88R-w" elementId="com.minres.scviewer.e4.application.command.changewavedisplay" commandName="Change Waveform Display Command"> | ||||
|     <parameters xmi:id="_P6PYwM2PEei6rfTGo88R-w" elementId="com.minres.scviewer.e4.application.commandparameter.changewavedisplay" name="Type" optional="false"/> | ||||
|   </commands> | ||||
|   <commands xmi:id="_4C_asM3ZEei6rfTGo88R-w" elementId="com.minres.scviewer.e4.application.command.changevaluedisplay" commandName="Change Value Display Command"> | ||||
|     <parameters xmi:id="_4C_asc3ZEei6rfTGo88R-w" elementId="com.minres.scviewer.e4.application.commandparameter.changevaluedisplay" name="Type" optional="false"/> | ||||
|   </commands> | ||||
|   <addons xmi:id="_95PfsnNmEeWBq8z1Dv39LA" elementId="org.eclipse.e4.core.commands.service" contributionURI="bundleclass://org.eclipse.e4.core.commands/org.eclipse.e4.core.commands.CommandServiceAddon"/> | ||||
|   <addons xmi:id="_95Pfs3NmEeWBq8z1Dv39LA" elementId="org.eclipse.e4.ui.contexts.service" contributionURI="bundleclass://org.eclipse.e4.ui.services/org.eclipse.e4.ui.services.ContextServiceAddon"/> | ||||
|   <addons xmi:id="_95PftHNmEeWBq8z1Dv39LA" elementId="org.eclipse.e4.ui.bindings.service" contributionURI="bundleclass://org.eclipse.e4.ui.bindings/org.eclipse.e4.ui.bindings.BindingServiceAddon"/> | ||||
|   | ||||
| @@ -2,36 +2,37 @@ Manifest-Version: 1.0 | ||||
| Bundle-ManifestVersion: 2 | ||||
| Bundle-Name: %Bundle-Name | ||||
| Bundle-SymbolicName: com.minres.scviewer.e4.application;singleton:=true | ||||
| Bundle-Version: 1.1.1.qualifier | ||||
| Bundle-Version: 2.0.0.qualifier | ||||
| Bundle-Vendor: %Bundle-Vendor | ||||
| Require-Bundle: javax.inject;bundle-version="1.0.0", | ||||
|  org.eclipse.core.runtime;bundle-version="3.11.1", | ||||
|  org.eclipse.swt;bundle-version="3.104.1", | ||||
|  org.eclipse.e4.ui.model.workbench;bundle-version="1.1.100", | ||||
|  org.eclipse.jface;bundle-version="3.11.0", | ||||
|  org.eclipse.e4.ui.services;bundle-version="1.2.0", | ||||
|  org.eclipse.e4.ui.workbench;bundle-version="1.3.0", | ||||
|  org.eclipse.e4.core.di;bundle-version="1.5.0", | ||||
|  org.eclipse.e4.ui.di;bundle-version="1.1.0", | ||||
|  org.eclipse.e4.core.contexts;bundle-version="1.4.0", | ||||
|  com.minres.scviewer.database.ui.swt;bundle-version="1.0.0", | ||||
|  com.minres.scviewer.database.ui, | ||||
|  com.minres.scviewer.database;bundle-version="1.0.0", | ||||
|  org.eclipse.equinox.ds;bundle-version="1.4.300", | ||||
|  org.eclipse.equinox.util;bundle-version="1.0.500", | ||||
|  org.eclipse.osgi.services;bundle-version="3.5.0", | ||||
|  org.eclipse.e4.core.services;bundle-version="2.0.0", | ||||
|  org.eclipse.osgi.services;bundle-version="3.5.0", | ||||
|  org.eclipse.core.jobs, | ||||
|  org.eclipse.osgi, | ||||
|  com.google.guava, | ||||
|  org.eclipse.equinox.preferences, | ||||
|  org.eclipse.core.expressions, | ||||
|  org.eclipse.e4.core.commands;bundle-version="0.11.0", | ||||
|  org.eclipse.e4.ui.workbench.addons.swt, | ||||
|  com.opcoach.e4.preferences, | ||||
|  org.eclipse.e4.core.di.extensions, | ||||
|  org.eclipse.e4.ui.css.swt.theme;bundle-version="0.10.0" | ||||
|   org.eclipse.core.runtime;bundle-version="3.11.1", | ||||
|   org.eclipse.swt;bundle-version="3.104.1", | ||||
|   org.eclipse.e4.ui.model.workbench;bundle-version="1.1.100", | ||||
|   org.eclipse.jface;bundle-version="3.11.0", | ||||
|   org.eclipse.e4.ui.services;bundle-version="1.2.0", | ||||
|   org.eclipse.e4.ui.workbench;bundle-version="1.3.0", | ||||
|   org.eclipse.e4.core.di;bundle-version="1.5.0", | ||||
|   org.eclipse.e4.ui.di;bundle-version="1.1.0", | ||||
|   org.eclipse.e4.core.contexts;bundle-version="1.4.0", | ||||
|   com.minres.scviewer.database.ui.swt;bundle-version="1.0.0", | ||||
|   com.minres.scviewer.database.ui, | ||||
|   com.minres.scviewer.database;bundle-version="1.0.0", | ||||
|   org.eclipse.equinox.ds;bundle-version="1.4.300", | ||||
|   org.eclipse.equinox.util;bundle-version="1.0.500", | ||||
|   org.eclipse.osgi.services;bundle-version="3.5.0", | ||||
|   org.eclipse.e4.core.services;bundle-version="2.0.0", | ||||
|   org.eclipse.osgi.services;bundle-version="3.5.0", | ||||
|   org.eclipse.core.jobs, | ||||
|   org.eclipse.osgi, | ||||
|   com.google.guava, | ||||
|   org.eclipse.equinox.preferences, | ||||
|   org.eclipse.core.expressions, | ||||
|   org.eclipse.e4.core.commands;bundle-version="0.11.0", | ||||
|   org.eclipse.e4.ui.workbench.addons.swt, | ||||
|   com.opcoach.e4.preferences, | ||||
|   org.eclipse.e4.core.di.extensions, | ||||
|   org.eclipse.e4.ui.css.swt.theme;bundle-version="0.10.0" | ||||
| Bundle-RequiredExecutionEnvironment: JavaSE-1.8 | ||||
| Import-Package: com.minres.scviewer.database, | ||||
|  javax.inject;version="1.0.0" | ||||
|   javax.inject;version="1.0.0" | ||||
| Automatic-Module-Name: com.minres.scviewer.e4.application | ||||
|   | ||||
| @@ -4,9 +4,8 @@ | ||||
|   <parent> | ||||
|   	<groupId>com.minres.scviewer</groupId> | ||||
|   	<artifactId>com.minres.scviewer.parent</artifactId> | ||||
|   	<version>1.0.0-SNAPSHOT</version> | ||||
|   	<version>2.0.0-SNAPSHOT</version> | ||||
|   	<relativePath>../com.minres.scviewer.parent</relativePath> | ||||
|   </parent> | ||||
|   <packaging>eclipse-plugin</packaging> | ||||
|   <version>1.1.1-SNAPSHOT</version> | ||||
|   </project> | ||||
| @@ -33,6 +33,10 @@ import org.eclipse.equinox.app.IApplicationContext; | ||||
| import org.osgi.service.event.Event; | ||||
| import org.osgi.service.event.EventHandler; | ||||
|  | ||||
| import com.minres.scviewer.e4.application.options.Options; | ||||
| import com.minres.scviewer.e4.application.options.Options.Multiplicity; | ||||
| import com.minres.scviewer.e4.application.options.Options.Separator; | ||||
|  | ||||
| /** | ||||
|  * This implementation contains e4 LifeCycle annotated methods.<br /> | ||||
|  * There is a corresponding entry in <em>plugin.xml</em> (under the | ||||
| @@ -59,7 +63,14 @@ public class E4LifeCycle { | ||||
| 	 */ | ||||
| 	@PostContextCreate | ||||
| 	void postContextCreate(IApplicationContext appContext, final IEventBroker eventBroker) { | ||||
| 		final String[] args = (String[])appContext.getArguments().get(IApplicationContext.APPLICATION_ARGS);  | ||||
| 		final String[] args = (String[])appContext.getArguments().get(IApplicationContext.APPLICATION_ARGS); | ||||
| 		Options opt = new Options(args, 1); | ||||
| 		opt.getSet().addOption("c", Separator.BLANK, Multiplicity.ONCE); | ||||
| 		if (!opt.check(Options.DEFAULT_SET, true, true)) { | ||||
| 		  System.exit(1); | ||||
| 		} | ||||
| 		final String confFile =opt.getSet().isSet("c")?opt.getSet().getOption("c").getResultValue(0):""; | ||||
|  | ||||
| 		// react on the first view being created, at that time the UI is available | ||||
| 		eventBroker.subscribe(UIEvents.UILifeCycle.ACTIVATE, new EventHandler() { | ||||
| 			@Override | ||||
| @@ -68,9 +79,10 @@ public class E4LifeCycle { | ||||
| 				if(part!=null){ | ||||
| 					IEclipseContext ctx = part.getContext(); | ||||
| 					OpenViewHandler openViewHandler= new OpenViewHandler(); | ||||
| 					if(confFile.length()>0) openViewHandler.setConfigFile(confFile); | ||||
| 					ContextInjectionFactory.inject(openViewHandler, ctx); | ||||
| 					eventBroker.unsubscribe(this); | ||||
| 					for(String name:args){ | ||||
| 					for(String name:opt.getSet().getData()){ | ||||
| 						if(new File(name).exists())	openViewHandler.openViewForFile(name); | ||||
| 					} | ||||
| 				} | ||||
| @@ -136,6 +148,7 @@ public class E4LifeCycle { | ||||
| 		/** The part service. */ | ||||
| 		@Inject EPartService partService; | ||||
| 		 | ||||
| 		String confFile=""; | ||||
| 		/** | ||||
| 		 * Open view for file. | ||||
| 		 * | ||||
| @@ -150,7 +163,13 @@ public class E4LifeCycle { | ||||
| 			partService.showPart(part, PartState.ACTIVATE); | ||||
| 			IEclipseContext ctx=part.getContext(); | ||||
| 			ctx.modify("input", file); //$NON-NLS-1$ | ||||
| 			ctx.declareModifiable("input"); //$NON-NLS-1$ | ||||
| 			//ctx.declareModifiable("input"); //$NON-NLS-1$ | ||||
| 			ctx.modify("config", confFile); //$NON-NLS-1$ | ||||
| 			//ctx.declareModifiable("config"); //$NON-NLS-1$				 | ||||
| 		} | ||||
|  | ||||
| 		public void setConfigFile(String confFile) { | ||||
| 			this.confFile=confFile; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -32,7 +32,7 @@ import com.minres.scviewer.e4.application.parts.WaveformViewer; | ||||
| /** | ||||
|  * The Class NavigateContribution. Currently not used in Application.e4xmi | ||||
|  */ | ||||
| public class NavigateContribution { | ||||
| public class NavigateToolbarContribution { | ||||
| 	 | ||||
| 	/** The part service. */ | ||||
| 	@Inject EPartService partService; | ||||
| @@ -0,0 +1,131 @@ | ||||
|   | ||||
| package com.minres.scviewer.e4.application.elements; | ||||
|  | ||||
| import java.util.Iterator; | ||||
| import java.util.List; | ||||
|  | ||||
| import javax.inject.Inject; | ||||
|  | ||||
| import org.eclipse.e4.core.di.annotations.Evaluate; | ||||
| import org.eclipse.e4.ui.di.AboutToHide; | ||||
| import org.eclipse.e4.ui.di.AboutToShow; | ||||
| import org.eclipse.e4.ui.model.application.MApplication; | ||||
| import org.eclipse.e4.ui.model.application.commands.MCommand; | ||||
| import org.eclipse.e4.ui.model.application.commands.MCommandsFactory; | ||||
| import org.eclipse.e4.ui.model.application.commands.MParameter; | ||||
| import org.eclipse.e4.ui.model.application.ui.basic.MPart; | ||||
| import org.eclipse.e4.ui.model.application.ui.menu.ItemType; | ||||
| import org.eclipse.e4.ui.model.application.ui.menu.MHandledMenuItem; | ||||
| import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement; | ||||
| import org.eclipse.e4.ui.model.application.ui.menu.MMenuFactory; | ||||
| import org.eclipse.e4.ui.workbench.modeling.EModelService; | ||||
| import org.eclipse.jface.viewers.ISelection; | ||||
| import org.eclipse.jface.viewers.IStructuredSelection; | ||||
|  | ||||
| import com.minres.scviewer.database.ISignal; | ||||
| import com.minres.scviewer.database.ISignalChange; | ||||
| import com.minres.scviewer.database.ISignalChangeBitVector; | ||||
| import com.minres.scviewer.database.ISignalChangeReal; | ||||
| import com.minres.scviewer.database.ui.TrackEntry; | ||||
| import com.minres.scviewer.e4.application.parts.WaveformViewer; | ||||
|  | ||||
| public class WaveformPopupMenuContribution { | ||||
| 	int counter=0; | ||||
| 	 | ||||
| 	@Inject MPart activePart; | ||||
| 		 | ||||
| 	final TrackEntry nullEntry = new TrackEntry(null); | ||||
| 	 | ||||
| 	@Evaluate | ||||
| 	public boolean evaluate() { | ||||
| 		Object obj = activePart.getObject(); | ||||
| 		if(obj instanceof WaveformViewer){ | ||||
| 			WaveformViewer wfv = (WaveformViewer)obj; | ||||
| 			ISelection sel = wfv.getSelection(); | ||||
| 			if(!sel.isEmpty() && sel instanceof IStructuredSelection) { | ||||
| 				Object selected = ((IStructuredSelection)sel).getFirstElement(); | ||||
| 				if(selected instanceof ISignal<?>) { | ||||
| 					ISignalChange s = (ISignalChange) ((ISignal<?>) selected).getEvents().firstEntry().getValue(); | ||||
| 					if((s instanceof ISignalChangeReal) || (s instanceof ISignalChangeBitVector)) { | ||||
| 						return true; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	@AboutToShow | ||||
| 	public void aboutToShow(List<MMenuElement> items, MApplication application, EModelService modelService) { | ||||
| 		Object obj = activePart.getObject(); | ||||
| 		if(obj instanceof WaveformViewer){ | ||||
| 			WaveformViewer wfv = (WaveformViewer)obj; | ||||
| 			ISelection sel = wfv.getSelection(); | ||||
| 			if(!sel.isEmpty() && sel instanceof IStructuredSelection) { | ||||
| 				Iterator<?> it = ((IStructuredSelection)sel).iterator(); | ||||
| 				Object first = it.next(); | ||||
| 				Object second=null; | ||||
| 				if(it.hasNext()) second=it.next(); | ||||
| 				if(first instanceof ISignal<?>) { | ||||
| 					ISignalChange s = (ISignalChange) ((ISignal<?>) first).getEvents().firstEntry().getValue(); | ||||
| 					//com.minres.scviewer.e4.application.menu.mulitvaluesettings | ||||
| 					if((s instanceof ISignalChangeReal) || (s instanceof ISignalChangeBitVector)) { | ||||
| 						TrackEntry entry=nullEntry; | ||||
| 						if(second instanceof TrackEntry) | ||||
| 							entry=(TrackEntry)second; | ||||
| 						if(s instanceof ISignalChangeBitVector) { | ||||
| 						    addValueMenuItem(items, application, modelService, "hex", TrackEntry.ValueDisplay.DEFAULT, entry.valueDisplay); | ||||
| 						    addValueMenuItem(items, application, modelService, "unsigned", TrackEntry.ValueDisplay.UNSIGNED, entry.valueDisplay); | ||||
| 						    addValueMenuItem(items, application, modelService, "signed", TrackEntry.ValueDisplay.SIGNED, entry.valueDisplay); | ||||
| 							items.add(MMenuFactory.INSTANCE.createMenuSeparator()); | ||||
| 							addWaveMenuItem(items, application, modelService, "bit vector", TrackEntry.WaveDisplay.DEFAULT, entry.waveDisplay); | ||||
| 						}						 | ||||
| 						addWaveMenuItem(items, application, modelService, "analog step-wise", TrackEntry.WaveDisplay.STEP_WISE, entry.waveDisplay); | ||||
| 						addWaveMenuItem(items, application, modelService, "analog continous", TrackEntry.WaveDisplay.CONTINOUS, entry.waveDisplay); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	private void addValueMenuItem(List<MMenuElement> items, MApplication application, EModelService modelService, | ||||
| 			String label, TrackEntry.ValueDisplay value, TrackEntry.ValueDisplay actual) { | ||||
| 		MHandledMenuItem item = MMenuFactory.INSTANCE.createHandledMenuItem(); | ||||
| 		item.setType(ItemType.RADIO); | ||||
| 		item.setSelected(value==actual); | ||||
| 		item.setLabel("Show as "+label); | ||||
| 		item.setContributorURI("platform:/plugin/com.minres.scviewer.e4.application"); | ||||
| 		List<MCommand> cmds = modelService.findElements(application, "com.minres.scviewer.e4.application.command.changevaluedisplay", MCommand.class, null); | ||||
| 		if(cmds.size()!=1) System.err.println("No command found!"); | ||||
| 		else item.setCommand(cmds.get(0)); | ||||
| 		MParameter param = MCommandsFactory.INSTANCE.createParameter(); | ||||
| 		param.setName("com.minres.scviewer.e4.application.commandparameter.changevaluedisplay"); | ||||
| 		param.setValue(value.toString()); | ||||
| 		item.getParameters().add(param); | ||||
| 		items.add(item); | ||||
| 	} | ||||
| 	 | ||||
| 	private void addWaveMenuItem(List<MMenuElement> items, MApplication application, EModelService modelService, | ||||
| 			String label, TrackEntry.WaveDisplay value, TrackEntry.WaveDisplay actual) { | ||||
| 		MHandledMenuItem item = MMenuFactory.INSTANCE.createHandledMenuItem(); | ||||
| 		item.setType(ItemType.RADIO); | ||||
| 		item.setSelected(value==actual); | ||||
| 		item.setLabel("Render "+label); | ||||
| 		item.setContributorURI("platform:/plugin/com.minres.scviewer.e4.application"); | ||||
| 		List<MCommand> cmds = modelService.findElements(application, "com.minres.scviewer.e4.application.command.changewavedisplay", MCommand.class, null); | ||||
| 		if(cmds.size()!=1) System.err.println("No command found!"); | ||||
| 		else item.setCommand(cmds.get(0)); | ||||
| 		MParameter param = MCommandsFactory.INSTANCE.createParameter(); | ||||
| 		param.setName("com.minres.scviewer.e4.application.commandparameter.changewavedisplay"); | ||||
| 		param.setValue(value.toString()); | ||||
| 		item.getParameters().add(param); | ||||
| 		items.add(item); | ||||
| 	} | ||||
| 	 | ||||
| 	@AboutToHide | ||||
| 	public void aboutToHide(List<MMenuElement> items) { | ||||
| 		 | ||||
| 	} | ||||
| 		 | ||||
| } | ||||
| @@ -12,16 +12,17 @@ package com.minres.scviewer.e4.application.handlers; | ||||
|  | ||||
| import org.eclipse.e4.core.di.annotations.Execute; | ||||
| import org.eclipse.e4.ui.model.application.MApplication; | ||||
| import org.eclipse.e4.ui.model.application.ui.basic.MDialog; | ||||
| import org.eclipse.e4.ui.model.application.ui.basic.MWindow; | ||||
| import org.eclipse.e4.ui.workbench.modeling.EModelService; | ||||
| import org.eclipse.swt.widgets.Shell; | ||||
|  | ||||
| public class AboutHandler { | ||||
|  | ||||
| 	static final String DIALOG_ID="com.minres.scviewer.e4.application.dialog.aboutscviewer"; | ||||
| 	 | ||||
| 	@Execute | ||||
| 	public void execute(Shell shell, MApplication app, MWindow window, EModelService ms /*@Named("mdialog01.dialog.0") MDialog dialog*/) { | ||||
| 		MDialog dialog = (MDialog) ms.find("com.minres.scviewer.e4.application.dialog.aboutscviewer", app); //$NON-NLS-1$ | ||||
| 		MWindow dialog = (MWindow) ms.find(DIALOG_ID, app); //$NON-NLS-1$ | ||||
| 		dialog.setToBeRendered(true); | ||||
| 		dialog.setToBeRendered(false); | ||||
| 	} | ||||
|   | ||||
| @@ -0,0 +1,51 @@ | ||||
|   | ||||
| package com.minres.scviewer.e4.application.handlers; | ||||
|  | ||||
| import java.util.Iterator; | ||||
|  | ||||
| import javax.inject.Named; | ||||
|  | ||||
| import org.eclipse.e4.core.di.annotations.CanExecute; | ||||
| import org.eclipse.e4.core.di.annotations.Execute; | ||||
| import org.eclipse.e4.ui.model.application.ui.basic.MPart; | ||||
| import org.eclipse.e4.ui.workbench.modeling.EPartService; | ||||
| import org.eclipse.jface.viewers.ISelection; | ||||
| import org.eclipse.jface.viewers.IStructuredSelection; | ||||
|  | ||||
| import com.minres.scviewer.database.ui.TrackEntry; | ||||
| import com.minres.scviewer.e4.application.parts.WaveformViewer; | ||||
|  | ||||
| public class ChangeValueDisplay { | ||||
| 	 | ||||
| 	static final String PARAMETER_ID="com.minres.scviewer.e4.application.commandparameter.changevaluedisplay"; //$NON-NLS-1$ | ||||
|  | ||||
| 	@CanExecute | ||||
| 	public boolean canExecute(EPartService partService) { | ||||
| 		MPart part = partService.getActivePart(); | ||||
| 		if(part==null) return false; | ||||
| 		return (part.getObject() instanceof WaveformViewer); | ||||
| 	} | ||||
|  | ||||
| 	@Execute | ||||
| 	public void execute(@Named(PARAMETER_ID) String param, EPartService partService) { | ||||
| 		MPart part = partService.getActivePart(); | ||||
| 		Object obj = part.getObject(); | ||||
| 		if(obj instanceof WaveformViewer){ | ||||
| 			WaveformViewer wfv = (WaveformViewer)obj; | ||||
| 			ISelection sel = wfv.getSelection(); | ||||
| 			if(!sel.isEmpty() && sel instanceof IStructuredSelection) { | ||||
| 				Iterator<?> it = ((IStructuredSelection)sel).iterator(); | ||||
| 				it.next(); | ||||
| 				if(it.hasNext()) { | ||||
| 						Object second = it.next(); | ||||
| 						if(second instanceof TrackEntry) { | ||||
| 							TrackEntry.ValueDisplay val = TrackEntry.ValueDisplay.valueOf(param); | ||||
| 							((TrackEntry)second).valueDisplay=val; | ||||
| 							wfv.update(); | ||||
| 						} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 		 | ||||
| } | ||||
| @@ -0,0 +1,51 @@ | ||||
|   | ||||
| package com.minres.scviewer.e4.application.handlers; | ||||
|  | ||||
| import java.util.Iterator; | ||||
|  | ||||
| import javax.inject.Named; | ||||
|  | ||||
| import org.eclipse.e4.core.di.annotations.CanExecute; | ||||
| import org.eclipse.e4.core.di.annotations.Execute; | ||||
| import org.eclipse.e4.ui.model.application.ui.basic.MPart; | ||||
| import org.eclipse.e4.ui.workbench.modeling.EPartService; | ||||
| import org.eclipse.jface.viewers.ISelection; | ||||
| import org.eclipse.jface.viewers.IStructuredSelection; | ||||
|  | ||||
| import com.minres.scviewer.database.ui.TrackEntry; | ||||
| import com.minres.scviewer.e4.application.parts.WaveformViewer; | ||||
|  | ||||
| public class ChangeWaveformDisplay { | ||||
| 	 | ||||
| 	static final String PARAMETER_ID="com.minres.scviewer.e4.application.commandparameter.changewavedisplay"; //$NON-NLS-1$ | ||||
|  | ||||
| 	@CanExecute | ||||
| 	public boolean canExecute(EPartService partService) { | ||||
| 		MPart part = partService.getActivePart(); | ||||
| 		if(part==null) return false; | ||||
| 		return (part.getObject() instanceof WaveformViewer); | ||||
| 	} | ||||
|  | ||||
| 	@Execute | ||||
| 	public void execute(@Named(PARAMETER_ID) String param, EPartService partService) { | ||||
| 		MPart part = partService.getActivePart(); | ||||
| 		Object obj = part.getObject(); | ||||
| 		if(obj instanceof WaveformViewer){ | ||||
| 			WaveformViewer wfv = (WaveformViewer)obj; | ||||
| 			ISelection sel = wfv.getSelection(); | ||||
| 			if(!sel.isEmpty() && sel instanceof IStructuredSelection) { | ||||
| 				Iterator<?> it = ((IStructuredSelection)sel).iterator(); | ||||
| 				it.next(); | ||||
| 				if(it.hasNext()) { | ||||
| 						Object second = it.next(); | ||||
| 						if(second instanceof TrackEntry) { | ||||
| 							TrackEntry.WaveDisplay val= TrackEntry.WaveDisplay.valueOf(param); | ||||
| 							((TrackEntry)second).waveDisplay=val; | ||||
| 							wfv.update(); | ||||
| 						} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 		 | ||||
| } | ||||
| @@ -1,5 +1,5 @@ | ||||
| AboutDialog_0=\nSCViewer - a SystemC waveform viewer\n\nVersion: 1.2.2\n | ||||
| AboutDialog_1=\nCopyright (c) 2015,2016,2017 MINRES Technologies GmbH and others.\n\nAll rights reserved. MINRES and the MINRES logo are trademarks of MINRES Technologies GmbH, http://www.minres.com/. 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\n\nParts of the software are governed by the Apache License Version 2.0 available at http://www.apache.org/licenses/. These are namely org.apache.jdbm and org.sqlite JDBC driver\n\nSources code is hosted at GitHub: https://github.com/minres/SCViewer\n | ||||
| AboutDialog_0=\nSCViewer - a SystemC waveform viewer\n\nVersion: 2.0\n | ||||
| AboutDialog_1=\nCopyright (c) 2015, 2018 MINRES Technologies GmbH and others.\n\nAll rights reserved. MINRES and the MINRES logo are trademarks of MINRES Technologies GmbH, http://www.minres.com/. 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\n\nParts of the software are governed by the Apache License Version 2.0 available at http://www.apache.org/licenses/. These are namely org.apache.jdbm and org.sqlite JDBC driver\n\nSources code is hosted at GitHub: https://github.com/minres/SCViewer\n | ||||
| DesignBrowser_12=Append all after | ||||
| DesignBrowser_16=Insert all before | ||||
| DesignBrowser_2=Enter text to filter waveforms | ||||
|   | ||||
| @@ -0,0 +1,275 @@ | ||||
| package com.minres.scviewer.e4.application.options; | ||||
|  | ||||
| /** | ||||
|  * This class holds all the data for an option. This includes the prefix, the key, the separator  | ||||
|  * (for value options), the multiplicity, and all the other settings describing the option. The class | ||||
|  * is designed to be only a data container from a user perspective, i. e. the user has read-access to  | ||||
|  * any data determined by the {@link Options#check()}, but not access to any of the other methods | ||||
|  * which are used internally for the operation of the actual check.  | ||||
|  */ | ||||
|  | ||||
| public class OptionData { | ||||
|  | ||||
|   private final static String CLASS = "OptionData"; | ||||
|  | ||||
|   private Options.Prefix              prefix       = null; | ||||
|   private String                      key          = null;  | ||||
|   private boolean                     detail       = false;  | ||||
|   private Options.Separator           separator    = null;  | ||||
|   private boolean                     value        = false;  | ||||
|   private Options.Multiplicity        multiplicity = null; | ||||
|   private java.util.regex.Pattern     pattern      = null; | ||||
|   private int                         counter      = 0; | ||||
|   private java.util.ArrayList<String> values       = null; | ||||
|   private java.util.ArrayList<String> details      = null; | ||||
|  | ||||
| /** | ||||
|  * The constructor | ||||
|  */ | ||||
|  | ||||
|   OptionData(Options.Prefix prefix,  | ||||
|              String key,  | ||||
|              boolean detail,  | ||||
|              Options.Separator separator,  | ||||
|              boolean value,  | ||||
|              Options.Multiplicity multiplicity) { | ||||
|  | ||||
|     if (prefix       == null) throw new IllegalArgumentException(CLASS + ": prefix may not be null"); | ||||
|     if (key          == null) throw new IllegalArgumentException(CLASS + ": key may not be null"); | ||||
|     if (separator    == null) throw new IllegalArgumentException(CLASS + ": separator may not be null"); | ||||
|     if (multiplicity == null) throw new IllegalArgumentException(CLASS + ": multiplicity may not be null"); | ||||
|  | ||||
| //.... The data describing the option | ||||
|  | ||||
|     this.prefix       = prefix; | ||||
|     this.key          = key; | ||||
|     this.detail       = detail; | ||||
|     this.separator    = separator; | ||||
|     this.value        = value; | ||||
|     this.multiplicity = multiplicity; | ||||
|  | ||||
| //.... Create the pattern to match this option | ||||
|  | ||||
|     if (value) { | ||||
|       if (separator == Options.Separator.BLANK) { | ||||
|         if (detail) { | ||||
|           pattern = java.util.regex.Pattern.compile(prefix.getName() + key + "((\\w|\\.)+)$"); | ||||
|         } else { | ||||
|           pattern = java.util.regex.Pattern.compile(prefix.getName() + key + "$"); | ||||
|         } | ||||
|       } else { | ||||
|         if (detail) { | ||||
|           pattern = java.util.regex.Pattern.compile(prefix.getName() + key + "((\\w|\\.)+)" + separator.getName() + "(.+)$"); | ||||
|         } else { | ||||
|           pattern = java.util.regex.Pattern.compile(prefix.getName() + key + separator.getName() + "(.+)$"); | ||||
|         } | ||||
|       } | ||||
|     } else { | ||||
|       pattern = java.util.regex.Pattern.compile(prefix.getName() + key + "$"); | ||||
|     } | ||||
|  | ||||
| //.... Structures to hold result data | ||||
|  | ||||
|     if (value) { | ||||
|       values = new java.util.ArrayList<String>(); | ||||
|       if (detail)  | ||||
|         details = new java.util.ArrayList<String>(); | ||||
|     } | ||||
|      | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Getter method for <code>prefix</code> property | ||||
|  * <p> | ||||
|  * @return The value for the <code>prefix</code> property | ||||
|  */ | ||||
|  | ||||
|   Options.Prefix getPrefix() { | ||||
|     return prefix; | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Getter method for <code>key</code> property | ||||
|  * <p> | ||||
|  * @return The value for the <code>key</code> property | ||||
|  */ | ||||
|  | ||||
|   String getKey() { | ||||
|     return key; | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Getter method for <code>detail</code> property | ||||
|  * <p> | ||||
|  * @return The value for the <code>detail</code> property | ||||
|  */ | ||||
|  | ||||
|   boolean useDetail() { | ||||
|     return detail; | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Getter method for <code>separator</code> property | ||||
|  * <p> | ||||
|  * @return The value for the <code>separator</code> property | ||||
|  */ | ||||
|  | ||||
|   Options.Separator getSeparator() { | ||||
|     return separator; | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Getter method for <code>value</code> property | ||||
|  * <p> | ||||
|  * @return The value for the <code>value</code> property | ||||
|  */ | ||||
|  | ||||
|   boolean useValue() { | ||||
|     return value; | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Getter method for <code>multiplicity</code> property | ||||
|  * <p> | ||||
|  * @return The value for the <code>multiplicity</code> property | ||||
|  */ | ||||
|  | ||||
|   Options.Multiplicity getMultiplicity() { | ||||
|     return multiplicity; | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Getter method for <code>pattern</code> property | ||||
|  * <p> | ||||
|  * @return The value for the <code>pattern</code> property | ||||
|  */ | ||||
|  | ||||
|   java.util.regex.Pattern getPattern() { | ||||
|     return pattern; | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Get the number of results found for this option, which is number of times the key matched | ||||
|  * <p> | ||||
|  * @return The number of results | ||||
|  */ | ||||
|  | ||||
|   public int getResultCount() { | ||||
|     if (value) { | ||||
|       return values.size(); | ||||
|     } else { | ||||
|       return counter; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Get the value with the given index. The index can range between 0 and {@link #getResultCount()}<code> - 1</code>. | ||||
|  * However, only for value options, a non-<code>null</code> value will be returned. Non-value options always  | ||||
|  * return <code>null</code>. | ||||
|  * <p> | ||||
|  * @param index The index for the desired value | ||||
|  * <p> | ||||
|  * @return The option value with the given index | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If the value for <code>index</code> is out of bounds | ||||
|  */ | ||||
|  | ||||
|   public String getResultValue(int index) { | ||||
|     if (!value) return null; | ||||
|     if (index < 0 || index >= getResultCount()) throw new IllegalArgumentException(CLASS + ": illegal value for index"); | ||||
|     return values.get(index); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Get the detail with the given index. The index can range between 0 and {@link #getResultCount()}<code> - 1</code>. | ||||
|  * However, only for value options which take details, a non-<code>null</code> detail will be returned. Non-value options  | ||||
|  * and value options which do not take details always return <code>null</code>. | ||||
|  * <p> | ||||
|  * @param index The index for the desired value | ||||
|  * <p> | ||||
|  * @return The option detail with the given index | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If the value for <code>index</code> is out of bounds | ||||
|  */ | ||||
|  | ||||
|   public String getResultDetail(int index) { | ||||
|     if (!detail) return null; | ||||
|     if (index < 0 || index >= getResultCount()) throw new IllegalArgumentException(CLASS + ": illegal value for index"); | ||||
|     return details.get(index); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Store the data for a match found | ||||
|  */ | ||||
|  | ||||
|   void addResult(String valueData, String detailData) { | ||||
|     if (value) { | ||||
|       if (valueData == null) throw new IllegalArgumentException(CLASS + ": valueData may not be null"); | ||||
|       values.add(valueData); | ||||
|       if (detail) { | ||||
|         if (detailData == null) throw new IllegalArgumentException(CLASS + ": detailData may not be null"); | ||||
|         details.add(detailData); | ||||
|       } | ||||
|     }  | ||||
|     counter++; | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * This is the overloaded {@link Object#toString()} method, and it is provided mainly for debugging  | ||||
|  * purposes. | ||||
|  * <p> | ||||
|  * @return A string representing the instance | ||||
|  */ | ||||
|  | ||||
|   public String toString() { | ||||
|  | ||||
|     StringBuffer sb = new StringBuffer(); | ||||
|  | ||||
|     sb.append("Prefix      : "); | ||||
|     sb.append(prefix); | ||||
|     sb.append('\n'); | ||||
|     sb.append("Key         : "); | ||||
|     sb.append(key); | ||||
|     sb.append('\n'); | ||||
|     sb.append("Detail      : "); | ||||
|     sb.append(detail); | ||||
|     sb.append('\n'); | ||||
|     sb.append("Separator   : "); | ||||
|     sb.append(separator); | ||||
|     sb.append('\n'); | ||||
|     sb.append("Value       : "); | ||||
|     sb.append(value); | ||||
|     sb.append('\n'); | ||||
|     sb.append("Multiplicity: "); | ||||
|     sb.append(multiplicity); | ||||
|     sb.append('\n'); | ||||
|     sb.append("Pattern     : "); | ||||
|     sb.append(pattern); | ||||
|     sb.append('\n'); | ||||
|  | ||||
|     sb.append("Results     : "); | ||||
|     sb.append(counter); | ||||
|     sb.append('\n'); | ||||
|     if (value) { | ||||
|       if (detail) { | ||||
|         for (int i = 0; i < values.size(); i++) { | ||||
|           sb.append(details.get(i)); | ||||
|           sb.append(" / "); | ||||
|           sb.append(values.get(i)); | ||||
|           sb.append('\n'); | ||||
|         } | ||||
|       } else { | ||||
|         for (int i = 0; i < values.size(); i++) { | ||||
|           sb.append(values.get(i)); | ||||
|           sb.append('\n'); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|      | ||||
|     return sb.toString(); | ||||
|  | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -0,0 +1,276 @@ | ||||
| package com.minres.scviewer.e4.application.options; | ||||
|  | ||||
| /** | ||||
|  * This class holds the information for a <i>set</i> of options. A set can hold any number of  | ||||
|  * <code>OptionData</code> instances which are checked together to determine success or failure.  | ||||
|  * <p> | ||||
|  * The approach to use this class looks like this: | ||||
|  * <p> | ||||
|  * <ol> | ||||
|  * <li> The user uses any of the <code>Options.addSet()</code> (e. g. {@link Options#addSet(String)}) to create  | ||||
|  *      any number of sets required (or just relies on the default set, if only one set is required) | ||||
|  * <li> The user adds all required option definitions to each set | ||||
|  * <li> Using any of the <code>Options.check()</code> methods, each set can be checked whether the options | ||||
|  *      that were specified on the command line satisfy its requirements | ||||
|  * <li> If the check was successful for a given set, several data items are available from this class: | ||||
|  *      <ul> | ||||
|  *      <li> All options defined for the set (through with e. g. values, details, and multiplicity are available) | ||||
|  *      <li> All data items found (these are the items on the command line which do not start with the prefix,  | ||||
|  *           i. e. non-option arguments) | ||||
|  *      <li> All unmatched arguments on the command line (these are the items on the command line which start  | ||||
|  *           with the prefix, but do not match to one of the options). | ||||
|  *           Programs can elect to ignore these, or react with an error | ||||
|  *      </ul> | ||||
|  * </ol> | ||||
|  */ | ||||
|  | ||||
| public class OptionSet { | ||||
|  | ||||
|   private final static String CLASS = "OptionSet"; | ||||
|  | ||||
|   private java.util.ArrayList<OptionData>       options             = new java.util.ArrayList<OptionData>(); | ||||
|   private java.util.HashMap<String, OptionData> keys                = new java.util.HashMap<String, OptionData>(); | ||||
|   private java.util.ArrayList<String>           unmatched           = new java.util.ArrayList<String>(); | ||||
|   private java.util.ArrayList<String>           data                = new java.util.ArrayList<String>(); | ||||
|   private String                                setName             = null; | ||||
|   private int                                   minData             = 0; | ||||
|   private int                                   maxData             = 0; | ||||
|   private Options.Prefix                        prefix              = null; | ||||
|   private Options.Multiplicity                  defaultMultiplicity = null; | ||||
|  | ||||
| /** | ||||
|  * Constructor | ||||
|  */ | ||||
|  | ||||
|   OptionSet(Options.Prefix prefix, Options.Multiplicity defaultMultiplicity, String setName, int minData, int maxData) { | ||||
|     if (setName == null)   throw new IllegalArgumentException(CLASS + ": setName may not be null"); | ||||
|     if (minData < 0)       throw new IllegalArgumentException(CLASS + ": minData must be >= 0"); | ||||
|     if (maxData < minData) throw new IllegalArgumentException(CLASS + ": maxData must be >= minData"); | ||||
|     this.prefix              = prefix; | ||||
|     this.defaultMultiplicity = defaultMultiplicity; | ||||
|     this.setName             = setName; | ||||
|     this.minData             = minData; | ||||
|     this.maxData             = maxData; | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Get a list of all the options defined for this set | ||||
|  * <p> | ||||
|  * @return A list of {@link OptionData} instances defined for this set | ||||
|  */ | ||||
|  | ||||
|   public java.util.ArrayList<OptionData> getOptionData() { | ||||
|     return options; | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Get the data for a specific option, identified by its key name (which is unique) | ||||
|  * <p> | ||||
|  * @param key The key for the option | ||||
|  * <p> | ||||
|  * @return The {@link OptionData} instance | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If the <code>key</code> is <code>null</code> or unknown in this set | ||||
|  */ | ||||
|  | ||||
|   public OptionData getOption(String key) { | ||||
|     if (key == null) throw new IllegalArgumentException(CLASS + ": key may not be null"); | ||||
|     if (!keys.containsKey(key)) throw new IllegalArgumentException(CLASS + ": unknown key: " + key); | ||||
|     return keys.get(key); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Check whether a specific option is set, i. e. whether it was specified at least once on the command line.  | ||||
|  * <p> | ||||
|  * @param key The key for the option | ||||
|  * <p> | ||||
|  * @return <code>true</code> or <code>false</code>, depending on the outcome of the check | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If the <code>key</code> is <code>null</code> or unknown in this set | ||||
|  */ | ||||
|  | ||||
|   public boolean isSet(String key) { | ||||
|     if (key == null) throw new IllegalArgumentException(CLASS + ": key may not be null"); | ||||
|     if (!keys.containsKey(key)) throw new IllegalArgumentException(CLASS + ": unknown key: " + key); | ||||
|     return keys.get(key).getResultCount() > 0 ? true : false; | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Getter method for <code>setName</code> property | ||||
|  * <p> | ||||
|  * @return The value for the <code>setName</code> property | ||||
|  */ | ||||
|  | ||||
|   public String getSetName() { | ||||
|     return setName; | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Getter method for <code>minData</code> property | ||||
|  * <p> | ||||
|  * @return The value for the <code>minData</code> property | ||||
|  */ | ||||
|  | ||||
|   public int getMinData() { | ||||
|     return minData; | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Getter method for <code>maxData</code> property | ||||
|  * <p> | ||||
|  * @return The value for the <code>maxData</code> property | ||||
|  */ | ||||
|  | ||||
|   public int getMaxData() { | ||||
|     return maxData; | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Return the data items found (these are the items on the command line which do not start with the prefix, i. e. non-option arguments) | ||||
|  * <p> | ||||
|  * @return A list of strings with all data items found | ||||
|  */ | ||||
|  | ||||
|   public java.util.ArrayList<String> getData() { | ||||
|     return data; | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Return all unmatched items found (these are the items on the command line which start with the prefix, but do not | ||||
|  * match to one of the options) | ||||
|  * <p> | ||||
|  * @return A list of strings with all unmatched items found | ||||
|  */ | ||||
|  | ||||
|   public java.util.ArrayList<String> getUnmatched() { | ||||
|     return unmatched; | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Add a non-value option with the given key, and the default prefix and multiplicity | ||||
|  * <p> | ||||
|  * @param key The key for the option | ||||
|  * <p> | ||||
|  * @return The set instance itself (to support invocation chaining for <code>addOption()</code> methods) | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If the <code>key</code> is <code>null</code> or a key with this name has already been defined | ||||
|  */ | ||||
|  | ||||
|   public OptionSet addOption(String key) { | ||||
|     return addOption(key, defaultMultiplicity); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Add a non-value option with the given key and multiplicity, and the default prefix | ||||
|  * <p> | ||||
|  * @param key          The key for the option | ||||
|  * @param multiplicity The multiplicity for the option | ||||
|  * <p> | ||||
|  * @return The set instance itself (to support invocation chaining for <code>addOption()</code> methods) | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If the <code>key</code> is <code>null</code> or a key with this name has already been defined | ||||
|  *                                  or if <code>multiplicity</code> is <code>null</code> | ||||
|  */ | ||||
|  | ||||
|   public OptionSet addOption(String key, Options.Multiplicity multiplicity) { | ||||
|     return addOption(key, false, Options.Separator.NONE, false, multiplicity); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Add a value option with the given key and separator, no details, and the default prefix and multiplicity | ||||
|  * <p> | ||||
|  * @param key       The key for the option | ||||
|  * @param separator The separator for the option | ||||
|  * <p> | ||||
|  * @return The set instance itself (to support invocation chaining for <code>addOption()</code> methods) | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If the <code>key</code> is <code>null</code> or a key with this name has already been defined | ||||
|  *                                  or if <code>separator</code> is <code>null</code> | ||||
|  */ | ||||
|  | ||||
|   public OptionSet addOption(String key, Options.Separator separator) { | ||||
|     return addOption(key, false, separator, true, defaultMultiplicity); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Add a value option with the given key, separator, and multiplicity, no details, and the default prefix | ||||
|  * <p> | ||||
|  * @param key          The key for the option | ||||
|  * @param separator    The separator for the option | ||||
|  * @param multiplicity The multiplicity for the option | ||||
|  * <p> | ||||
|  * @return The set instance itself (to support invocation chaining for <code>addOption()</code> methods) | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If the <code>key</code> is <code>null</code> or a key with this name has already been defined | ||||
|  *                                  or if <code>separator</code> or <code>multiplicity</code> are <code>null</code> | ||||
|  */ | ||||
|  | ||||
|   public OptionSet addOption(String key, Options.Separator separator, Options.Multiplicity multiplicity) { | ||||
|     return addOption(key, false, separator, true, multiplicity); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  *  | ||||
|  * Add a value option with the given key and separator, possibly details, and the default prefix and multiplicity | ||||
|  * <p> | ||||
|  * @param key       The key for the option | ||||
|  * @param details   A boolean indicating whether details are expected for the option | ||||
|  * @param separator The separator for the option | ||||
|  * <p> | ||||
|  * @return The set instance itself (to support invocation chaining for <code>addOption()</code> methods) | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If the <code>key</code> is <code>null</code> or a key with this name has already been defined | ||||
|  *                                  or if <code>separator</code> is <code>null</code> | ||||
|  */ | ||||
|  | ||||
|   public OptionSet addOption(String key, boolean details, Options.Separator separator) { | ||||
|     return addOption(key, details, separator, true, defaultMultiplicity); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Add a value option with the given key, separator, and multiplicity, possibly details, and the default prefix | ||||
|  * <p> | ||||
|  * @param key          The key for the option | ||||
|  * @param details      A boolean indicating whether details are expected for the option | ||||
|  * @param separator    The separator for the option | ||||
|  * @param multiplicity The multiplicity for the option | ||||
|  * <p> | ||||
|  * @return The set instance itself (to support invocation chaining for <code>addOption()</code> methods) | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If the <code>key</code> is <code>null</code> or a key with this name has already been defined | ||||
|  *                                  or if <code>separator</code> or <code>multiplicity</code> are <code>null</code> | ||||
|  */ | ||||
|  | ||||
|   public OptionSet addOption(String key, boolean details, Options.Separator separator, Options.Multiplicity multiplicity) { | ||||
|     return addOption(key, details, separator, true, multiplicity); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * The master method to add an option. Since there are combinations which are not  | ||||
|  * acceptable (like a NONE separator and a true value), this method is not public. | ||||
|  * Internally, we only supply acceptable combinations. | ||||
|  */ | ||||
|  | ||||
|   OptionSet addOption(String key,  | ||||
|                       boolean details,  | ||||
|                       Options.Separator separator,  | ||||
|                       boolean value,  | ||||
|                       Options.Multiplicity multiplicity) { | ||||
|  | ||||
|     if (key == null) throw new IllegalArgumentException(CLASS + ": key may not be null"); | ||||
|     if (multiplicity == null) throw new IllegalArgumentException(CLASS + ": multiplicity may not be null"); | ||||
|     if (separator == null) throw new IllegalArgumentException(CLASS + ": separator may not be null"); | ||||
|     if (keys.containsKey(key))  throw new IllegalArgumentException(CLASS + ": the key "  | ||||
|         + key + " has already been defined for this OptionSet"); | ||||
|  | ||||
|     OptionData od = new OptionData(prefix, key, details, separator, value, multiplicity); | ||||
|     options.add(od); | ||||
|     keys.put(key, od); | ||||
|  | ||||
|     return this; | ||||
|      | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -0,0 +1,768 @@ | ||||
| package com.minres.scviewer.e4.application.options; | ||||
|  | ||||
| /** | ||||
|  * The central class for option processing. Sets are identified by their name, but there is also  | ||||
|  * an anonymous default set, which is very convenient if an application requieres only one set.  | ||||
|  */ | ||||
|  | ||||
| public class Options { | ||||
|  | ||||
|   private final static String CLASS = "Options"; | ||||
|  | ||||
| /** | ||||
|  * The name used internally for the default set | ||||
|  */ | ||||
|  | ||||
|   public final static String DEFAULT_SET = "DEFAULT_OPTION_SET"; | ||||
|  | ||||
| /** | ||||
|  * An enum encapsulating the possible separators between value options and their actual values.  | ||||
|  */ | ||||
|  | ||||
|   public enum Separator { | ||||
|    | ||||
| /** | ||||
|  * Separate option and value by ":" | ||||
|  */ | ||||
|  | ||||
|     COLON(':'), | ||||
|  | ||||
| /** | ||||
|  * Separate option and value by "=" | ||||
|  */ | ||||
|  | ||||
|     EQUALS('='), | ||||
|  | ||||
| /** | ||||
|  * Separate option and value by blank space | ||||
|  */ | ||||
|  | ||||
|     BLANK(' '),      // Or, more precisely, whitespace (as allowed by the CLI) | ||||
|  | ||||
| /** | ||||
|  * This is just a placeholder in case no separator is required (i. e. for non-value options) | ||||
|  */ | ||||
|  | ||||
|     NONE('D');       // NONE is a placeholder in case no separator is required, 'D' is just an arbitrary dummy value | ||||
|    | ||||
|     private char c; | ||||
|    | ||||
|     private Separator(char c) { | ||||
|       this.c = c; | ||||
|     } | ||||
|    | ||||
| /** | ||||
|  * Return the actual separator character  | ||||
|  * <p> | ||||
|  * @return The actual separator character | ||||
|  */ | ||||
|  | ||||
|     char getName() { | ||||
|       return c; | ||||
|     } | ||||
|    | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * An enum encapsulating the possible prefixes identifying options (and separating them from command line data items) | ||||
|  */ | ||||
|  | ||||
|   public enum Prefix { | ||||
|  | ||||
| /** | ||||
|  * Options start with a "-" (typically on Unix platforms) | ||||
|  */ | ||||
|  | ||||
|     DASH('-'), | ||||
|  | ||||
| /** | ||||
|  * Options start with a "/" (typically on Windows platforms) | ||||
|  */ | ||||
|  | ||||
|     SLASH('/'); | ||||
|    | ||||
|     private char c; | ||||
|    | ||||
|     private Prefix(char c) { | ||||
|       this.c = c; | ||||
|     } | ||||
|    | ||||
| /** | ||||
|  * Return the actual prefix character  | ||||
|  * <p> | ||||
|  * @return The actual prefix character | ||||
|  */ | ||||
|  | ||||
|     char getName() { | ||||
|       return c; | ||||
|     } | ||||
|    | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * An enum encapsulating the possible multiplicities for options | ||||
|  */ | ||||
|  | ||||
|   public enum Multiplicity { | ||||
|  | ||||
| /** | ||||
|  * Option needs to occur exactly once | ||||
|  */ | ||||
|  | ||||
|     ONCE, | ||||
|  | ||||
| /** | ||||
|  * Option needs to occur at least once | ||||
|  */ | ||||
|  | ||||
|     ONCE_OR_MORE, | ||||
|  | ||||
| /** | ||||
|  * Option needs to occur either once or not at all | ||||
|  */ | ||||
|  | ||||
|     ZERO_OR_ONE,  | ||||
|  | ||||
| /** | ||||
|  * Option can occur any number of times | ||||
|  */ | ||||
|  | ||||
|     ZERO_OR_MORE;  | ||||
|  | ||||
|   } | ||||
|  | ||||
|   private java.util.HashMap<String, OptionSet> optionSets          = new java.util.HashMap<String, OptionSet>(); | ||||
|   private Prefix                               prefix              = null; | ||||
|   private Multiplicity                         defaultMultiplicity = null; | ||||
|   private String[]                             arguments           = null; | ||||
|   private int                                  defaultMinData      = 0; | ||||
|   private int                                  defaultMaxData      = 0; | ||||
|   private StringBuffer                         checkErrors         = null; | ||||
|  | ||||
| /** | ||||
|  * Constructor | ||||
|  * <p> | ||||
|  * @param args                The command line arguments to check | ||||
|  * @param prefix              The prefix to use for all command line options. It can only be set here for all options at  | ||||
|  *                            the same time | ||||
|  * @param defaultMultiplicity The default multiplicity to use for all options (can be overridden when adding an option) | ||||
|  * @param defMinData          The default minimum number of data items for all sets (can be overridden when adding a set) | ||||
|  * @param defMaxData          The default maximum number of data items for all sets (can be overridden when adding a set) | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If either <code>args</code>, <code>prefix</code>, or <code>defaultMultiplicity</code>  | ||||
|  *                                  is <code>null</code> - or if the data range values don't make sense | ||||
|  */ | ||||
|  | ||||
|   public Options(String args[], Prefix prefix, Multiplicity defaultMultiplicity, int defMinData, int defMaxData) { | ||||
|  | ||||
|     if (args                == null) throw new IllegalArgumentException(CLASS + ": args may not be null"); | ||||
|     if (prefix              == null) throw new IllegalArgumentException(CLASS + ": prefix may not be null"); | ||||
|     if (defaultMultiplicity == null) throw new IllegalArgumentException(CLASS + ": defaultMultiplicity may not be null"); | ||||
|  | ||||
|     if (defMinData < 0) throw new IllegalArgumentException(CLASS + ": defMinData must be >= 0"); | ||||
|     if (defMaxData < defMinData) throw new IllegalArgumentException(CLASS + ": defMaxData must be >= defMinData"); | ||||
|  | ||||
|     arguments = new String[args.length]; | ||||
|     int i = 0; | ||||
|     for (String s : args)  | ||||
|       arguments[i++] = s; | ||||
|  | ||||
|     this.prefix              = prefix; | ||||
|     this.defaultMultiplicity = defaultMultiplicity; | ||||
|     this.defaultMinData      = defMinData; | ||||
|     this.defaultMaxData      = defMaxData; | ||||
|  | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Constructor | ||||
|  * <p> | ||||
|  * @param args                The command line arguments to check | ||||
|  * @param prefix              The prefix to use for all command line options. It can only be set here for all options at  | ||||
|  *                            the same time | ||||
|  * @param defaultMultiplicity The default multiplicity to use for all options (can be overridden when adding an option) | ||||
|  * @param data                The default minimum and maximum number of data items for all sets (can be overridden when adding a set) | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If either <code>args</code>, <code>prefix</code>, or <code>defaultMultiplicity</code>  | ||||
|  *                                  is <code>null</code> - or if the data range value doesn't make sense | ||||
|  */ | ||||
|  | ||||
|   public Options(String args[], Prefix prefix, Multiplicity defaultMultiplicity, int data) { | ||||
|     this(args, prefix, defaultMultiplicity, data, data); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Constructor. The default number of data items is set to 0. | ||||
|  * <p> | ||||
|  * @param args                The command line arguments to check | ||||
|  * @param prefix              The prefix to use for all command line options. It can only be set here for all options at  | ||||
|  *                            the same time | ||||
|  * @param defaultMultiplicity The default multiplicity to use for all options (can be overridden when adding an option) | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If either <code>args</code>, <code>prefix</code>, or <code>defaultMultiplicity</code>  | ||||
|  *                                  is <code>null</code> | ||||
|  */ | ||||
|  | ||||
|   public Options(String args[], Prefix prefix, Multiplicity defaultMultiplicity) { | ||||
|     this(args, prefix, defaultMultiplicity, 0, 0); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Constructor. The prefix is set to {@link Prefix#DASH}. | ||||
|  * <p> | ||||
|  * @param args                The command line arguments to check | ||||
|  * @param defaultMultiplicity The default multiplicity to use for all options (can be overridden when adding an option) | ||||
|  * @param defMinData          The default minimum number of data items for all sets (can be overridden when adding a set) | ||||
|  * @param defMaxData          The default maximum number of data items for all sets (can be overridden when adding a set) | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If either <code>args</code> or <code>defaultMultiplicity</code>  | ||||
|  *                                  is <code>null</code> - or if the data range values don't make sense | ||||
|  */ | ||||
|  | ||||
|   public Options(String args[], Multiplicity defaultMultiplicity, int defMinData, int defMaxData) { | ||||
|     this(args, Prefix.DASH, defaultMultiplicity, defMinData, defMaxData); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Constructor. The prefix is set to {@link Prefix#DASH}. | ||||
|  * <p> | ||||
|  * @param args                The command line arguments to check | ||||
|  * @param defaultMultiplicity The default multiplicity to use for all options (can be overridden when adding an option) | ||||
|  * @param data                The default minimum and maximum number of data items for all sets (can be overridden when adding a set) | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If either <code>args</code> or <code>defaultMultiplicity</code>  | ||||
|  *                                  is <code>null</code> - or if the data range value doesn't make sense | ||||
|  */ | ||||
|  | ||||
|   public Options(String args[], Multiplicity defaultMultiplicity, int data) { | ||||
|     this(args, Prefix.DASH, defaultMultiplicity, data, data); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Constructor. The prefix is set to {@link Prefix#DASH}, and the default number of data items is set to 0. | ||||
|  * <p> | ||||
|  * @param args                The command line arguments to check | ||||
|  * @param defaultMultiplicity The default multiplicity to use for all options (can be overridden when adding an option) | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If either <code>args</code> or <code>defaultMultiplicity</code>  | ||||
|  *                                  is <code>null</code> | ||||
|  */ | ||||
|  | ||||
|   public Options(String args[], Multiplicity defaultMultiplicity) { | ||||
|     this(args, Prefix.DASH, defaultMultiplicity, 0, 0); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Constructor. The prefix is set to {@link Prefix#DASH}, the default number of data items is set to 0, and  | ||||
|  * the multiplicity is set to {@link Multiplicity#ONCE}.  | ||||
|  * <p> | ||||
|  * @param args The command line arguments to check | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If <code>args</code> is <code>null</code> | ||||
|  */ | ||||
|  | ||||
|   public Options(String args[]) { | ||||
|     this(args, Prefix.DASH, Multiplicity.ONCE); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Constructor. The prefix is set to {@link Prefix#DASH}, and  | ||||
|  * the multiplicity is set to {@link Multiplicity#ONCE}.  | ||||
|  * <p> | ||||
|  * @param args The command line arguments to check | ||||
|  * @param data The default minimum and maximum number of data items for all sets (can be overridden when adding a set) | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If <code>args</code> is <code>null</code> - or if the data range value doesn't make sense | ||||
|  */ | ||||
|  | ||||
|   public Options(String args[], int data) { | ||||
|     this(args, Prefix.DASH, Multiplicity.ONCE, data, data); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Constructor. The prefix is set to {@link Prefix#DASH}, and  | ||||
|  * the multiplicity is set to {@link Multiplicity#ONCE}.  | ||||
|  * <p> | ||||
|  * @param args       The command line arguments to check | ||||
|  * @param defMinData The default minimum number of data items for all sets (can be overridden when adding a set) | ||||
|  * @param defMaxData The default maximum number of data items for all sets (can be overridden when adding a set) | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If <code>args</code> is <code>null</code> - or if the data range values don't make sense | ||||
|  */ | ||||
|  | ||||
|   public Options(String args[], int defMinData, int defMaxData) { | ||||
|     this(args, Prefix.DASH, Multiplicity.ONCE, defMinData, defMaxData); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Constructor. The default number of data items is set to 0, and  | ||||
|  * the multiplicity is set to {@link Multiplicity#ONCE}.  | ||||
|  * <p> | ||||
|  * @param args   The command line arguments to check | ||||
|  * @param prefix The prefix to use for all command line options. It can only be set here for all options at  | ||||
|  *               the same time | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If either <code>args</code> or <code>prefix</code> is <code>null</code> | ||||
|  */ | ||||
|  | ||||
|   public Options(String args[], Prefix prefix) { | ||||
|     this(args, prefix, Multiplicity.ONCE, 0, 0); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Constructor. The multiplicity is set to {@link Multiplicity#ONCE}.  | ||||
|  * <p> | ||||
|  * @param args   The command line arguments to check | ||||
|  * @param prefix The prefix to use for all command line options. It can only be set here for all options at  | ||||
|  * @param data   The default minimum and maximum number of data items for all sets (can be overridden when adding a set) | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If either <code>args</code> or <code>prefix</code> is <code>null</code>  | ||||
|  *                                  - or if the data range value doesn't make sense | ||||
|  */ | ||||
|  | ||||
|   public Options(String args[], Prefix prefix, int data) { | ||||
|     this(args, prefix, Multiplicity.ONCE, data, data); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Constructor. The multiplicity is set to {@link Multiplicity#ONCE}.  | ||||
|  * <p> | ||||
|  * @param args       The command line arguments to check | ||||
|  * @param prefix     The prefix to use for all command line options. It can only be set here for all options at  | ||||
|  *                   the same time | ||||
|  * @param defMinData The default minimum number of data items for all sets (can be overridden when adding a set) | ||||
|  * @param defMaxData The default maximum number of data items for all sets (can be overridden when adding a set) | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If either <code>args</code> or <code>prefix</code> is <code>null</code>  | ||||
|  *                                  - or if the data range values don't make sense | ||||
|  */ | ||||
|  | ||||
|   public Options(String args[], Prefix prefix, int defMinData, int defMaxData) { | ||||
|     this(args, prefix, Multiplicity.ONCE, defMinData, defMaxData); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Return the (first) matching set. This invocation does not ignore unmatched options and requires that  | ||||
|  * data items are the last ones on the command line.  | ||||
|  * <p> | ||||
|  * @return The first set which matches (i. e. the <code>check()</code> method returns <code>true</code>) - or  | ||||
|  *         <code>null</code>, if no set matches. | ||||
|  */ | ||||
|  | ||||
|   public OptionSet getMatchingSet() { | ||||
|     return getMatchingSet(false, true); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Return the (first) matching set.  | ||||
|  * <p> | ||||
|  * @param ignoreUnmatched A boolean to select whether unmatched options can be ignored in the checks or not | ||||
|  * @param requireDataLast A boolean to indicate whether the data items have to be the last ones on the command line or not | ||||
|  * <p> | ||||
|  * @return The first set which matches (i. e. the <code>check()</code> method returns <code>true</code>) - or  | ||||
|  *         <code>null</code>, if no set matches. | ||||
|  */ | ||||
|  | ||||
|   public OptionSet getMatchingSet(boolean ignoreUnmatched, boolean requireDataLast) { | ||||
|     for (String setName : optionSets.keySet())  | ||||
|       if (check(setName, ignoreUnmatched, requireDataLast))  | ||||
|         return optionSets.get(setName); | ||||
|     return null; | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Add an option set. | ||||
|  * <p> | ||||
|  * @param setName The name for the set. This must be a unique identifier | ||||
|  * @param minData The minimum number of data items for this set | ||||
|  * @param maxData The maximum number of data items for this set | ||||
|  * <p> | ||||
|  * @return The new <code>Optionset</code> instance created. This is useful to allow chaining of <code>addOption()</code> | ||||
|  *         calls right after this method | ||||
|  */ | ||||
|  | ||||
|   public OptionSet addSet(String setName, int minData, int maxData) { | ||||
|     if (setName == null) throw new IllegalArgumentException(CLASS + ": setName may not be null"); | ||||
|     if (optionSets.containsKey(setName)) throw new IllegalArgumentException(CLASS + ": a set with the name "  | ||||
|         + setName + " has already been defined"); | ||||
|     OptionSet os = new OptionSet(prefix, defaultMultiplicity, setName, minData, maxData); | ||||
|     optionSets.put(setName, os); | ||||
|     return os; | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Add an option set. | ||||
|  * <p> | ||||
|  * @param setName The name for the set. This must be a unique identifier | ||||
|  * @param data    The minimum and maximum number of data items for this set | ||||
|  * <p> | ||||
|  * @return The new <code>Optionset</code> instance created. This is useful to allow chaining of <code>addOption()</code> | ||||
|  *         calls right after this method | ||||
|  */ | ||||
|  | ||||
|   public OptionSet addSet(String setName, int data) { | ||||
|     return addSet(setName, data, data); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Add an option set. The defaults for the number of data items are used.  | ||||
|  * <p> | ||||
|  * @param setName The name for the set. This must be a unique identifier | ||||
|  * <p> | ||||
|  * @return The new <code>Optionset</code> instance created. This is useful to allow chaining of <code>addOption()</code> | ||||
|  *         calls right after this method | ||||
|  */ | ||||
|  | ||||
|   public OptionSet addSet(String setName) { | ||||
|     return addSet(setName, defaultMinData, defaultMaxData); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Return an option set - or <code>null</code>, if no set with the given name exists | ||||
|  * <p> | ||||
|  * @param setName The name for the set to retrieve | ||||
|  * <p> | ||||
|  * @return The set to retrieve (or <code>null</code>, if no set with the given name exists) | ||||
|  */ | ||||
|  | ||||
|   public OptionSet getSet(String setName) { | ||||
|     return optionSets.get(setName); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * This returns the (anonymous) default set | ||||
|  * <p> | ||||
|  * @return The default set | ||||
|  */ | ||||
|  | ||||
|   public OptionSet getSet() { | ||||
|     if (getSet(DEFAULT_SET) == null)  | ||||
|       addSet(DEFAULT_SET, defaultMinData, defaultMaxData); | ||||
|     return getSet(DEFAULT_SET); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * The error messages collected during the last option check (invocation of any of the <code>check()</code> methods). This | ||||
|  * is useful to determine what was wrong with the command line arguments provided | ||||
|  * <p> | ||||
|  * @return A string with all collected error messages | ||||
|  */ | ||||
|  | ||||
|   public String getCheckErrors() { | ||||
|     return checkErrors.toString(); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Run the checks for the default set. <code>ignoreUnmatched</code> is set to <code>false</code>, and  | ||||
|  * <code>requireDataLast</code> is set to <code>true</code>. | ||||
|  * <p> | ||||
|  * @return A boolean indicating whether all checks were successful or not | ||||
|  */ | ||||
|  | ||||
|   public boolean check() { | ||||
|     return check(DEFAULT_SET, false, true); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Run the checks for the default set.  | ||||
|  * <p> | ||||
|  * @param ignoreUnmatched A boolean to select whether unmatched options can be ignored in the checks or not | ||||
|  * @param requireDataLast A boolean to indicate whether the data items have to be the last ones on the command line or not | ||||
|  * <p> | ||||
|  * @return A boolean indicating whether all checks were successful or not | ||||
|  */ | ||||
|  | ||||
|   public boolean check(boolean ignoreUnmatched, boolean requireDataLast) { | ||||
|     return check(DEFAULT_SET, ignoreUnmatched, requireDataLast); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Run the checks for the given set. <code>ignoreUnmatched</code> is set to <code>false</code>, and  | ||||
|  * <code>requireDataLast</code> is set to <code>true</code>. | ||||
|  * <p> | ||||
|  * @param setName The name for the set to check | ||||
|  * <p> | ||||
|  * @return A boolean indicating whether all checks were successful or not | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If either <code>setName</code> is <code>null</code>, or the set is unknown. | ||||
|  */ | ||||
|  | ||||
|   public boolean check(String setName) { | ||||
|     return check(setName, false, true); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Run the checks for the given set. | ||||
|  * <p> | ||||
|  * @param setName The name for the set to check | ||||
|  * @param ignoreUnmatched A boolean to select whether unmatched options can be ignored in the checks or not | ||||
|  * @param requireDataLast A boolean to indicate whether the data items have to be the last ones on the command line or not | ||||
|  * <p> | ||||
|  * @return A boolean indicating whether all checks were successful or not | ||||
|  * <p> | ||||
|  * @throws IllegalArgumentException If either <code>setName</code> is <code>null</code>, or the set is unknown. | ||||
|  */ | ||||
|  | ||||
|   public boolean check(String setName, boolean ignoreUnmatched, boolean requireDataLast) { | ||||
|  | ||||
|     if (setName == null) throw new IllegalArgumentException(CLASS + ": setName may not be null"); | ||||
|     if (optionSets.get(setName) == null) throw new IllegalArgumentException(CLASS + ": Unknown OptionSet: " + setName); | ||||
|  | ||||
|     checkErrors = new StringBuffer(); | ||||
|     checkErrors.append("Checking set "); | ||||
|     checkErrors.append(setName); | ||||
|     checkErrors.append('\n'); | ||||
|  | ||||
| //.... Access the data for the set to use | ||||
|  | ||||
|     OptionSet                       set         = optionSets.get(setName); | ||||
|     java.util.ArrayList<OptionData> options     = set.getOptionData(); | ||||
|     java.util.ArrayList<String>     data        = set.getData(); | ||||
|     java.util.ArrayList<String>     unmatched   = set.getUnmatched(); | ||||
|  | ||||
| //.... Catch some trivial cases | ||||
|  | ||||
|     if (options.size() == 0) {              // No options have been defined at all | ||||
|       if (arguments.length == 0) {          // No arguments have been given: in this case, this is a success | ||||
|         return true; | ||||
|       } else { | ||||
|         checkErrors.append("No options have been defined, nothing to check\n"); | ||||
|         return false; | ||||
|       } | ||||
|     } else if (arguments.length == 0) {     // Options have been defined, but no arguments given | ||||
|       checkErrors.append("Options have been defined, but no arguments have been given; nothing to check\n"); | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
| //.... Parse all the arguments given | ||||
|  | ||||
|     int                     ipos    = 0; | ||||
|     int                     offset  = 0; | ||||
|     java.util.regex.Matcher m       = null; | ||||
|     String                  value   = null; | ||||
|     String                  detail  = null; | ||||
|     String                  next    = null; | ||||
|     String                  key     = null; | ||||
|     String                  pre     = Character.toString(prefix.getName()); | ||||
|     boolean                 add     = true; | ||||
|     boolean[]               matched = new boolean[arguments.length]; | ||||
|  | ||||
|     for (int i = 0; i < matched.length; i++)                    // Initially, we assume there was no match at all | ||||
|       matched[i] = false; | ||||
|  | ||||
|     while (true) { | ||||
|  | ||||
|       value  = null; | ||||
|       detail = null; | ||||
|       offset = 0; | ||||
|       add    = true; | ||||
|       key    = arguments[ipos]; | ||||
|  | ||||
|       for (OptionData optionData : options) {                   // For each argument, we may need to check all defined options | ||||
|         m = optionData.getPattern().matcher(key); | ||||
|         if (m.lookingAt()) { | ||||
|           if (optionData.useValue()) {                          // The code section for value options | ||||
|             if (optionData.useDetail()) { | ||||
|               detail = m.group(1); | ||||
|               offset = 2;                                       // required for correct Matcher.group access below | ||||
|             } | ||||
|             if (optionData.getSeparator() == Separator.BLANK) { // In this case, the next argument must be the value | ||||
|               if (ipos + 1 == arguments.length) {               // The last argument, thus no value follows it: Error | ||||
|                 checkErrors.append("At end of arguments - no value found following argument "); | ||||
|                 checkErrors.append(key); | ||||
|                 checkErrors.append('\n'); | ||||
|                 add = false; | ||||
|               } else { | ||||
|                 next = arguments[ipos + 1]; | ||||
|                 if (next.startsWith(pre)) {                     // The next one is an argument, not a value: Error | ||||
|                   checkErrors.append("No value found following argument "); | ||||
|                   checkErrors.append(key); | ||||
|                   checkErrors.append('\n'); | ||||
|                   add = false; | ||||
|                 } else { | ||||
|                   value           = next; | ||||
|                   matched[ipos++] = true;                       // Mark the key and the value | ||||
|                   matched[ipos]   = true; | ||||
|                 } | ||||
|               } | ||||
|             } else {                                            // The value follows the separator in this case | ||||
|               value         = m.group(1 + offset); | ||||
|               matched[ipos] = true; | ||||
|             } | ||||
|           } else {                                              // Simple, non-value options | ||||
|             matched[ipos] = true; | ||||
|           } | ||||
|   | ||||
|           if (add) optionData.addResult(value, detail);         // Store the result | ||||
|           break;                                                // No need to check more options, we have a match | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       ipos++;                                                   // Advance to the next argument to check | ||||
|       if (ipos >= arguments.length) break;                      // Terminating condition for the check loop | ||||
|  | ||||
|     } | ||||
|  | ||||
| //.... Identify unmatched arguments and actual (non-option) data | ||||
|  | ||||
|     int first = -1;                                             // Required later for requireDataLast | ||||
|     for (int i = 0; i < matched.length; i++) {                  // Assemble the list of unmatched options | ||||
|       if (!matched[i]) { | ||||
|         if (arguments[i].startsWith(pre)) {                     // This is an unmatched option | ||||
|           unmatched.add(arguments[i]); | ||||
|           checkErrors.append("No matching option found for argument "); | ||||
|           checkErrors.append(arguments[i]); | ||||
|           checkErrors.append('\n'); | ||||
|         } else {                                                // This is actual data | ||||
|           if (first < 0) first = i; | ||||
|           data.add(arguments[i]); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
| //.... Checks to determine overall success; start with multiplicity of options | ||||
|  | ||||
|     boolean err = true; | ||||
|  | ||||
|     for (OptionData optionData : options) {     | ||||
|  | ||||
|       key = optionData.getKey(); | ||||
|       err = false;                                // Local check result for one option | ||||
|  | ||||
|       switch (optionData.getMultiplicity()) { | ||||
|         case ONCE:         if (optionData.getResultCount() != 1) err = true; break; | ||||
|         case ONCE_OR_MORE: if (optionData.getResultCount() == 0) err = true; break; | ||||
|         case ZERO_OR_ONE:  if (optionData.getResultCount() > 1)  err = true; break; | ||||
|         case ZERO_OR_MORE: break; | ||||
|       } | ||||
|  | ||||
|       if (err) { | ||||
|         checkErrors.append("Wrong number of occurences found for argument "); | ||||
|         checkErrors.append(prefix.getName()); | ||||
|         checkErrors.append(key); | ||||
|         checkErrors.append('\n'); | ||||
|         return false; | ||||
|       } | ||||
|  | ||||
|     } | ||||
|  | ||||
| //.... Check range for data | ||||
|  | ||||
|     if (data.size() < set.getMinData() || data.size() > set.getMaxData()) { | ||||
|       checkErrors.append("Invalid number of data arguments: "); | ||||
|       checkErrors.append(data.size()); | ||||
|       checkErrors.append(" (allowed range: "); | ||||
|       checkErrors.append(set.getMinData()); | ||||
|       checkErrors.append(" ... "); | ||||
|       checkErrors.append(set.getMaxData()); | ||||
|       checkErrors.append(")\n"); | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
| //.... Check for location of the data in the list of command line arguments | ||||
|  | ||||
|     if (requireDataLast) { | ||||
|       if (first + data.size() != arguments.length) { | ||||
|         checkErrors.append("Invalid data specification: data arguments are not the last ones on the command line\n"); | ||||
|         return false; | ||||
|       } | ||||
|     } | ||||
|      | ||||
| //.... Check for unmatched arguments | ||||
|  | ||||
|     if (!ignoreUnmatched && unmatched.size() > 0) return false;     // Don't accept unmatched arguments | ||||
|  | ||||
| //.... If we made it to here, all checks were successful | ||||
|  | ||||
|     return true; | ||||
|  | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Add the given non-value option to <i>all</i> known sets. | ||||
|  * See {@link OptionSet#addOption(String)} for details.  | ||||
|  */ | ||||
|  | ||||
|   public void addOptionAllSets(String key) { | ||||
|     for (String setName : optionSets.keySet()) | ||||
|       optionSets.get(setName).addOption(key, defaultMultiplicity); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Add the given non-value option to <i>all</i> known sets. | ||||
|  * See {@link OptionSet#addOption(String, Options.Multiplicity)} for details.  | ||||
|  */ | ||||
|  | ||||
|   public void addOptionAllSets(String key, Multiplicity multiplicity) { | ||||
|     for (String setName : optionSets.keySet()) | ||||
|       optionSets.get(setName).addOption(key, false, Separator.NONE, false, multiplicity); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Add the given value option to <i>all</i> known sets. | ||||
|  * See {@link OptionSet#addOption(String, Options.Separator)} for details.  | ||||
|  */ | ||||
|  | ||||
|   public void addOptionAllSets(String key, Separator separator) { | ||||
|     for (String setName : optionSets.keySet()) | ||||
|       optionSets.get(setName).addOption(key, false, separator, true, defaultMultiplicity); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Add the given value option to <i>all</i> known sets. | ||||
|  * See {@link OptionSet#addOption(String, Options.Separator, Options.Multiplicity)} for details.  | ||||
|  */ | ||||
|  | ||||
|   public void addOptionAllSets(String key, Separator separator, Multiplicity multiplicity) { | ||||
|     for (String setName : optionSets.keySet()) | ||||
|       optionSets.get(setName).addOption(key, false, separator, true, multiplicity); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Add the given value option to <i>all</i> known sets. | ||||
|  * See {@link OptionSet#addOption(String, boolean, Options.Separator)} for details.  | ||||
|  */ | ||||
|  | ||||
|   public void addOptionAllSets(String key, boolean details, Separator separator) { | ||||
|     for (String setName : optionSets.keySet()) | ||||
|       optionSets.get(setName).addOption(key, details, separator, true, defaultMultiplicity); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * Add the given value option to <i>all</i> known sets. | ||||
|  * See {@link OptionSet#addOption(String, boolean, Options.Separator, Options.Multiplicity)} for details.  | ||||
|  */ | ||||
|  | ||||
|   public void addOptionAllSets(String key, boolean details, Separator separator, Multiplicity multiplicity) { | ||||
|     for (String setName : optionSets.keySet()) | ||||
|       optionSets.get(setName).addOption(key, details, separator, true, multiplicity); | ||||
|   } | ||||
|  | ||||
| /** | ||||
|  * This is the overloaded {@link Object#toString()} method, and it is provided mainly for debugging | ||||
|  * purposes. | ||||
|  * <p> | ||||
|  * @return A string representing the instance | ||||
|  */ | ||||
|  | ||||
|   public String toString() { | ||||
|  | ||||
|     StringBuffer sb = new StringBuffer(); | ||||
|  | ||||
|     for (OptionSet set : optionSets.values()) { | ||||
|       sb.append("Set: "); | ||||
|       sb.append(set.getSetName()); | ||||
|       sb.append('\n'); | ||||
|       for (OptionData data : set.getOptionData()) { | ||||
|         sb.append(data.toString()); | ||||
|         sb.append('\n'); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     return sb.toString(); | ||||
|  | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -133,7 +133,7 @@ public class AboutDialog extends Dialog { | ||||
| 				// links are activated on mouse down when the control key is held down  | ||||
| //				if ((event.stateMask & SWT.MOD1) != 0) { | ||||
| 					try { | ||||
| 						int offset = ((StyledText)event.widget).getOffsetAtLocation(new Point (event.x, event.y)); | ||||
| 						int offset = ((StyledText)event.widget).getOffsetAtPoint(new Point (event.x, event.y)); | ||||
| 						StyleRange style = ((StyledText)event.widget).getStyleRangeAtOffset(offset); | ||||
| 						if (style != null && style.underline && style.underlineStyle == SWT.UNDERLINE_LINK) { | ||||
| 							Desktop.getDesktop().browse(new java.net.URI(style.data.toString())); | ||||
|   | ||||
| @@ -14,6 +14,7 @@ import java.beans.PropertyChangeEvent; | ||||
| import java.beans.PropertyChangeListener; | ||||
| import java.io.File; | ||||
| import java.io.FileInputStream; | ||||
| import java.io.FileNotFoundException; | ||||
| import java.io.FileOutputStream; | ||||
| import java.io.IOException; | ||||
| import java.util.ArrayList; | ||||
| @@ -31,6 +32,7 @@ import javax.inject.Named; | ||||
|  | ||||
| import org.eclipse.core.runtime.IProgressMonitor; | ||||
| import org.eclipse.core.runtime.IStatus; | ||||
| import org.eclipse.core.runtime.Platform; | ||||
| import org.eclipse.core.runtime.Status; | ||||
| import org.eclipse.core.runtime.SubMonitor; | ||||
| import org.eclipse.core.runtime.jobs.IJobChangeEvent; | ||||
| @@ -55,9 +57,16 @@ import org.eclipse.jface.viewers.ISelection; | ||||
| import org.eclipse.jface.viewers.ISelectionChangedListener; | ||||
| import org.eclipse.jface.viewers.IStructuredSelection; | ||||
| import org.eclipse.jface.viewers.SelectionChangedEvent; | ||||
| import org.eclipse.swt.SWT; | ||||
| import org.eclipse.swt.events.MouseEvent; | ||||
| import org.eclipse.swt.events.MouseTrackListener; | ||||
| import org.eclipse.swt.events.MouseWheelListener; | ||||
| import org.eclipse.swt.graphics.RGB; | ||||
| import org.eclipse.swt.graphics.Rectangle; | ||||
| import org.eclipse.swt.widgets.Composite; | ||||
| import org.eclipse.swt.widgets.Display; | ||||
| import org.eclipse.swt.widgets.Event; | ||||
| import org.eclipse.swt.widgets.Listener; | ||||
|  | ||||
| import com.minres.scviewer.database.ITx; | ||||
| import com.minres.scviewer.database.ITxRelation; | ||||
| @@ -71,6 +80,8 @@ import com.minres.scviewer.database.ui.GotoDirection; | ||||
| import com.minres.scviewer.database.ui.ICursor; | ||||
| import com.minres.scviewer.database.ui.IWaveformViewer; | ||||
| import com.minres.scviewer.database.ui.TrackEntry; | ||||
| import com.minres.scviewer.database.ui.TrackEntry.ValueDisplay; | ||||
| import com.minres.scviewer.database.ui.TrackEntry.WaveDisplay; | ||||
| import com.minres.scviewer.database.ui.WaveformColors; | ||||
| import com.minres.scviewer.e4.application.Messages; | ||||
| import com.minres.scviewer.e4.application.internal.status.WaveStatusBarControl; | ||||
| @@ -98,6 +109,10 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis | ||||
| 	/** The Constant SHOWN_WAVEFORM. */ | ||||
| 	protected static final String SHOWN_WAVEFORM = "SHOWN_WAVEFORM"; //$NON-NLS-1$ | ||||
| 	 | ||||
| 	protected static final String VALUE_DISPLAY = ".VALUE_DISPLAY"; //$NON-NLS-1$ | ||||
| 	 | ||||
| 	protected static final String WAVE_DISPLAY = ".WAVE_DISPLAY"; //$NON-NLS-1$ | ||||
| 	 | ||||
| 	/** The Constant SHOWN_CURSOR. */ | ||||
| 	protected static final String SHOWN_CURSOR = "SHOWN_CURSOR"; //$NON-NLS-1$ | ||||
| 	 | ||||
| @@ -137,7 +152,7 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis | ||||
| 	@Inject | ||||
| 	ESelectionService selectionService; | ||||
|  | ||||
| 	/** The e part service. */ | ||||
| 	/** The part service. */ | ||||
| 	@Inject | ||||
| 	EPartService ePartService; | ||||
|  | ||||
| @@ -232,6 +247,106 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis | ||||
| 					selectionService.setSelection(event.getSelection()); | ||||
| 			} | ||||
| 		}); | ||||
| 		waveformPane.getWaveformControl().addMouseTrackListener(new MouseTrackListener() { | ||||
| 			 | ||||
| 			@Override | ||||
| 			public void mouseHover(MouseEvent e) { | ||||
| 				// TODO Auto-generated method stub | ||||
| 				 | ||||
| 			} | ||||
| 			 | ||||
| 			@Override | ||||
| 			public void mouseExit(MouseEvent e) { | ||||
| 				// TODO Auto-generated method stub | ||||
| 				 | ||||
| 			} | ||||
| 			 | ||||
| 			@Override | ||||
| 			public void mouseEnter(MouseEvent e) { | ||||
| 				// TODO Auto-generated method stub | ||||
| 				 | ||||
| 			} | ||||
| 		}); | ||||
| 		 | ||||
| 		waveformPane.getWaveformControl().addMouseWheelListener(new MouseWheelListener() { | ||||
| 			 | ||||
| 			@Override | ||||
| 			public void mouseScrolled(MouseEvent e) { | ||||
| 				// TODO Auto-generated method stub | ||||
| 				 | ||||
| 			} | ||||
| 		}); | ||||
| 		 | ||||
| 		waveformPane.getWaveformControl().addListener(SWT.KeyDown, new Listener() { | ||||
| 			 | ||||
| 			@Override | ||||
| 			public void handleEvent(Event e) { | ||||
| 				int state = e.stateMask & SWT.MODIFIER_MASK; | ||||
| 				if(Platform.OS_MACOSX.equals(Platform.getOS())) { //swap cammnd and control for MacOSX | ||||
| 					if((state&SWT.COMMAND)!=0) { | ||||
| 						state&=~SWT.COMMAND; | ||||
| 						state|=SWT.CONTROL; | ||||
| 					} else if((state&SWT.CONTROL)!=0) { | ||||
| 						state&=~SWT.CONTROL; | ||||
| 						state|=SWT.COMMAND; | ||||
| 					} | ||||
| 				} | ||||
| 				if(state==SWT.ALT) { | ||||
| 					switch(e.keyCode) { | ||||
| 					case SWT.ARROW_LEFT: | ||||
| 						waveformPane.scrollHorizontal(-100); | ||||
| 						return; | ||||
| 					case SWT.ARROW_RIGHT: | ||||
| 						waveformPane.scrollHorizontal(100); | ||||
| 						return; | ||||
| 					case SWT.KEYPAD_ADD: | ||||
| 						return; | ||||
| 					case SWT.KEYPAD_SUBTRACT: | ||||
| 						return; | ||||
| 					} | ||||
| 				} else if(state==SWT.CTRL) { | ||||
| 					int zoomlevel = waveformPane.getZoomLevel(); | ||||
| 					switch(e.keyCode) { | ||||
| 					case '+': | ||||
| 					case SWT.KEYPAD_ADD: | ||||
| 						if(zoomlevel>0) | ||||
| 							waveformPane.setZoomLevel(zoomlevel-1); | ||||
| 						return; | ||||
| 					case '-': | ||||
| 					case SWT.KEYPAD_SUBTRACT: | ||||
| 						if(zoomlevel<waveformPane.getZoomLevels().length-1) | ||||
| 							waveformPane.setZoomLevel(zoomlevel+1); | ||||
| 						return; | ||||
| 					case SWT.ARROW_UP: | ||||
| 						waveformPane.moveSelectedTrack(-1); | ||||
| 						return; | ||||
| 					case SWT.ARROW_DOWN: | ||||
| 						waveformPane.moveSelectedTrack(1); | ||||
| 						return; | ||||
| 					} | ||||
| 				} else if(state==SWT.SHIFT) { | ||||
| 				} else { | ||||
| 					switch(e.keyCode) { | ||||
| 					case SWT.ARROW_LEFT: | ||||
| 						waveformPane.scrollHorizontal(-10); | ||||
| 						return; | ||||
| 					case SWT.ARROW_RIGHT: | ||||
| 						waveformPane.scrollHorizontal(10); | ||||
| 						return; | ||||
| 					case SWT.ARROW_UP: | ||||
| 						waveformPane.moveSelection(GotoDirection.UP); | ||||
| 						return; | ||||
| 					case SWT.ARROW_DOWN: | ||||
| 						waveformPane.moveSelection(GotoDirection.DOWN); | ||||
| 						return; | ||||
| 					case SWT.HOME:			return; //TODO: should be handled | ||||
| 					case SWT.END:			return; //TODO: should be handled | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
| 			} | ||||
| 		}); | ||||
| 		 | ||||
| 		zoomLevel = waveformPane.getZoomLevels(); | ||||
| 		setupColors(); | ||||
| 		checkForUpdates = prefs.getBoolean(PreferenceConstants.DATABASE_RELOAD, true); | ||||
| @@ -245,10 +360,12 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis | ||||
| 		if (filesToLoad.size() > 0) | ||||
| 			loadDatabase(persistedState); | ||||
| 		eventBroker.post(WaveStatusBarControl.ZOOM_LEVEL, zoomLevel[waveformPane.getZoomLevel()]); | ||||
| //		menuService.registerContextMenu(waveformPane.getNameControl(), | ||||
| //				"com.minres.scviewer.e4.application.popupmenu.namecontext"); //$NON-NLS-1$ | ||||
| 		menuService.registerContextMenu(waveformPane.getNameControl(), | ||||
| 				"com.minres.scviewer.e4.application.popupmenu.namecontext"); //$NON-NLS-1$ | ||||
| 				"com.minres.scviewer.e4.application.popupmenu.wavecontext"); //$NON-NLS-1$ | ||||
| 		menuService.registerContextMenu(waveformPane.getValueControl(), | ||||
| 				"com.minres.scviewer.e4.application.popupmenu.namecontext"); //$NON-NLS-1$ | ||||
| 				"com.minres.scviewer.e4.application.popupmenu.wavecontext"); //$NON-NLS-1$ | ||||
| 		menuService.registerContextMenu(waveformPane.getWaveformControl(), | ||||
| 				"com.minres.scviewer.e4.application.popupmenu.wavecontext"); //$NON-NLS-1$ | ||||
| 		ePartService.addPartListener(new PartListener() { | ||||
| @@ -380,7 +497,7 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis | ||||
| 	 */ | ||||
| 	@Inject | ||||
| 	@Optional | ||||
| 	public void setPartInput(@Named("input") Object partInput) { | ||||
| 	public void setPartInput(@Named("input") Object partInput, @Named("config") Object partConfig) { | ||||
| 		if (partInput instanceof File) { | ||||
| 			filesToLoad = new ArrayList<File>(); | ||||
| 			File file = (File) partInput; | ||||
| @@ -404,6 +521,9 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis | ||||
| 			} | ||||
| 			if (filesToLoad.size() > 0) | ||||
| 				loadDatabase(persistedState); | ||||
| 			if(partConfig instanceof String) { | ||||
| 				loadState((String) partConfig); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -412,7 +532,7 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis | ||||
| 	 */ | ||||
| 	@Focus | ||||
| 	public void setFocus() { | ||||
| 		myParent.setFocus(); | ||||
| 		waveformPane.getWaveformControl().setFocus(); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| @@ -459,12 +579,13 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis | ||||
| 			FileInputStream in = new FileInputStream(fileName); | ||||
| 			props.load(in); | ||||
| 			in.close(); | ||||
| 			@SuppressWarnings({ "unchecked", "rawtypes" }) | ||||
| 			HashMap<String, String> propMap = new HashMap<String, String>((Map) props); | ||||
| 			restoreWaveformViewerState(propMap); | ||||
| 		} catch(FileNotFoundException e) { | ||||
| 		} catch (IOException e) { | ||||
| 			e.printStackTrace(); | ||||
| 		} | ||||
| 		@SuppressWarnings({ "unchecked", "rawtypes" }) | ||||
| 		HashMap<String, String> propMap = new HashMap<String, String>((Map) props); | ||||
| 		restoreWaveformViewerState(propMap); | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| @@ -478,6 +599,8 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis | ||||
| 		index = 0; | ||||
| 		for (TrackEntry trackEntry : waveformPane.getStreamList()) { | ||||
| 			persistedState.put(SHOWN_WAVEFORM + index, trackEntry.waveform.getFullName()); | ||||
| 			persistedState.put(SHOWN_WAVEFORM + index + VALUE_DISPLAY, trackEntry.valueDisplay.toString()); | ||||
| 			persistedState.put(SHOWN_WAVEFORM + index + WAVE_DISPLAY, trackEntry.waveDisplay.toString()); | ||||
| 			index++; | ||||
| 		} | ||||
| 		List<ICursor> cursors = waveformPane.getCursorList(); | ||||
| @@ -501,8 +624,16 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis | ||||
| 		List<TrackEntry> res = new LinkedList<>(); | ||||
| 		for (int i = 0; i < waves; i++) { | ||||
| 			IWaveform<? extends IWaveformEvent> waveform = database.getStreamByName(state.get(SHOWN_WAVEFORM + i)); | ||||
| 			if (waveform != null) | ||||
| 				res.add(new TrackEntry(waveform)); | ||||
| 			if (waveform != null) { | ||||
| 				TrackEntry t = new TrackEntry(waveform); | ||||
| 				res.add(t); | ||||
| 				String v = state.get(SHOWN_WAVEFORM + i + VALUE_DISPLAY); | ||||
| 				if(v!=null) | ||||
| 					t.valueDisplay=ValueDisplay.valueOf(v); | ||||
| 				String s = state.get(SHOWN_WAVEFORM + i + WAVE_DISPLAY); | ||||
| 				if(s!=null) | ||||
| 					t.waveDisplay=WaveDisplay.valueOf(s); | ||||
| 			} | ||||
| 		} | ||||
| 		if (res.size() > 0) | ||||
| 			waveformPane.getStreamList().addAll(res); | ||||
| @@ -658,6 +789,7 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis | ||||
| 				index++; | ||||
| 			waveformPane.getStreamList().addAll(index, streams); | ||||
| 		} | ||||
| 		setFocus(); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| @@ -724,6 +856,7 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis | ||||
| 	 * @param level the new zoom level | ||||
| 	 */ | ||||
| 	public void setZoomLevel(Integer level) { | ||||
| 		//System.out.println("setZoomLevel() - ZoomLevel: " + level); | ||||
| 		if (level < 0) | ||||
| 			level = 0; | ||||
| 		if (level > zoomLevel.length - 1) | ||||
| @@ -732,11 +865,43 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis | ||||
| 		updateAll(); | ||||
| 	} | ||||
|  | ||||
|     //FIXME: need to use unitString and unitMultiplier from class WaveformCanvas which is located in >com.minres.scviewer.database.swt.internal. | ||||
| 	//Trying to import com.minres.scviewer.database.swt.internal.WaveformCanvas results in the error: | ||||
| 	//'Access restriction: The type 'WaveformCanvas' is not API (restriction on required project 'com.minres.scviewer.database.ui.swt')'. | ||||
| 	public final static String[] unitString={"fs", "ps", "ns", "<EFBFBD>s", "ms"};//, "s"}; | ||||
|     public final static int[] unitMultiplier={1, 3, 10, 30, 100, 300}; | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Sets the zoom fit. | ||||
| 	 */ | ||||
| 	public void setZoomFit() { | ||||
| 		waveformPane.setZoomLevel(6); | ||||
|  | ||||
| 		//actual max time of signal | ||||
| 		long maxTime = waveformPane.getMaxTime(); | ||||
| 		 | ||||
| 		//get area actually capable of displaying data, i.e. area of the receiver which is capable of displaying data | ||||
| 		Rectangle clientArea = myParent.getClientArea(); | ||||
| 		long clientAreaWidth = clientArea.width; | ||||
| 		 | ||||
| 		//System.out.println("ZoomLevel[] Array (Length " + zoomLevel.length + "): " + Arrays.toString(zoomLevel)); | ||||
| 		//System.out.println("ClientArea myParent: " + myParent.getClientArea()); | ||||
| 		//System.out.println("MaxTime: " + maxTime); | ||||
| 		//System.out.println("clientAreaWidth: " + clientAreaWidth); | ||||
| 		 | ||||
|     	boolean foundZoom=false; | ||||
| 		//try to find existing zoomlevel where scaleFactor*clientAreaWidth >= maxTime, if one is found set it as new zoomlevel | ||||
| 		for (int level=0; level<unitMultiplier.length*unitString.length; level++){ | ||||
| 			long scaleFactor = (long) Math.pow(10, level/2); | ||||
| 		    if(level%2==1) scaleFactor*=3; | ||||
| 		    if(scaleFactor*clientAreaWidth >= maxTime) { | ||||
| 		    	setZoomLevel(level); | ||||
| 		    	foundZoom=true; | ||||
| 		    	break; | ||||
| 		    } | ||||
| 		} | ||||
| 		//if no zoom level is found, set biggest one available | ||||
| 		if(!foundZoom) setZoomLevel(unitMultiplier.length*unitString.length-1); | ||||
| 				 | ||||
| 		updateAll(); | ||||
| 	} | ||||
|  | ||||
| @@ -878,5 +1043,9 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis | ||||
| 		if(navigationRelationType!=relationType) waveformPane.setHighliteRelation(relationType); | ||||
| 		navigationRelationType=relationType; | ||||
| 	} | ||||
| 	 | ||||
| 	public void update() { | ||||
| 		waveformPane.update(); | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -41,12 +41,15 @@ public class DefaultValuesInitializer extends AbstractPreferenceInitializer { | ||||
|         colors[WaveformColors.TX_BG.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GREEN); | ||||
|         colors[WaveformColors.TX_BG_HIGHLITE.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN); | ||||
|         colors[WaveformColors.TX_BORDER.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED); | ||||
|         colors[WaveformColors.SIGNAL0.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN); | ||||
|         colors[WaveformColors.SIGNAL1.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN); | ||||
|         colors[WaveformColors.SIGNAL0.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GREEN); | ||||
|         colors[WaveformColors.SIGNAL1.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GREEN); | ||||
|         colors[WaveformColors.SIGNALZ.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_YELLOW); | ||||
|         colors[WaveformColors.SIGNALX.ordinal()] = SWTResourceManager.getColor(255,  51,  51); | ||||
|         colors[WaveformColors.SIGNALU.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_YELLOW); | ||||
|         colors[WaveformColors.SIGNAL_REAL.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_YELLOW); | ||||
|         colors[WaveformColors.SIGNAL_NAN.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED); | ||||
|         colors[WaveformColors.SIGNAL_TEXT.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_WHITE); | ||||
|         colors[WaveformColors.SIGNAL_REAL.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_YELLOW); | ||||
|         colors[WaveformColors.CURSOR.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED); | ||||
|         colors[WaveformColors.CURSOR_DRAG.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GRAY); | ||||
|         colors[WaveformColors.CURSOR_TEXT.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_WHITE); | ||||
|   | ||||
| @@ -20,7 +20,7 @@ import org.eclipse.wb.swt.ResourceManager; | ||||
|  | ||||
| import com.minres.scviewer.database.IHierNode; | ||||
| import com.minres.scviewer.database.ISignal; | ||||
| import com.minres.scviewer.database.ISignalChangeMulti; | ||||
| import com.minres.scviewer.database.ISignalChangeBitVector; | ||||
| import com.minres.scviewer.database.ITxStream; | ||||
| import com.minres.scviewer.database.IWaveformDb; | ||||
| import com.minres.scviewer.e4.application.parts.LoadingWaveformDb; | ||||
| @@ -101,7 +101,7 @@ public class TxDbLabelProvider implements ILabelProvider { | ||||
| 			return stream; | ||||
| 		}else if(element instanceof ISignal<?>){ | ||||
| 			Object o = ((ISignal<?>)element).getEvents().firstEntry().getValue(); | ||||
| 			if(o instanceof ISignalChangeMulti) | ||||
| 			if(o instanceof ISignalChangeBitVector) | ||||
| 				return wave; | ||||
| 			else  | ||||
| 				return signal; | ||||
|   | ||||
| @@ -147,15 +147,15 @@ public class ResourceManager extends SWTResourceManager { | ||||
| 			CompositeImageDescriptor compositImageDesc = new CompositeImageDescriptor() { | ||||
| 				@Override | ||||
| 				protected void drawCompositeImage(int width, int height) { | ||||
| 					drawImage(baseImage.getImageData(), 0, 0); | ||||
| 					drawImage(createCachedImageDataProvider(baseImage), 0, 0); | ||||
| 					if (corner == TOP_LEFT) { | ||||
| 						drawImage(decorator.getImageData(), 0, 0); | ||||
| 						drawImage(createCachedImageDataProvider(decorator), 0, 0); | ||||
| 					} else if (corner == TOP_RIGHT) { | ||||
| 						drawImage(decorator.getImageData(), bib.width - dib.width, 0); | ||||
| 						drawImage(createCachedImageDataProvider(decorator), bib.width - dib.width, 0); | ||||
| 					} else if (corner == BOTTOM_LEFT) { | ||||
| 						drawImage(decorator.getImageData(), 0, bib.height - dib.height); | ||||
| 						drawImage(createCachedImageDataProvider(decorator), 0, bib.height - dib.height); | ||||
| 					} else if (corner == BOTTOM_RIGHT) { | ||||
| 						drawImage(decorator.getImageData(), bib.width - dib.width, bib.height - dib.height); | ||||
| 						drawImage(createCachedImageDataProvider(decorator), bib.width - dib.width, bib.height - dib.height); | ||||
| 					} | ||||
| 				} | ||||
| 				@Override | ||||
|   | ||||
| @@ -6,11 +6,10 @@ | ||||
| 	<parent> | ||||
| 		<groupId>com.minres.scviewer</groupId> | ||||
| 		<artifactId>com.minres.scviewer.parent</artifactId> | ||||
| 		<version>1.0.0-SNAPSHOT</version> | ||||
| 		<version>2.0.0-SNAPSHOT</version> | ||||
| 		<relativePath>../com.minres.scviewer.parent</relativePath> | ||||
| 	</parent> | ||||
| 	<artifactId>com.minres.scviewer.e4.product</artifactId> | ||||
| 	<version>1.3.0-SNAPSHOT</version> | ||||
| 	<packaging>eclipse-repository</packaging> | ||||
| 	<groupId>com.minres.scviewer</groupId> | ||||
| 	<build> | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <?pde version="3.5"?> | ||||
|  | ||||
| <product name="SCViewer" uid="scviewer" id="com.minres.scviewer.e4.application.product" application="org.eclipse.e4.ui.workbench.swt.E4Application" version="1.3.0.qualifier" useFeatures="false" includeLaunchers="true"> | ||||
| <product name="SCViewer" uid="scviewer" id="com.minres.scviewer.e4.application.product" application="org.eclipse.e4.ui.workbench.swt.E4Application" version="2.0.0.qualifier" useFeatures="false" includeLaunchers="true"> | ||||
|  | ||||
|    <configIni use="default"> | ||||
|    </configIni> | ||||
| @@ -72,8 +72,10 @@ | ||||
|       <plugin id="org.eclipse.core.expressions"/> | ||||
|       <plugin id="org.eclipse.core.filesystem"/> | ||||
|       <plugin id="org.eclipse.core.filesystem.macosx" fragment="true"/> | ||||
|       <plugin id="org.eclipse.core.filesystem.win32.x86_64" fragment="true"/> | ||||
|       <plugin id="org.eclipse.core.jobs"/> | ||||
|       <plugin id="org.eclipse.core.resources"/> | ||||
|       <plugin id="org.eclipse.core.resources.win32.x86_64" fragment="true"/> | ||||
|       <plugin id="org.eclipse.core.runtime"/> | ||||
|       <plugin id="org.eclipse.e4.core.commands"/> | ||||
|       <plugin id="org.eclipse.e4.core.contexts"/> | ||||
| @@ -118,6 +120,7 @@ | ||||
|       <plugin id="org.eclipse.pde.ds.lib"/> | ||||
|       <plugin id="org.eclipse.swt"/> | ||||
|       <plugin id="org.eclipse.swt.cocoa.macosx.x86_64" fragment="true"/> | ||||
|       <plugin id="org.eclipse.swt.win32.win32.x86_64" fragment="true"/> | ||||
|       <plugin id="org.w3c.css.sac"/> | ||||
|       <plugin id="org.w3c.dom.events"/> | ||||
|       <plugin id="org.w3c.dom.smil"/> | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
| 	<modelVersion>4.0.0</modelVersion> | ||||
| 	<groupId>com.minres.scviewer</groupId> | ||||
| 	<artifactId>com.minres.scviewer.parent</artifactId> | ||||
| 	<version>1.0.0-SNAPSHOT</version> | ||||
| 	<version>2.0.0-SNAPSHOT</version> | ||||
| 	<packaging>pom</packaging> | ||||
| 	<modules> | ||||
| 		<module>../com.minres.scviewer.target</module> | ||||
|   | ||||
							
								
								
									
										22
									
								
								com.minres.scviewer.target/neon.target
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								com.minres.scviewer.target/neon.target
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?><?pde version="3.8"?><target name="Neon Platform" sequenceNumber="138"> | ||||
| <locations> | ||||
| <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="true" type="InstallableUnit"> | ||||
| <unit id="org.eclipse.equinox.executable.feature.group" version="3.6.300.v20161122-1740"/> | ||||
| <unit id="org.eclipse.platform.sdk" version="4.6.2.M20161124-1400"/> | ||||
| <unit id="org.eclipse.rcp.sdk.id" version="4.6.2.M20161124-1400"/> | ||||
| <unit id="org.eclipse.rcptt.core.feature.group" version="2.1.0.201604261352"/> | ||||
| <repository location="http://download.eclipse.org/releases/neon"/> | ||||
| </location> | ||||
| <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="true" type="InstallableUnit"> | ||||
| <unit id="org.codehaus.groovy24.feature.feature.group" version="2.9.3.xx-201806261157-e46"/> | ||||
| <repository location="http://dist.springsource.org/snapshot/GRECLIPSE/e4.6"/> | ||||
| </location> | ||||
| </locations> | ||||
| <environment> | ||||
| <arch>x86_64</arch> | ||||
| <nl>de_DE</nl> | ||||
| </environment> | ||||
| <launcherArgs> | ||||
| <vmArgs>-Dosgi.requiredJavaVersion=1.7 -XX:MaxPermSize=256 -Xms40m -Xmx2G </vmArgs> | ||||
| </launcherArgs> | ||||
| </target> | ||||
| @@ -6,6 +6,8 @@ | ||||
| <unit id="org.eclipse.sdk.feature.group" version="0.0.0"/> | ||||
| <unit id="org.eclipse.rcp.sdk.id" version="0.0.0"/> | ||||
| <unit id="org.eclipse.rcptt.core.feature.group" version="0.0.0"/> | ||||
| <unit id="org.eclipse.e4.rcp.feature.group" version="0.0.0"/> | ||||
| <unit id="org.eclipse.platform.feature.group" version="0.0.0"/> | ||||
| <repository location="http://download.eclipse.org/releases/photon"/> | ||||
| </location> | ||||
| <location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="true" type="InstallableUnit"> | ||||
|   | ||||
| @@ -1,2 +1,3 @@ | ||||
| eclipse.preferences.version=1 | ||||
| groovy.compiler.level=26 | ||||
| groovy.script.filters=**/*.dsld,y,**/*.gradle,n | ||||
|   | ||||
| @@ -23,3 +23,4 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8 | ||||
| Bundle-ActivationPolicy: lazy | ||||
| Import-Package: com.google.common.collect | ||||
| Service-Component: OSGI-INF/component.xml | ||||
| Automatic-Module-Name: com.minres.scviewer.ui | ||||
|   | ||||
| @@ -347,12 +347,18 @@ public class TxEditorPart extends EditorPart implements ITabbedPropertySheetPage | ||||
| 			addStreamToList(stream); | ||||
| 	} | ||||
|  | ||||
| 	public void removeStreamFromList(IWaveform<? extends IWaveformEvent> obj){ | ||||
| 		if(getEditorInput() instanceof TxEditorInput && ((TxEditorInput) getEditorInput()).getStreamNames().contains(obj.getFullName())){ | ||||
| 			((TxEditorInput) getEditorInput()).getStreamNames().remove(obj.getFullName()); | ||||
| 			txDisplay.getStreamList().remove(obj); | ||||
| 		} else | ||||
| 			txDisplay.getStreamList().remove(obj); | ||||
| 	public void removeStreamFromList(IWaveform<? extends IWaveformEvent> waveform){ | ||||
| 		if(getEditorInput() instanceof TxEditorInput && ((TxEditorInput) getEditorInput()).getStreamNames().contains(waveform.getFullName())){ | ||||
| 			((TxEditorInput) getEditorInput()).getStreamNames().remove(waveform.getFullName()); | ||||
| 		} | ||||
| 		TrackEntry entry=null; | ||||
| 		for(TrackEntry e:txDisplay.getStreamList()) { | ||||
| 			if(e.waveform==waveform) { | ||||
| 				entry=e; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		txDisplay.getStreamList().remove(entry); | ||||
| 	} | ||||
|  | ||||
| 	public void removeStreamsFromList(IWaveform<? extends IWaveformEvent>[] iWaveforms){ | ||||
|   | ||||
| @@ -16,3 +16,4 @@ Require-Bundle: javax.inject, | ||||
| Export-Package: com.opcoach.e4.preferences, | ||||
|  com.opcoach.e4.preferences.handlers | ||||
| Bundle-ActivationPolicy: lazy | ||||
| Automatic-Module-Name: com.opcoach.e4.preferences | ||||
|   | ||||
		Reference in New Issue
	
	Block a user