mirror of https://github.com/lawrancej/logisim.git
Merge remote-tracking branch 'allevaton/master'
This commit is contained in:
commit
c495b63e85
124
build.gradle
124
build.gradle
|
@ -9,71 +9,95 @@ version = '2.7.2'
|
|||
description = 'Logisim: Logic Simulator'
|
||||
|
||||
launch4j {
|
||||
mainClassName = project.mainClassName // launch4j should know this from the application plugin, right?
|
||||
jar = "lib/"+project.name+"-"+project.version+".jar"
|
||||
// launch4j should know this from the application plugin, right?
|
||||
mainClassName = project.mainClassName
|
||||
jar = "lib/"+project.name+"-"+project.version+".jar"
|
||||
}
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
ivy {
|
||||
artifactPattern 'http://gradle-launch4j.googlecode.com/files/[module]-[revision].[ext]'
|
||||
}
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'edu.sc.seis:gradle-launch4j:1.0.5', 'net.sourceforge.nekohtml:nekohtml:1.9.18', 'javax.help:javahelp:2.0.05'
|
||||
}
|
||||
repositories {
|
||||
ivy {
|
||||
artifactPattern 'http://gradle-launch4j.googlecode.com/files/[module]-[revision].[ext]'
|
||||
}
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath \
|
||||
'edu.sc.seis:gradle-launch4j:1.0.5',
|
||||
'net.sourceforge.nekohtml:nekohtml:1.9.18',
|
||||
'javax.help:javahelp:2.0.05'
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url 'http://nexus.gephi.org/nexus/content/repositories/public'
|
||||
}
|
||||
mavenCentral()
|
||||
maven {
|
||||
url 'http://nexus.gephi.org/nexus/content/repositories/public'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile 'javax.help:javahelp:2.0.05', 'com.connectina.swing:fontchooser:1.0', 'org.apache.commons:commons-lang3:3.1', 'net.sourceforge.collections:collections-generic:4.01', 'org.apache.xmlgraphics:batik-svggen:1.7', 'org.apache.xmlgraphics:batik-swing:1.7', 'org.apache.xmlgraphics:batik-transcoder:1.7', fileTree(dir: 'libs', include: '*.jar')
|
||||
testCompile 'junit:junit:4.11'
|
||||
compile \
|
||||
'javax.help:javahelp:2.0.05',
|
||||
'com.connectina.swing:fontchooser:1.0',
|
||||
'org.apache.commons:commons-lang3:3.1',
|
||||
'net.sourceforge.collections:collections-generic:4.01',
|
||||
'org.apache.xmlgraphics:batik-svggen:1.7',
|
||||
'org.apache.xmlgraphics:batik-swing:1.7',
|
||||
'org.apache.xmlgraphics:batik-transcoder:1.7',
|
||||
|
||||
// Native JDK logger (java.util.logging)
|
||||
//'org.slf4j:slf4j-jdk14:1.7.5',
|
||||
|
||||
// Simplified logger (less lines)
|
||||
'org.slf4j:slf4j-simple:1.6.1',
|
||||
|
||||
// Logging does nothing (use for release builds)
|
||||
//'org.slf4j:slf4j-nop:1.7.5',
|
||||
|
||||
// Local dependencies convention: ./libs/*.jar
|
||||
fileTree(dir: 'libs', include: '*.jar')
|
||||
|
||||
testCompile 'junit:junit:4.11'
|
||||
}
|
||||
|
||||
processResources << {
|
||||
println "Processing Java Help..."
|
||||
def parser = new org.cyberneko.html.parsers.SAXParser()
|
||||
def doc_src = 'src/main/resources/doc'
|
||||
def doc_target = 'build/resources/main/doc'
|
||||
println "Processing Java Help..."
|
||||
def parser = new org.cyberneko.html.parsers.SAXParser()
|
||||
def doc_src = 'src/main/resources/doc'
|
||||
def doc_target = 'build/resources/main/doc'
|
||||
|
||||
file(doc_src).listFiles().each { locale ->
|
||||
if (locale.name.length() == 2) { // Locale names are two characters long
|
||||
// Build contents.xml with the id=>text mapping from locale/html/contents.html
|
||||
def dict = [:]
|
||||
def doc = new XmlParser(parser).parse("${doc_src}/${locale.name}/html/contents.html")
|
||||
doc.'**'.A.each { dict[it.@id] = it.text() }
|
||||
file(doc_src).listFiles().each { locale ->
|
||||
if (locale.name.length() == 2) { // Locale names are two characters long
|
||||
// Build contents.xml with the id=>text mapping from locale/html/contents.html
|
||||
def dict = [:]
|
||||
def doc = new XmlParser(parser).parse("${doc_src}/${locale.name}/html/contents.html")
|
||||
doc.'**'.A.each { dict[it.@id] = it.text() }
|
||||
|
||||
// Rewrite support/base-contents.xml as locale/contents.xml.
|
||||
def contents = new XmlParser().parse("${doc_src}/support/base-contents.xml")
|
||||
contents.'**'.'tocitem'.each {
|
||||
it.@text = (dict.containsKey(it.@target)) ? dict[it.@target] : it.@target
|
||||
}
|
||||
new XmlNodePrinter(new File("${doc_target}/${locale.name}/contents.xml").newPrintWriter("UTF-8")).print(contents)
|
||||
// Rewrite support/base-contents.xml as locale/contents.xml.
|
||||
def contents = new XmlParser().parse("${doc_src}/support/base-contents.xml")
|
||||
contents.'**'.'tocitem'.each {
|
||||
it.@text = (dict.containsKey(it.@target)) ? dict[it.@target] : it.@target
|
||||
}
|
||||
new XmlNodePrinter(new File("${doc_target}/${locale.name}/contents.xml").newPrintWriter("UTF-8")).print(contents)
|
||||
|
||||
// Build JavaHelp map
|
||||
def map = new XmlParser().parse("${doc_src}/support/base-map.jhm")
|
||||
map.'**'.'mapID'.each { it.@url = "${locale.name}/${it.@url}" }
|
||||
new XmlNodePrinter(new PrintWriter(new FileWriter("${doc_target}/map_${locale.name}.jhm"))).print(map)
|
||||
// Build JavaHelp map
|
||||
def map = new XmlParser().parse("${doc_src}/support/base-map.jhm")
|
||||
map.'**'.'mapID'.each { it.@url = "${locale.name}/${it.@url}" }
|
||||
new XmlNodePrinter(new PrintWriter(new FileWriter("${doc_target}/map_${locale.name}.jhm"))).print(map)
|
||||
|
||||
// Build HelpSet
|
||||
def hs = new File("${doc_src}/support/base-doc.hs")
|
||||
def out = new PrintWriter(new FileWriter("${doc_target}/doc_${locale.name}.hs"))
|
||||
hs.eachLine { out.println(it.replace("{lang}", locale.name)) }
|
||||
out.close()
|
||||
// Build HelpSet
|
||||
def hs = new File("${doc_src}/support/base-doc.hs")
|
||||
def out = new PrintWriter(new FileWriter("${doc_target}/doc_${locale.name}.hs"))
|
||||
hs.eachLine { out.println(it.replace("{lang}", locale.name)) }
|
||||
out.close()
|
||||
|
||||
// JavaHelp index
|
||||
javaexec {
|
||||
main = 'com.sun.java.help.search.Indexer'
|
||||
classpath = sourceSets.main.compileClasspath
|
||||
args '-c', 'jhindexer.cfg', '-db', "${doc_target}/search_lookup_${locale.name}", '-locale', locale.name, "${doc_target}/${locale.name}/html/guide", "${doc_target}/${locale.name}/html/libs"
|
||||
}
|
||||
}
|
||||
}
|
||||
// JavaHelp index
|
||||
javaexec {
|
||||
main = 'com.sun.java.help.search.Indexer'
|
||||
classpath = sourceSets.main.compileClasspath
|
||||
args '-c', 'jhindexer.cfg', '-db', "${doc_target}/search_lookup_${locale.name}", '-locale', locale.name, "${doc_target}/${locale.name}/html/guide", "${doc_target}/${locale.name}/html/libs"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ import javax.swing.SwingConstants;
|
|||
* HexEditor is a GUI component for editing Hex values.
|
||||
*
|
||||
* @author Carl Burch
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class HexEditor extends JComponent implements Scrollable {
|
||||
|
@ -32,7 +31,8 @@ public class HexEditor extends JComponent implements Scrollable {
|
|||
public void bytesChanged(HexModel source, long start, long numBytes,
|
||||
int[] oldValues) {
|
||||
repaint(0, measures.toY(start),
|
||||
getWidth(), measures.toY(start + numBytes) + measures.getCellHeight());
|
||||
getWidth(), measures.toY(start + numBytes) +
|
||||
measures.getCellHeight());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,10 @@ public class HexEditor extends JComponent implements Scrollable {
|
|||
private Caret caret;
|
||||
private Highlighter highlighter;
|
||||
|
||||
/**
|
||||
* Constructs a hex editor object, based on a model
|
||||
* @param model The model to base the editor on
|
||||
*/
|
||||
public HexEditor(HexModel model) {
|
||||
this.model = model;
|
||||
this.listener = new Listener();
|
||||
|
@ -49,13 +53,15 @@ public class HexEditor extends JComponent implements Scrollable {
|
|||
this.caret = new Caret(this);
|
||||
this.highlighter = new Highlighter(this);
|
||||
|
||||
// Nick A: change the font here
|
||||
this.setFont( new Font( "Dialog", Font.PLAIN, 16 ) );
|
||||
|
||||
setOpaque(true);
|
||||
setBackground(Color.WHITE);
|
||||
if (model != null) {
|
||||
model.addHexModelListener(listener);
|
||||
}
|
||||
|
||||
|
||||
measures.recompute();
|
||||
}
|
||||
|
||||
|
@ -63,22 +69,45 @@ public class HexEditor extends JComponent implements Scrollable {
|
|||
|
||||
Highlighter getHighlighter() { return highlighter; }
|
||||
|
||||
/**
|
||||
* Return the editor's base model
|
||||
* @return the model
|
||||
*/
|
||||
public HexModel getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the caret object (cursor)
|
||||
* @return the caret object
|
||||
*/
|
||||
public Caret getCaret() {
|
||||
return caret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extends the current highlighted regions.
|
||||
* @param start where to begin
|
||||
* @param end where to end
|
||||
* @param color the color of the highlight
|
||||
* @return the highlighted region's handle
|
||||
*/
|
||||
public Object addHighlight(int start, int end, Color color) {
|
||||
return highlighter.add(start, end, color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the highlighted region.
|
||||
* @param tag the highlighted object
|
||||
*/
|
||||
public void removeHighlight(Object tag) {
|
||||
highlighter.remove(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the model, if one doesn't exist or wants to be changed
|
||||
* @param value the new model
|
||||
*/
|
||||
public void setModel(HexModel value) {
|
||||
if (model == value) {
|
||||
return;
|
||||
|
@ -98,6 +127,11 @@ public class HexEditor extends JComponent implements Scrollable {
|
|||
measures.recompute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Scroll to the visible address (location of the caret).
|
||||
* @param start where to begin
|
||||
* @param end where to end
|
||||
*/
|
||||
public void scrollAddressToVisible(int start, int end) {
|
||||
if (start < 0 || end < 0) {
|
||||
return;
|
||||
|
@ -115,18 +149,33 @@ public class HexEditor extends JComponent implements Scrollable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current font and updates metrics
|
||||
* @param value the new font object
|
||||
*/
|
||||
@Override
|
||||
public void setFont(Font value) {
|
||||
super.setFont(value);
|
||||
measures.recompute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bounds of the hex fields.
|
||||
* @param x the x coordinate
|
||||
* @param y the y coordinate
|
||||
* @param width the width to adjust the metrics by
|
||||
* @param height the height to adjust the metrics by
|
||||
*/
|
||||
@Override
|
||||
public void setBounds(int x, int y, int width, int height) {
|
||||
super.setBounds(x, y, width, height);
|
||||
measures.widthChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Repaints the objects
|
||||
* @param g the graphics handle
|
||||
*/
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
measures.ensureComputed(g);
|
||||
|
@ -148,11 +197,16 @@ public class HexEditor extends JComponent implements Scrollable {
|
|||
long xaddr1 = measures.toAddress(getWidth(), clip.y + clip.height) + 1;
|
||||
highlighter.paint(g, xaddr0, xaddr1);
|
||||
|
||||
int newSize = (int)(Math.log10(clip.width*clip.height)*4);
|
||||
|
||||
this.setFont( new Font( "Dialog", Font.PLAIN, newSize ) );
|
||||
|
||||
g.setColor(getForeground());
|
||||
Font baseFont = g.getFont();
|
||||
FontMetrics baseFm = g.getFontMetrics(baseFont);
|
||||
Font labelFont = baseFont.deriveFont(Font.ITALIC);
|
||||
FontMetrics labelFm = g.getFontMetrics(labelFont);
|
||||
|
||||
int cols = measures.getColumnCount();
|
||||
int baseX = measures.getBaseX();
|
||||
int baseY = measures.toY(xaddr0) + baseFm.getAscent() + baseFm.getLeading() / 2;
|
||||
|
@ -161,6 +215,7 @@ public class HexEditor extends JComponent implements Scrollable {
|
|||
int labelChars = measures.getLabelChars();
|
||||
int cellWidth = measures.getCellWidth();
|
||||
int cellChars = measures.getCellChars();
|
||||
|
||||
for(long a = xaddr0; a < xaddr1; a += cols, baseY += dy) {
|
||||
String label = toHex(a, labelChars);
|
||||
g.setFont(labelFont);
|
||||
|
@ -179,6 +234,12 @@ public class HexEditor extends JComponent implements Scrollable {
|
|||
caret.paintForeground(g, xaddr0, xaddr1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a value to hex
|
||||
* @param value the long value
|
||||
* @param chars the characters value
|
||||
* @return the converted hex string
|
||||
*/
|
||||
private String toHex(long value, int chars) {
|
||||
String ret = Long.toHexString(value);
|
||||
int retLen = ret.length();
|
||||
|
@ -198,15 +259,26 @@ public class HexEditor extends JComponent implements Scrollable {
|
|||
//
|
||||
// selection methods
|
||||
//
|
||||
|
||||
/**
|
||||
* Is there a selection?
|
||||
* @return if it exists
|
||||
*/
|
||||
public boolean selectionExists() {
|
||||
return caret.getMark() >= 0 && caret.getDot() >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select every hex editor
|
||||
*/
|
||||
public void selectAll() {
|
||||
caret.setDot(model.getLastOffset(), false);
|
||||
caret.setDot(0, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the selection
|
||||
*/
|
||||
public void delete() {
|
||||
long p0 = caret.getMark();
|
||||
long p1 = caret.getDot();
|
||||
|
@ -223,11 +295,20 @@ public class HexEditor extends JComponent implements Scrollable {
|
|||
//
|
||||
// Scrollable methods
|
||||
//
|
||||
|
||||
/**
|
||||
* Returns the preferred size of the viewport
|
||||
* @return the dimensions object
|
||||
*/
|
||||
@Override
|
||||
public Dimension getPreferredScrollableViewportSize() {
|
||||
return getPreferredSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the increment in which to scroll
|
||||
* @return the scrolling increment
|
||||
*/
|
||||
@Override
|
||||
public int getScrollableUnitIncrement(Rectangle vis,
|
||||
int orientation, int direction) {
|
||||
|
@ -247,6 +328,9 @@ public class HexEditor extends JComponent implements Scrollable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the block increment so we don't scroll in the middle of one
|
||||
*/
|
||||
@Override
|
||||
public int getScrollableBlockIncrement(Rectangle vis,
|
||||
int orientation, int direction) {
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
package com.cburch.logisim;
|
||||
|
||||
import org.slf4j.*;
|
||||
|
||||
/**
|
||||
* Handles everything involving Logisim's version number
|
||||
* @author Carl Burch, Ryan Steinmetz
|
||||
|
@ -11,6 +13,8 @@ package com.cburch.logisim;
|
|||
public class LogisimVersion implements Comparable<LogisimVersion> {
|
||||
private static final int FINAL_REVISION = Integer.MAX_VALUE / 4;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger( LogisimVersion.class );
|
||||
|
||||
/**
|
||||
* Creates a new LogisimVersion object without a revision number
|
||||
* @param major
|
||||
|
@ -64,8 +68,7 @@ public class LogisimVersion implements Comparable<LogisimVersion> {
|
|||
}
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
System.out.println( "Something went wrong when parsing the version string:\n" );
|
||||
e.printStackTrace();
|
||||
logger.warn( "Something went wrong when parsing the version string." );
|
||||
}
|
||||
|
||||
return new LogisimVersion(major, minor, release, revision);
|
||||
|
|
|
@ -22,6 +22,9 @@ package com.cburch.logisim;
|
|||
|
||||
import com.cburch.logisim.gui.start.Startup;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Main entry point into Logisim.
|
||||
*
|
||||
|
@ -33,11 +36,19 @@ public class Main {
|
|||
public static final String VERSION_NAME = VERSION.toString();
|
||||
public static final int COPYRIGHT_YEAR = 2012;
|
||||
|
||||
/** Logger */
|
||||
public static final Logger logger = LoggerFactory.getLogger( Main.class );
|
||||
|
||||
/**
|
||||
* Entry point
|
||||
* @param args Command line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
Startup startup = Startup.parseArgs(args);
|
||||
if (startup == null) {
|
||||
System.exit(0);
|
||||
} else {
|
||||
logger.info( "Starting Logisim" );
|
||||
startup.run();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JScrollPane;
|
||||
|
@ -24,9 +25,19 @@ import com.cburch.logisim.tools.Library;
|
|||
import com.cburch.logisim.util.JFileChoosers;
|
||||
import com.cburch.logisim.util.MacCompatibility;
|
||||
import com.cburch.logisim.util.ZipClassLoader;
|
||||
|
||||
import static com.cburch.logisim.util.LocaleString.*;
|
||||
|
||||
import org.slf4j.*;
|
||||
|
||||
/**
|
||||
* A class to encapsulate loading functionality
|
||||
* of files or library objects
|
||||
*/
|
||||
public class Loader implements LibraryLoader {
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger( Loader.class );
|
||||
|
||||
public static final String LOGISIM_EXTENSION = ".circ";
|
||||
public static final FileFilter LOGISIM_FILTER = new LogisimFileFilter();
|
||||
public static final FileFilter JAR_FILTER = new JarFileFilter();
|
||||
|
@ -66,31 +77,53 @@ public class Loader implements LibraryLoader {
|
|||
private Stack<File> filesOpening = new Stack<File>();
|
||||
private Map<File,File> substitutions = new HashMap<File,File>();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param parent the parent
|
||||
*/
|
||||
public Loader(Component parent) {
|
||||
this.parent = parent;
|
||||
clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get built-in functionality.
|
||||
* @return the built-in functionality
|
||||
*/
|
||||
public Builtin getBuiltin() {
|
||||
return builtin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parent of the component from a high level.
|
||||
* @param value the component's new parent
|
||||
*/
|
||||
public void setParent(Component value) {
|
||||
parent = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get substitutions from a source file
|
||||
* @param source the source file
|
||||
* @return the returned file
|
||||
*/
|
||||
private File getSubstitution(File source) {
|
||||
File ret = substitutions.get(source);
|
||||
return ret == null ? source : ret;
|
||||
}
|
||||
|
||||
//
|
||||
// file chooser related methods
|
||||
//
|
||||
/**
|
||||
* Get the file from the file chooser
|
||||
* @return the selected file
|
||||
*/
|
||||
public File getMainFile() {
|
||||
return mainFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns a file chooser
|
||||
* @return the JFileChooser
|
||||
*/
|
||||
public JFileChooser createChooser() {
|
||||
return JFileChoosers.createAt(getCurrentDirectory());
|
||||
}
|
||||
|
@ -110,17 +143,25 @@ public class Loader implements LibraryLoader {
|
|||
mainFile = value;
|
||||
}
|
||||
|
||||
//
|
||||
// more substantive methods accessed from outside this package
|
||||
//
|
||||
/**
|
||||
* More substantive methods accessed from outside this package.
|
||||
*/
|
||||
public void clear() {
|
||||
filesOpening.clear();
|
||||
mainFile = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a file from an array of files to substitute.
|
||||
* @param file the main file
|
||||
* @param substitutions the substitution files
|
||||
* @return A functioning LogisimFile
|
||||
* @throws LoadFailedException if there was an error loading the file
|
||||
*/
|
||||
public LogisimFile openLogisimFile(File file, Map<File,File> substitutions)
|
||||
throws LoadFailedException {
|
||||
this.substitutions = substitutions;
|
||||
// FIXME allevaton: What's up with this? Try finally with no catch?
|
||||
try {
|
||||
return openLogisimFile(file);
|
||||
} finally {
|
||||
|
@ -128,6 +169,12 @@ public class Loader implements LibraryLoader {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a file from the hard drive.
|
||||
* @param file the file object
|
||||
* @return the LogisimFile object
|
||||
* @throws LoadFailedException if there was a problem loading the file
|
||||
*/
|
||||
public LogisimFile openLogisimFile(File file) throws LoadFailedException {
|
||||
try {
|
||||
LogisimFile ret = loadLogisimFile(file);
|
||||
|
@ -138,22 +185,38 @@ public class Loader implements LibraryLoader {
|
|||
showMessages(ret);
|
||||
return ret;
|
||||
} catch (LoaderException e) {
|
||||
logger.error( "An error occurred when loading the file.\n"
|
||||
+ e.getMessage() );
|
||||
throw new LoadFailedException(e.getMessage(), e.isShown());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a file from an input stream
|
||||
* @param reader The input stream
|
||||
* @return a fully functioning LogisimFile object
|
||||
* @throws LoadFailedException if it failed to load
|
||||
* @throws IOException if another error occurred
|
||||
*/
|
||||
public LogisimFile openLogisimFile(InputStream reader)
|
||||
throws LoadFailedException, IOException {
|
||||
LogisimFile ret = null;
|
||||
try {
|
||||
ret = LogisimFile.load(reader, this);
|
||||
} catch (LoaderException e) {
|
||||
logger.error( "An error occurred when loading the file.\n"
|
||||
+ e.getMessage() );
|
||||
return null;
|
||||
}
|
||||
showMessages(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a specified Logisim library
|
||||
* @param file the library file
|
||||
* @return the library object
|
||||
*/
|
||||
public Library loadLogisimLibrary(File file) {
|
||||
File actual = getSubstitution(file);
|
||||
LoadedLibrary ret = LibraryManager.instance.loadLogisimLibrary(this, actual);
|
||||
|
@ -164,15 +227,31 @@ public class Loader implements LibraryLoader {
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a library as a jar
|
||||
* @param file the jar file
|
||||
* @param className the class in the jar
|
||||
* @return the library object
|
||||
*/
|
||||
public Library loadJarLibrary(File file, String className) {
|
||||
File actual = getSubstitution(file);
|
||||
return LibraryManager.instance.loadJarLibrary(this, actual, className);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload the specified library.
|
||||
* @param lib The specified library
|
||||
*/
|
||||
public void reload(LoadedLibrary lib) {
|
||||
LibraryManager.instance.reload(this, lib);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the current file.
|
||||
* @param file The source file
|
||||
* @param dest The destination file
|
||||
* @return if the safe was a success
|
||||
*/
|
||||
public boolean save(LogisimFile file, File dest) {
|
||||
Library reference = LibraryManager.instance.findReference(file, dest);
|
||||
if (reference != null) {
|
||||
|
@ -190,7 +269,10 @@ public class Loader implements LibraryLoader {
|
|||
try {
|
||||
try {
|
||||
MacCompatibility.setFileCreatorAndType(dest, "LGSM", "circ");
|
||||
} catch (IOException e) { }
|
||||
} catch (IOException e) {
|
||||
logger.warn( "Could not set Mac compatible"
|
||||
+ " file associative flags (file creator and type)" );
|
||||
}
|
||||
fwrite = new FileOutputStream(dest);
|
||||
file.write(fwrite, this);
|
||||
file.setName(toProjectName(dest));
|
||||
|
@ -200,6 +282,7 @@ public class Loader implements LibraryLoader {
|
|||
LibraryManager.instance.fileSaved(this, dest, oldFile, file);
|
||||
} catch (IOException e) {
|
||||
if (backupCreated) {
|
||||
logger.info( "Backup found, recovering from it." );
|
||||
recoverBackup(backup, dest);
|
||||
}
|
||||
|
||||
|
@ -220,6 +303,7 @@ public class Loader implements LibraryLoader {
|
|||
fwrite.close();
|
||||
} catch (IOException e) {
|
||||
if (backupCreated) {
|
||||
logger.info( "Backup found, recovering from it." );
|
||||
recoverBackup(backup, dest);
|
||||
}
|
||||
if (dest.exists() && dest.length() == 0) {
|
||||
|
@ -254,6 +338,11 @@ public class Loader implements LibraryLoader {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a name for a backup file
|
||||
* @param base the base file
|
||||
* @return the backup file
|
||||
*/
|
||||
private static File determineBackupName(File base) {
|
||||
File dir = base.getParentFile();
|
||||
String name = base.getName();
|
||||
|
@ -271,6 +360,11 @@ public class Loader implements LibraryLoader {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recover from a backup.
|
||||
* @param backup the backup file to recover from
|
||||
* @param dest where does the backup file go
|
||||
*/
|
||||
private static void recoverBackup(File backup, File dest) {
|
||||
if (backup != null && backup.exists()) {
|
||||
if (dest.exists()) {
|
||||
|
@ -281,13 +375,17 @@ public class Loader implements LibraryLoader {
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// methods for LibraryManager
|
||||
//
|
||||
/**
|
||||
* Loads a Logisim file
|
||||
* @param request the requested file
|
||||
* @return the completed file object
|
||||
*/
|
||||
LogisimFile loadLogisimFile(File request) throws LoadFailedException {
|
||||
File actual = getSubstitution(request);
|
||||
for (File fileOpening : filesOpening) {
|
||||
if (fileOpening.equals(actual)) {
|
||||
logger.error( "An error occurred when opening the file.\n"
|
||||
+ _("logisimCircularError" ) );
|
||||
throw new LoadFailedException(_("logisimCircularError",
|
||||
toProjectName(actual)));
|
||||
}
|
||||
|
@ -298,6 +396,8 @@ public class Loader implements LibraryLoader {
|
|||
try {
|
||||
ret = LogisimFile.load(actual, this);
|
||||
} catch (IOException e) {
|
||||
logger.error( "An error occurred when opening the file.\n"
|
||||
+ _("logisimCircularError" ) );
|
||||
throw new LoadFailedException(_("logisimLoadError",
|
||||
toProjectName(actual), e.toString()));
|
||||
} finally {
|
||||
|
@ -307,6 +407,12 @@ public class Loader implements LibraryLoader {
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a Java jar file as a library
|
||||
* @param request the requested jar file
|
||||
* @param string the class name specified in the file
|
||||
* @return the loaded library
|
||||
*/
|
||||
Library loadJarFile(File request, String className) throws LoadFailedException {
|
||||
File actual = getSubstitution(request);
|
||||
// Up until 2.1.8, this was written to use a URLClassLoader, which
|
||||
|
@ -339,9 +445,11 @@ public class Loader implements LibraryLoader {
|
|||
try {
|
||||
retClass = loader.loadClass(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
logger.error( "Class not found" );
|
||||
throw new LoadFailedException(_("jarClassNotFoundError", className));
|
||||
}
|
||||
if (!(Library.class.isAssignableFrom(retClass))) {
|
||||
logger.error( "Class not library" );
|
||||
throw new LoadFailedException(_("jarClassNotLibraryError", className));
|
||||
}
|
||||
|
||||
|
@ -350,6 +458,7 @@ public class Loader implements LibraryLoader {
|
|||
try {
|
||||
ret = (Library) retClass.newInstance();
|
||||
} catch (Exception e) {
|
||||
logger.error( "Class not library" );
|
||||
throw new LoadFailedException(_("jarLibraryNotCreatedError", className));
|
||||
}
|
||||
return ret;
|
||||
|
@ -358,18 +467,34 @@ public class Loader implements LibraryLoader {
|
|||
//
|
||||
// Library methods
|
||||
//
|
||||
|
||||
/**
|
||||
* Loads a Logisim library
|
||||
* @param desc the file descriptor
|
||||
* @return the library object
|
||||
*/
|
||||
@Override
|
||||
public Library loadLibrary(String desc) {
|
||||
return LibraryManager.instance.loadLibrary(this, desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a descriptor from a library
|
||||
* @param lib the library
|
||||
* @return the descriptor
|
||||
*/
|
||||
@Override
|
||||
public String getDescriptor(Library lib) {
|
||||
return LibraryManager.instance.getDescriptor(this, lib);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows an error based on its description, also logs it
|
||||
* @param description the error text
|
||||
*/
|
||||
@Override
|
||||
public void showError(String description) {
|
||||
logger.error( description );
|
||||
if (!filesOpening.empty()) {
|
||||
File top = filesOpening.peek();
|
||||
String init = toProjectName(top) + ":";
|
||||
|
@ -403,6 +528,10 @@ public class Loader implements LibraryLoader {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the messages from a file
|
||||
* @param source the file to load from
|
||||
*/
|
||||
private void showMessages(LogisimFile source) {
|
||||
if (source == null) {
|
||||
return;
|
||||
|
@ -420,6 +549,13 @@ public class Loader implements LibraryLoader {
|
|||
//
|
||||
// helper methods
|
||||
//
|
||||
|
||||
/**
|
||||
* Get a file from a name
|
||||
* @param name file name
|
||||
* @param filter the file name filter
|
||||
* @return the file object
|
||||
*/
|
||||
File getFileFor(String name, FileFilter filter) {
|
||||
// Determine the actual file name.
|
||||
File file = new File(name);
|
||||
|
@ -447,6 +583,11 @@ public class Loader implements LibraryLoader {
|
|||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Conform a file to the current project
|
||||
* @param file the destined file
|
||||
* @return the project name
|
||||
*/
|
||||
private String toProjectName(File file) {
|
||||
String ret = file.getName();
|
||||
if (ret.endsWith(LOGISIM_EXTENSION)) {
|
||||
|
|
|
@ -13,6 +13,9 @@ import java.io.File;
|
|||
|
||||
import javax.swing.UIManager;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.cburch.logisim.Main;
|
||||
import com.cburch.logisim.file.LoadFailedException;
|
||||
import com.cburch.logisim.file.Loader;
|
||||
|
@ -25,11 +28,17 @@ import com.cburch.logisim.proj.Project;
|
|||
import com.cburch.logisim.proj.ProjectActions;
|
||||
import com.cburch.logisim.util.LocaleManager;
|
||||
import com.cburch.logisim.util.MacCompatibility;
|
||||
|
||||
import static com.cburch.logisim.util.LocaleString.*;
|
||||
|
||||
/**
|
||||
* A class to encapsulate the startup process
|
||||
*/
|
||||
public class Startup {
|
||||
private static Startup startupTemp = null;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger( Startup.class );
|
||||
|
||||
static void doOpen(File file) {
|
||||
if (startupTemp != null) {
|
||||
startupTemp.doOpenFile(file);
|
||||
|
@ -76,11 +85,14 @@ public class Startup {
|
|||
MacOsAdapter.register();
|
||||
MacOsAdapter.addListeners(true);
|
||||
} catch (ClassNotFoundException e) {
|
||||
logger.warn( "Failed to register handler: " + e.getLocalizedMessage() );
|
||||
return;
|
||||
} catch (Exception t) {
|
||||
try {
|
||||
MacOsAdapter.addListeners(false);
|
||||
} catch (Exception t2) { }
|
||||
} catch (Exception t2) {
|
||||
logger.warn( "Failed to register MacOS adapters" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,15 +133,19 @@ public class Startup {
|
|||
return Collections.unmodifiableMap(substitutions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts splash screen and launches Logisim
|
||||
*/
|
||||
public void run() {
|
||||
if (isTty) {
|
||||
try {
|
||||
TtyInterface.run(this);
|
||||
return;
|
||||
} catch (Exception t) {
|
||||
t.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
logger.error( "Logisim failed to start.\nException: "
|
||||
+ e.getLocalizedMessage() );
|
||||
e.printStackTrace();
|
||||
System.exit(-1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,9 +156,10 @@ public class Startup {
|
|||
try {
|
||||
monitor = new SplashScreen();
|
||||
monitor.setVisible(true);
|
||||
} catch (Exception t) {
|
||||
} catch (Exception e) {
|
||||
monitor = null;
|
||||
showSplash = false;
|
||||
logger.warn( "Not showing the splash screen, for some reason" );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,7 +175,7 @@ public class Startup {
|
|||
if (count < 0) {
|
||||
// this will never happen, but the optimizer doesn't know that...
|
||||
//OK
|
||||
System.err.println("FATAL ERROR - no components");
|
||||
logger.error( "FATAL - no components were found");
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
|
@ -199,7 +216,8 @@ public class Startup {
|
|||
ProjectActions.doOpen(monitor, fileToOpen, substitutions);
|
||||
} catch (LoadFailedException ex) {
|
||||
//OK
|
||||
System.err.println(fileToOpen.getName() + ": " + ex.getMessage());
|
||||
logger.error( "Could not open "
|
||||
+ fileToOpen.getName() + ": " + ex.getMessage() );
|
||||
System.exit(-1);
|
||||
}
|
||||
if (first) {
|
||||
|
@ -227,12 +245,12 @@ public class Startup {
|
|||
}
|
||||
}
|
||||
//OK
|
||||
System.err.println(_("invalidLocaleError"));
|
||||
logger.warn(_("invalidLocaleError"));
|
||||
//OK
|
||||
System.err.println(_("invalidLocaleOptionsHeader"));
|
||||
logger.warn(_("invalidLocaleOptionsHeader"));
|
||||
for (int i = 0; i < opts.length; i++) {
|
||||
//OK
|
||||
System.err.println(" " + opts[i].toString());
|
||||
logger.warn(" " + opts[i].toString());
|
||||
}
|
||||
System.exit(-1);
|
||||
}
|
||||
|
@ -254,8 +272,8 @@ public class Startup {
|
|||
}
|
||||
/**
|
||||
* Parses the command-line arguments to com.cburch.logisim.Main
|
||||
* @param args
|
||||
* @return A Startup object
|
||||
* @param args command line arguments
|
||||
* @return A Startup object or null if it fails
|
||||
*/
|
||||
public static Startup parseArgs(String[] args) {
|
||||
// see whether we'll be using any graphics
|
||||
|
@ -303,7 +321,7 @@ public class Startup {
|
|||
String[] fmts = args[i].split(",");
|
||||
if (fmts.length == 0) {
|
||||
//OK
|
||||
System.err.println(_("ttyFormatError"));
|
||||
logger.warn(_("ttyFormatError"));
|
||||
}
|
||||
for (int j = 0; j < fmts.length; j++) {
|
||||
String fmt = fmts[j].trim();
|
||||
|
@ -333,7 +351,7 @@ public class Startup {
|
|||
File b = new File(args[i + 2]);
|
||||
if (ret.substitutions.containsKey(a)) {
|
||||
//OK
|
||||
System.err.println(_("argDuplicateSubstitutionError"));
|
||||
logger.error(_("argDuplicateSubstitutionError"));
|
||||
return null;
|
||||
} else {
|
||||
ret.substitutions.put(a, b);
|
||||
|
@ -341,7 +359,7 @@ public class Startup {
|
|||
}
|
||||
} else {
|
||||
//OK
|
||||
System.err.println(_("argTwoSubstitutionError"));
|
||||
logger.error(_("argTwoSubstitutionError"));
|
||||
return null;
|
||||
}
|
||||
} else if (arg.equals("-load")) {
|
||||
|
@ -349,26 +367,26 @@ public class Startup {
|
|||
i++;
|
||||
if (ret.loadFile != null) {
|
||||
//OK
|
||||
System.err.println(_("loadMultipleError"));
|
||||
logger.warn(_("loadMultipleError"));
|
||||
}
|
||||
File f = new File(args[i]);
|
||||
ret.loadFile = f;
|
||||
} else {
|
||||
//OK
|
||||
System.err.println(_("loadNeedsFileError"));
|
||||
logger.error(_("loadNeedsFileError"));
|
||||
return null;
|
||||
}
|
||||
} else if (arg.equals("-empty")) {
|
||||
if (ret.templFile != null || ret.templEmpty || ret.templPlain) {
|
||||
//OK
|
||||
System.err.println(_("argOneTemplateError"));
|
||||
logger.error(_("argOneTemplateError"));
|
||||
return null;
|
||||
}
|
||||
ret.templEmpty = true;
|
||||
} else if (arg.equals("-plain")) {
|
||||
if (ret.templFile != null || ret.templEmpty || ret.templPlain) {
|
||||
//OK
|
||||
System.err.println(_("argOneTemplateError"));
|
||||
logger.error(_("argOneTemplateError"));
|
||||
return null;
|
||||
}
|
||||
ret.templPlain = true;
|
||||
|
@ -389,7 +407,7 @@ public class Startup {
|
|||
AppPreferences.GATE_SHAPE.set(AppPreferences.SHAPE_RECTANGULAR);
|
||||
} else {
|
||||
//OK
|
||||
System.err.println(_("argGatesOptionError"));
|
||||
logger.error(_("argGatesOptionError"));
|
||||
System.exit(-1);
|
||||
}
|
||||
} else if (arg.equals("-locale")) {
|
||||
|
@ -412,13 +430,13 @@ public class Startup {
|
|||
AppPreferences.ACCENTS_REPLACE.setBoolean(true);
|
||||
} else {
|
||||
//OK
|
||||
System.err.println(_("argAccentsOptionError"));
|
||||
logger.error(_("argAccentsOptionError"));
|
||||
System.exit(-1);
|
||||
}
|
||||
} else if (arg.equals("-template")) {
|
||||
if (ret.templFile != null || ret.templEmpty || ret.templPlain) {
|
||||
//OK
|
||||
System.err.println(_("argOneTemplateError"));
|
||||
logger.error(_("argOneTemplateError"));
|
||||
return null;
|
||||
}
|
||||
i++;
|
||||
|
@ -429,11 +447,11 @@ public class Startup {
|
|||
ret.templFile = new File(args[i]);
|
||||
if (!ret.templFile.exists()) {
|
||||
//OK
|
||||
System.err.println(String.format(
|
||||
logger.warn(String.format(
|
||||
_("templateMissingError"), args[i]));
|
||||
} else if (!ret.templFile.canRead()) {
|
||||
//OK
|
||||
System.err.println(String.format(
|
||||
logger.warn(String.format(
|
||||
_("templateCannotReadError"), args[i]));
|
||||
}
|
||||
} else if (arg.equals("-nosplash")) {
|
||||
|
@ -449,49 +467,36 @@ public class Startup {
|
|||
}
|
||||
if (ret.isTty && ret.filesToOpen.isEmpty()) {
|
||||
//OK
|
||||
System.err.println(_("ttyNeedsFileError"));
|
||||
logger.error(_("ttyNeedsFileError"));
|
||||
return null;
|
||||
}
|
||||
if (ret.loadFile != null && !ret.isTty) {
|
||||
//OK
|
||||
System.err.println(_("loadNeedsTtyError"));
|
||||
logger.error(_("loadNeedsTtyError"));
|
||||
return null;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints command line help functionality
|
||||
*/
|
||||
private static void printUsage() {
|
||||
//OK
|
||||
System.err.println(String.format(_("argUsage"), Startup.class.getName()));
|
||||
//OK
|
||||
System.err.println();
|
||||
//OK
|
||||
System.err.println(_("argOptionHeader"));
|
||||
//OK
|
||||
System.err.println(" " + _("argAccentsOption"));
|
||||
//OK
|
||||
System.err.println(" " + _("argClearOption"));
|
||||
//OK
|
||||
System.err.println(" " + _("argEmptyOption"));
|
||||
//OK
|
||||
System.err.println(" " + _("argGatesOption"));
|
||||
//OK
|
||||
System.err.println(" " + _("argHelpOption"));
|
||||
//OK
|
||||
System.err.println(" " + _("argLoadOption"));
|
||||
//OK
|
||||
System.err.println(" " + _("argLocaleOption"));
|
||||
//OK
|
||||
System.err.println(" " + _("argNoSplashOption"));
|
||||
//OK
|
||||
System.err.println(" " + _("argPlainOption"));
|
||||
//OK
|
||||
System.err.println(" " + _("argSubOption"));
|
||||
//OK
|
||||
System.err.println(" " + _("argTemplateOption"));
|
||||
//OK
|
||||
System.err.println(" " + _("argTtyOption"));
|
||||
//OK
|
||||
System.err.println(" " + _("argVersionOption"));
|
||||
System.exit(-1);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue