mirror of https://github.com/lawrancej/logisim.git
Integrating a large number bug fixes, all of which (or most of which) are based on bug reports submitted through SourceForge:
Feature: The window's last-observed location is saved as a preference, and that location is used when the application starts later. Bug fix: The Probe's Radix attribute displayed the values as they are saved in the file, rather than the display strings based on the current translation being used. Appearance change: Rectangular XOR and XNOR gates are drawn with "=1" to conform to the ISO standard (previously it was simply "1"). However, if the "Multiple-Input Behavior" attribute is "When an odd number are on" and there are more than two inputs, the label is "2k+1" to reflect that it is actually doing an odd parity. (Previously it showed this label for odd parity even when there were just two inputs.) Bug fix: Edits to the Bit Extender's Extension Type attribute or the Comparator's did not have an immediate effect in the circuit. Bug fix: Under MacOS X, the title bar's close-window button would indicate that the file was changed after the first change, but the indicator would not disappear when the file was saved. Bug fix: When a rectangle, oval, or rounded rectangle in a circuit's appearance had a paint type of "Border & Fill" and it was filled with solid black, that information was not properly stored in the saved file. Bug fix: Libraries could not be unloaded. Bug fix: The XNOR gate incorrectly did even parity by default, rather than being off only when exactly one input is one. Bug fix: Most options were not loaded when a file was later reopened (all except the toolbar and mouse mappings). Bug fix: The Logisim version saved in the project file was not interpreted correctly when opening the project. One consequence: If you edited the toolbar to include the Select and Wiring tools, they would be replaced by the Edit tool when reloaded. Bug fix: When moving a selection so that one wire in the selection is moved exactly into the location of a wire being moved, the wire would sometimes disappear entirely rather than be moved. Bug fix: With the Edit Tool, pressing the backspace key deletes the current selection (just as it does when the delete key is pressed). Bug fix: Edits to the Bit Extender's Extension Type attribute or the Comparator's did not have an immediate effect in the circuit. Bug fix: Under MacOS X, the title bar's close-window button would indicate that the file was changed after the first change, but the indicator would not disappear when the file was saved. git-svn-id: https://circuit.svn.sourceforge.net/svnroot/circuit/trunk@164 70edf91d-0b9e-4248-82e7-2488d7716404
This commit is contained in:
parent
dcda046abb
commit
d4499774e5
|
@ -143,7 +143,9 @@ class SvgCreator {
|
||||||
elt.setAttribute("fill", "none");
|
elt.setAttribute("fill", "none");
|
||||||
} else {
|
} else {
|
||||||
Color fill = shape.getValue(DrawAttr.FILL_COLOR);
|
Color fill = shape.getValue(DrawAttr.FILL_COLOR);
|
||||||
if (!colorMatches(fill, Color.BLACK)) {
|
if (colorMatches(fill, Color.BLACK)) {
|
||||||
|
elt.removeAttribute("fill");
|
||||||
|
} else {
|
||||||
elt.setAttribute("fill", getColorString(fill));
|
elt.setAttribute("fill", getColorString(fill));
|
||||||
}
|
}
|
||||||
if (showOpacity(fill)) {
|
if (showOpacity(fill)) {
|
||||||
|
|
|
@ -49,7 +49,7 @@ public class SvgReader {
|
||||||
String fill = elt.getAttribute("fill");
|
String fill = elt.getAttribute("fill");
|
||||||
if (stroke.equals("") || stroke.equals("none")) {
|
if (stroke.equals("") || stroke.equals("none")) {
|
||||||
ret.setValue(DrawAttr.PAINT_TYPE, DrawAttr.PAINT_FILL);
|
ret.setValue(DrawAttr.PAINT_TYPE, DrawAttr.PAINT_FILL);
|
||||||
} else if (fill.equals("") || fill.equals("none")) {
|
} else if (fill.equals("none")) {
|
||||||
ret.setValue(DrawAttr.PAINT_TYPE, DrawAttr.PAINT_STROKE);
|
ret.setValue(DrawAttr.PAINT_TYPE, DrawAttr.PAINT_STROKE);
|
||||||
} else {
|
} else {
|
||||||
ret.setValue(DrawAttr.PAINT_TYPE, DrawAttr.PAINT_STROKE_FILL);
|
ret.setValue(DrawAttr.PAINT_TYPE, DrawAttr.PAINT_STROKE_FILL);
|
||||||
|
@ -69,6 +69,7 @@ public class SvgReader {
|
||||||
}
|
}
|
||||||
if (attrs.contains(DrawAttr.FILL_COLOR)) {
|
if (attrs.contains(DrawAttr.FILL_COLOR)) {
|
||||||
String color = elt.getAttribute("fill");
|
String color = elt.getAttribute("fill");
|
||||||
|
if (color.equals("")) color = "#000000";
|
||||||
String opacity = elt.getAttribute("fill-opacity");
|
String opacity = elt.getAttribute("fill-opacity");
|
||||||
if (!color.equals("none")) {
|
if (!color.equals("none")) {
|
||||||
ret.setValue(DrawAttr.FILL_COLOR, getColor(color, opacity));
|
ret.setValue(DrawAttr.FILL_COLOR, getColor(color, opacity));
|
||||||
|
|
|
@ -15,7 +15,7 @@ public class LogisimVersion {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LogisimVersion parse(String versionString) {
|
public static LogisimVersion parse(String versionString) {
|
||||||
String[] parts = versionString.split(".");
|
String[] parts = versionString.split("\\.");
|
||||||
int major = 0;
|
int major = 0;
|
||||||
int minor = 0;
|
int minor = 0;
|
||||||
int release = 0;
|
int release = 0;
|
||||||
|
|
|
@ -145,20 +145,28 @@ class CircuitChange {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute(CircuitMutator mutator) {
|
void execute(CircuitMutator mutator, ReplacementMap prevReplacements) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CLEAR: mutator.clear(circuit); break;
|
case CLEAR: mutator.clear(circuit); prevReplacements.reset(); break;
|
||||||
case ADD: mutator.add(circuit, comp); break;
|
case ADD: prevReplacements.add(comp); break;
|
||||||
case ADD_ALL:
|
case ADD_ALL:
|
||||||
for (Component comp : comps) mutator.add(circuit, comp);
|
for (Component comp : comps) prevReplacements.add(comp);
|
||||||
break;
|
break;
|
||||||
case REMOVE: mutator.remove(circuit, comp); break;
|
case REMOVE: prevReplacements.remove(comp); break;
|
||||||
case REMOVE_ALL:
|
case REMOVE_ALL:
|
||||||
for (Component comp : comps) mutator.remove(circuit, comp);
|
for (Component comp : comps) prevReplacements.remove(comp);
|
||||||
|
break;
|
||||||
|
case REPLACE: prevReplacements.append((ReplacementMap) newValue); break;
|
||||||
|
case SET:
|
||||||
|
mutator.replace(circuit, prevReplacements);
|
||||||
|
prevReplacements.reset();
|
||||||
|
mutator.set(circuit, comp, attr, newValue);
|
||||||
|
break;
|
||||||
|
case SET_FOR_CIRCUIT:
|
||||||
|
mutator.replace(circuit, prevReplacements);
|
||||||
|
prevReplacements.reset();
|
||||||
|
mutator.setForCircuit(circuit, attr, newValue);
|
||||||
break;
|
break;
|
||||||
case REPLACE: mutator.replace(circuit, (ReplacementMap) newValue); break;
|
|
||||||
case SET: mutator.set(circuit, comp, attr, newValue); break;
|
|
||||||
case SET_FOR_CIRCUIT: mutator.setForCircuit(circuit, attr, newValue); break;
|
|
||||||
default: throw new IllegalArgumentException("unknown change type " + type);
|
default: throw new IllegalArgumentException("unknown change type " + type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,8 +103,21 @@ public final class CircuitMutation extends CircuitTransaction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void run(CircuitMutator mutator) {
|
protected void run(CircuitMutator mutator) {
|
||||||
|
Circuit curCircuit = null;
|
||||||
|
ReplacementMap curReplacements = null;
|
||||||
for (CircuitChange change : changes) {
|
for (CircuitChange change : changes) {
|
||||||
change.execute(mutator);
|
Circuit circ = change.getCircuit();
|
||||||
|
if (circ != curCircuit) {
|
||||||
|
if (curCircuit != null) {
|
||||||
|
mutator.replace(curCircuit, curReplacements);
|
||||||
|
}
|
||||||
|
curCircuit = circ;
|
||||||
|
curReplacements = new ReplacementMap();
|
||||||
|
}
|
||||||
|
change.execute(mutator, curReplacements);
|
||||||
|
}
|
||||||
|
if (curCircuit != null) {
|
||||||
|
mutator.replace(curCircuit, curReplacements);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,12 +4,13 @@
|
||||||
package com.cburch.logisim.circuit;
|
package com.cburch.logisim.circuit;
|
||||||
|
|
||||||
import com.cburch.logisim.data.Attribute;
|
import com.cburch.logisim.data.Attribute;
|
||||||
|
import com.cburch.logisim.data.AttributeOption;
|
||||||
import com.cburch.logisim.data.Attributes;
|
import com.cburch.logisim.data.Attributes;
|
||||||
import com.cburch.logisim.data.BitWidth;
|
import com.cburch.logisim.data.BitWidth;
|
||||||
import com.cburch.logisim.data.Value;
|
import com.cburch.logisim.data.Value;
|
||||||
import com.cburch.logisim.util.StringGetter;
|
import com.cburch.logisim.util.StringGetter;
|
||||||
|
|
||||||
public abstract class RadixOption {
|
public abstract class RadixOption extends AttributeOption {
|
||||||
public static final RadixOption RADIX_2 = new Radix2();
|
public static final RadixOption RADIX_2 = new Radix2();
|
||||||
public static final RadixOption RADIX_8 = new Radix8();
|
public static final RadixOption RADIX_8 = new Radix8();
|
||||||
public static final RadixOption RADIX_10_UNSIGNED = new Radix10Unsigned();
|
public static final RadixOption RADIX_10_UNSIGNED = new Radix10Unsigned();
|
||||||
|
@ -35,6 +36,7 @@ public abstract class RadixOption {
|
||||||
private StringGetter displayGetter;
|
private StringGetter displayGetter;
|
||||||
|
|
||||||
private RadixOption(String saveName, StringGetter displayGetter) {
|
private RadixOption(String saveName, StringGetter displayGetter) {
|
||||||
|
super(saveName, displayGetter);
|
||||||
this.saveName = saveName;
|
this.saveName = saveName;
|
||||||
this.displayGetter = displayGetter;
|
this.displayGetter = displayGetter;
|
||||||
}
|
}
|
||||||
|
@ -47,6 +49,7 @@ public abstract class RadixOption {
|
||||||
return saveName;
|
return saveName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toDisplayString() {
|
public String toDisplayString() {
|
||||||
return displayGetter.get();
|
return displayGetter.get();
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,11 @@ public class ReplacementMap {
|
||||||
this.inverse = inverse;
|
this.inverse = inverse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
map.clear();
|
||||||
|
inverse.clear();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return map.isEmpty() && inverse.isEmpty();
|
return map.isEmpty() && inverse.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,15 @@ class WireIterator implements Iterator<Location> {
|
||||||
if (curY < destY) deltaY = 10;
|
if (curY < destY) deltaY = 10;
|
||||||
else if (curY > destY) deltaY = -10;
|
else if (curY > destY) deltaY = -10;
|
||||||
else deltaY = 0;
|
else deltaY = 0;
|
||||||
|
|
||||||
|
int offX = (destX - curX) % 10;
|
||||||
|
if (offX != 0) { // should not happen, but in case it does...
|
||||||
|
destX = curX + deltaX * ((destX - curX) / 10);
|
||||||
|
}
|
||||||
|
int offY = (destY - curY) % 10;
|
||||||
|
if (offY != 0) { // should not happen, but in case it does...
|
||||||
|
destY = curY + deltaY * ((destY - curY) / 10);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
|
|
|
@ -270,8 +270,8 @@ public class LogisimFile extends Library implements LibraryEventSource {
|
||||||
factories.add(((AddTool) tool).getFactory());
|
factories.add(((AddTool) tool).getFactory());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (AddTool tool : tools) {
|
|
||||||
Circuit circuit = (Circuit) tool.getFactory();
|
for (Circuit circuit : getCircuits()) {
|
||||||
for (Component comp : circuit.getNonWires()) {
|
for (Component comp : circuit.getNonWires()) {
|
||||||
if (factories.contains(comp.getFactory())) {
|
if (factories.contains(comp.getFactory())) {
|
||||||
return StringUtil.format(Strings.get("unloadUsedError"),
|
return StringUtil.format(Strings.get("unloadUsedError"),
|
||||||
|
@ -300,10 +300,6 @@ public class LogisimFile extends Library implements LibraryEventSource {
|
||||||
fireEvent(LibraryEvent.SET_MAIN, circuit);
|
fireEvent(LibraryEvent.SET_MAIN, circuit);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOptions(Options options) {
|
|
||||||
this.options = options;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// other methods
|
// other methods
|
||||||
//
|
//
|
||||||
|
|
|
@ -32,11 +32,15 @@ public class Options {
|
||||||
GATE_UNDEFINED_IGNORE, Integer.valueOf(1000), Integer.valueOf(0),
|
GATE_UNDEFINED_IGNORE, Integer.valueOf(1000), Integer.valueOf(0),
|
||||||
};
|
};
|
||||||
|
|
||||||
private AttributeSet attrs = AttributeSets.fixedSet(ATTRIBUTES, DEFAULTS);
|
private AttributeSet attrs;
|
||||||
private MouseMappings mmappings = new MouseMappings();
|
private MouseMappings mmappings;
|
||||||
private ToolbarData toolbar = new ToolbarData();
|
private ToolbarData toolbar;
|
||||||
|
|
||||||
public Options() { }
|
public Options() {
|
||||||
|
attrs = AttributeSets.fixedSet(ATTRIBUTES, DEFAULTS);
|
||||||
|
mmappings = new MouseMappings();
|
||||||
|
toolbar = new ToolbarData();
|
||||||
|
}
|
||||||
|
|
||||||
public AttributeSet getAttributeSet() {
|
public AttributeSet getAttributeSet() {
|
||||||
return attrs;
|
return attrs;
|
||||||
|
|
|
@ -94,7 +94,7 @@ class XmlReader {
|
||||||
if (name.equals("circuit") || name.equals("lib")) {
|
if (name.equals("circuit") || name.equals("lib")) {
|
||||||
; // Nothing to do: Done earlier.
|
; // Nothing to do: Done earlier.
|
||||||
} else if (name.equals("options")) {
|
} else if (name.equals("options")) {
|
||||||
initAttributeSet(elt, file.getOptions().getAttributeSet(), null);
|
initAttributeSet(sub_elt, file.getOptions().getAttributeSet(), null);
|
||||||
} else if (name.equals("mappings")) {
|
} else if (name.equals("mappings")) {
|
||||||
initMouseMappings(sub_elt);
|
initMouseMappings(sub_elt);
|
||||||
} else if (name.equals("toolbar")) {
|
} else if (name.equals("toolbar")) {
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
/* Copyright (c) 2010, Carl Burch. License information is located in the
|
||||||
|
* com.cburch.logisim.Main source code and at www.cburch.com/logisim/. */
|
||||||
|
|
||||||
package com.cburch.logisim.gui.generic;
|
package com.cburch.logisim.gui.generic;
|
||||||
|
|
||||||
import java.awt.Frame;
|
import java.awt.Frame;
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
/* Copyright (c) 2010, Carl Burch. License information is located in the
|
||||||
|
* com.cburch.logisim.Main source code and at www.cburch.com/logisim/. */
|
||||||
|
|
||||||
package com.cburch.logisim.gui.generic;
|
package com.cburch.logisim.gui.generic;
|
||||||
|
|
||||||
import java.awt.Image;
|
import java.awt.Image;
|
||||||
|
|
|
@ -7,6 +7,12 @@ import java.awt.BorderLayout;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Container;
|
import java.awt.Container;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
|
import java.awt.GraphicsConfiguration;
|
||||||
|
import java.awt.GraphicsDevice;
|
||||||
|
import java.awt.GraphicsEnvironment;
|
||||||
|
import java.awt.IllegalComponentStateException;
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.awt.Rectangle;
|
||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
|
@ -45,6 +51,7 @@ import com.cburch.logisim.proj.Project;
|
||||||
import com.cburch.logisim.proj.ProjectActions;
|
import com.cburch.logisim.proj.ProjectActions;
|
||||||
import com.cburch.logisim.proj.ProjectEvent;
|
import com.cburch.logisim.proj.ProjectEvent;
|
||||||
import com.cburch.logisim.proj.ProjectListener;
|
import com.cburch.logisim.proj.ProjectListener;
|
||||||
|
import com.cburch.logisim.proj.Projects;
|
||||||
import com.cburch.logisim.tools.SetAttributeAction;
|
import com.cburch.logisim.tools.SetAttributeAction;
|
||||||
import com.cburch.logisim.tools.Tool;
|
import com.cburch.logisim.tools.Tool;
|
||||||
import com.cburch.logisim.util.HorizontalSplitPane;
|
import com.cburch.logisim.util.HorizontalSplitPane;
|
||||||
|
@ -65,12 +72,6 @@ public class Frame extends LFrame implements LocaleListener {
|
||||||
public void projectChanged(ProjectEvent event) {
|
public void projectChanged(ProjectEvent event) {
|
||||||
int action = event.getAction();
|
int action = event.getAction();
|
||||||
|
|
||||||
if (action == ProjectEvent.ACTION_COMPLETE
|
|
||||||
|| action == ProjectEvent.UNDO_COMPLETE
|
|
||||||
|| action == ProjectEvent.ACTION_SET_FILE) {
|
|
||||||
enableSave();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (action == ProjectEvent.ACTION_SET_FILE) {
|
if (action == ProjectEvent.ACTION_SET_FILE) {
|
||||||
computeTitle();
|
computeTitle();
|
||||||
proj.setTool(proj.getOptions().getToolbarData().getFirstTool());
|
proj.setTool(proj.getOptions().getToolbarData().getFirstTool());
|
||||||
|
@ -93,6 +94,8 @@ public class Frame extends LFrame implements LocaleListener {
|
||||||
public void libraryChanged(LibraryEvent e) {
|
public void libraryChanged(LibraryEvent e) {
|
||||||
if (e.getAction() == LibraryEvent.SET_NAME) {
|
if (e.getAction() == LibraryEvent.SET_NAME) {
|
||||||
computeTitle();
|
computeTitle();
|
||||||
|
} else if (e.getAction() == LibraryEvent.DIRTY_STATE) {
|
||||||
|
enableSave();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,6 +262,10 @@ public class Frame extends LFrame implements LocaleListener {
|
||||||
|
|
||||||
this.setSize(AppPreferences.WINDOW_WIDTH.get().intValue(),
|
this.setSize(AppPreferences.WINDOW_WIDTH.get().intValue(),
|
||||||
AppPreferences.WINDOW_HEIGHT.get().intValue());
|
AppPreferences.WINDOW_HEIGHT.get().intValue());
|
||||||
|
Point prefPoint = getInitialLocation();
|
||||||
|
if (prefPoint != null) {
|
||||||
|
this.setLocation(prefPoint);
|
||||||
|
}
|
||||||
this.setExtendedState(AppPreferences.WINDOW_STATE.get().intValue());
|
this.setExtendedState(AppPreferences.WINDOW_STATE.get().intValue());
|
||||||
|
|
||||||
menuListener.register(mainPanel);
|
menuListener.register(mainPanel);
|
||||||
|
@ -372,6 +379,7 @@ public class Frame extends LFrame implements LocaleListener {
|
||||||
s = StringUtil.format(Strings.get("titleFileKnown"), name);
|
s = StringUtil.format(Strings.get("titleFileKnown"), name);
|
||||||
}
|
}
|
||||||
this.setTitle(s);
|
this.setTitle(s);
|
||||||
|
myProjectListener.enableSave();
|
||||||
}
|
}
|
||||||
|
|
||||||
void viewAttributes(Tool newTool) {
|
void viewAttributes(Tool newTool) {
|
||||||
|
@ -436,6 +444,15 @@ public class Frame extends LFrame implements LocaleListener {
|
||||||
Dimension dim = getSize();
|
Dimension dim = getSize();
|
||||||
AppPreferences.WINDOW_WIDTH.set(Integer.valueOf(dim.width));
|
AppPreferences.WINDOW_WIDTH.set(Integer.valueOf(dim.width));
|
||||||
AppPreferences.WINDOW_HEIGHT.set(Integer.valueOf(dim.height));
|
AppPreferences.WINDOW_HEIGHT.set(Integer.valueOf(dim.height));
|
||||||
|
Point loc;
|
||||||
|
try {
|
||||||
|
loc = getLocationOnScreen();
|
||||||
|
} catch (IllegalComponentStateException e) {
|
||||||
|
loc = Projects.getLocation(this);
|
||||||
|
}
|
||||||
|
if (loc != null) {
|
||||||
|
AppPreferences.WINDOW_LOCATION.set(loc.x + "," + loc.y);
|
||||||
|
}
|
||||||
AppPreferences.WINDOW_LEFT_SPLIT.set(Double.valueOf(leftRegion.getFraction()));
|
AppPreferences.WINDOW_LEFT_SPLIT.set(Double.valueOf(leftRegion.getFraction()));
|
||||||
AppPreferences.WINDOW_MAIN_SPLIT.set(Double.valueOf(mainRegion.getFraction()));
|
AppPreferences.WINDOW_MAIN_SPLIT.set(Double.valueOf(mainRegion.getFraction()));
|
||||||
}
|
}
|
||||||
|
@ -468,4 +485,62 @@ public class Frame extends LFrame implements LocaleListener {
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Point getInitialLocation() {
|
||||||
|
String s = AppPreferences.WINDOW_LOCATION.get();
|
||||||
|
if (s == null) return null;
|
||||||
|
int comma = s.indexOf(',');
|
||||||
|
if (comma < 0) return null;
|
||||||
|
try {
|
||||||
|
int x = Integer.parseInt(s.substring(0, comma));
|
||||||
|
int y = Integer.parseInt(s.substring(comma + 1));
|
||||||
|
while (isProjectFrameAt(x, y)) {
|
||||||
|
x += 20;
|
||||||
|
y += 20;
|
||||||
|
}
|
||||||
|
Rectangle desired = new Rectangle(x, y, 50, 50);
|
||||||
|
|
||||||
|
int gcBestSize = 0;
|
||||||
|
Point gcBestPoint = null;
|
||||||
|
GraphicsEnvironment ge;
|
||||||
|
ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||||
|
for (GraphicsDevice gd : ge.getScreenDevices()) {
|
||||||
|
for (GraphicsConfiguration gc : gd.getConfigurations()) {
|
||||||
|
Rectangle gcBounds = gc.getBounds();
|
||||||
|
if (gcBounds.intersects(desired)) {
|
||||||
|
Rectangle inter = gcBounds.intersection(desired);
|
||||||
|
int size = inter.width * inter.height;
|
||||||
|
if (size > gcBestSize) {
|
||||||
|
gcBestSize = size;
|
||||||
|
int x2 = Math.max(gcBounds.x, Math.min(inter.x,
|
||||||
|
inter.x + inter.width - 50));
|
||||||
|
int y2 = Math.max(gcBounds.y, Math.min(inter.y,
|
||||||
|
inter.y + inter.height - 50));
|
||||||
|
gcBestPoint = new Point(x2, y2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (gcBestPoint != null) {
|
||||||
|
if (isProjectFrameAt(gcBestPoint.x, gcBestPoint.y)) {
|
||||||
|
gcBestPoint = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return gcBestPoint;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isProjectFrameAt(int x, int y) {
|
||||||
|
for (Project current : Projects.getOpenProjects()) {
|
||||||
|
Frame frame = current.getFrame();
|
||||||
|
if (frame != null) {
|
||||||
|
Point loc = frame.getLocationOnScreen();
|
||||||
|
int d = Math.abs(loc.x - x) + Math.abs(loc.y - y);
|
||||||
|
if (d <= 3) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ class MenuHelp extends JMenu implements ActionListener {
|
||||||
private JMenuItem library = new JMenuItem();
|
private JMenuItem library = new JMenuItem();
|
||||||
private JMenuItem about = new JMenuItem();
|
private JMenuItem about = new JMenuItem();
|
||||||
private HelpSet helpSet;
|
private HelpSet helpSet;
|
||||||
private String helpSetUrl;
|
private String helpSetUrl = "";
|
||||||
private JHelp helpComponent;
|
private JHelp helpComponent;
|
||||||
private LFrame helpFrame;
|
private LFrame helpFrame;
|
||||||
|
|
||||||
|
@ -77,11 +77,11 @@ class MenuHelp extends JMenu implements ActionListener {
|
||||||
|
|
||||||
private void loadBroker() {
|
private void loadBroker() {
|
||||||
String helpUrl = Strings.get("helpsetUrl");
|
String helpUrl = Strings.get("helpsetUrl");
|
||||||
if (helpUrl == null) helpUrl = "doc/en/doc.hs";
|
if (helpUrl == null) helpUrl = "doc/doc_en.hs";
|
||||||
if (helpSet == null || helpFrame == null || !helpUrl.equals(helpSetUrl)) {
|
if (helpSet == null || helpFrame == null || !helpUrl.equals(helpSetUrl)) {
|
||||||
ClassLoader cl = MenuHelp.class.getClassLoader();
|
ClassLoader loader = MenuHelp.class.getClassLoader();
|
||||||
try {
|
try {
|
||||||
URL hsURL = HelpSet.findHelpSet(cl, helpUrl);
|
URL hsURL = HelpSet.findHelpSet(loader, helpUrl);
|
||||||
if (hsURL == null) {
|
if (hsURL == null) {
|
||||||
disableHelp();
|
disableHelp();
|
||||||
JOptionPane.showMessageDialog(menubar.getParentWindow(),
|
JOptionPane.showMessageDialog(menubar.getParentWindow(),
|
||||||
|
@ -100,6 +100,7 @@ class MenuHelp extends JMenu implements ActionListener {
|
||||||
} else {
|
} else {
|
||||||
helpFrame.getContentPane().removeAll();
|
helpFrame.getContentPane().removeAll();
|
||||||
helpFrame.getContentPane().add(helpComponent);
|
helpFrame.getContentPane().add(helpComponent);
|
||||||
|
helpComponent.revalidate();
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
disableHelp();
|
disableHelp();
|
||||||
|
|
|
@ -400,7 +400,7 @@ public class Startup {
|
||||||
System.err.println(); //OK
|
System.err.println(); //OK
|
||||||
System.err.println(Strings.get("argOptionHeader")); //OK
|
System.err.println(Strings.get("argOptionHeader")); //OK
|
||||||
System.err.println(" " + Strings.get("argAccentsOption")); //OK
|
System.err.println(" " + Strings.get("argAccentsOption")); //OK
|
||||||
System.err.println(" " + Strings.get("argClearPropsOption")); //OK
|
System.err.println(" " + Strings.get("argClearOption")); //OK
|
||||||
System.err.println(" " + Strings.get("argEmptyOption")); //OK
|
System.err.println(" " + Strings.get("argEmptyOption")); //OK
|
||||||
System.err.println(" " + Strings.get("argGatesOption")); //OK
|
System.err.println(" " + Strings.get("argGatesOption")); //OK
|
||||||
System.err.println(" " + Strings.get("argHelpOption")); //OK
|
System.err.println(" " + Strings.get("argHelpOption")); //OK
|
||||||
|
|
|
@ -144,6 +144,8 @@ public class AppPreferences {
|
||||||
= create(new PrefMonitorInt("windowWidth", 640));
|
= create(new PrefMonitorInt("windowWidth", 640));
|
||||||
public static final PrefMonitor<Integer> WINDOW_HEIGHT
|
public static final PrefMonitor<Integer> WINDOW_HEIGHT
|
||||||
= create(new PrefMonitorInt("windowHeight", 480));
|
= create(new PrefMonitorInt("windowHeight", 480));
|
||||||
|
public static final PrefMonitor<String> WINDOW_LOCATION
|
||||||
|
= create(new PrefMonitorString("windowLocation", "0,0"));
|
||||||
public static final PrefMonitor<Double> WINDOW_MAIN_SPLIT
|
public static final PrefMonitor<Double> WINDOW_MAIN_SPLIT
|
||||||
= create(new PrefMonitorDouble("windowMainSplit", 0.25));
|
= create(new PrefMonitorDouble("windowMainSplit", 0.25));
|
||||||
public static final PrefMonitor<Double> WINDOW_LEFT_SPLIT
|
public static final PrefMonitor<Double> WINDOW_LEFT_SPLIT
|
||||||
|
|
|
@ -5,6 +5,7 @@ package com.cburch.logisim.proj;
|
||||||
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
|
import java.awt.Window;
|
||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
|
@ -12,6 +13,7 @@ import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
import com.cburch.logisim.file.Loader;
|
import com.cburch.logisim.file.Loader;
|
||||||
import com.cburch.logisim.gui.main.Frame;
|
import com.cburch.logisim.gui.main.Frame;
|
||||||
|
@ -21,6 +23,9 @@ import com.cburch.logisim.util.PropertyChangeWeakSupport;
|
||||||
public class Projects {
|
public class Projects {
|
||||||
public static final String projectListProperty = "projectList";
|
public static final String projectListProperty = "projectList";
|
||||||
|
|
||||||
|
private static final WeakHashMap<Window, Point> frameLocations
|
||||||
|
= new WeakHashMap<Window, Point>();
|
||||||
|
|
||||||
private static void projectRemoved(Project proj, Frame frame,
|
private static void projectRemoved(Project proj, Frame frame,
|
||||||
MyListener listener) {
|
MyListener listener) {
|
||||||
frame.removeWindowListener(listener);
|
frame.removeWindowListener(listener);
|
||||||
|
@ -40,6 +45,9 @@ public class Projects {
|
||||||
Frame frame = (Frame) event.getSource();
|
Frame frame = (Frame) event.getSource();
|
||||||
if ((frame.getExtendedState() & Frame.ICONIFIED) == 0) {
|
if ((frame.getExtendedState() & Frame.ICONIFIED) == 0) {
|
||||||
mostRecentFrame = frame;
|
mostRecentFrame = frame;
|
||||||
|
try {
|
||||||
|
frameLocations.put(frame, frame.getLocationOnScreen());
|
||||||
|
} catch (Throwable t) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,4 +167,9 @@ public class Projects {
|
||||||
public static void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
|
public static void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
|
||||||
propertySupport.removePropertyChangeListener(propertyName, listener);
|
propertySupport.removePropertyChangeListener(propertyName, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Point getLocation(Window win) {
|
||||||
|
Point ret = frameLocations.get(win);
|
||||||
|
return ret == null ? null : (Point) ret.clone();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import com.cburch.logisim.data.BitWidth;
|
||||||
import com.cburch.logisim.data.Bounds;
|
import com.cburch.logisim.data.Bounds;
|
||||||
import com.cburch.logisim.data.Direction;
|
import com.cburch.logisim.data.Direction;
|
||||||
import com.cburch.logisim.data.Value;
|
import com.cburch.logisim.data.Value;
|
||||||
|
import com.cburch.logisim.instance.Instance;
|
||||||
import com.cburch.logisim.instance.InstanceFactory;
|
import com.cburch.logisim.instance.InstanceFactory;
|
||||||
import com.cburch.logisim.instance.InstancePainter;
|
import com.cburch.logisim.instance.InstancePainter;
|
||||||
import com.cburch.logisim.instance.InstanceState;
|
import com.cburch.logisim.instance.InstanceState;
|
||||||
|
@ -115,4 +116,18 @@ public class Comparator extends InstanceFactory {
|
||||||
painter.drawPort(EQ, "=", Direction.WEST);
|
painter.drawPort(EQ, "=", Direction.WEST);
|
||||||
painter.drawPort(LT, "<", Direction.WEST);
|
painter.drawPort(LT, "<", Direction.WEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// methods for instances
|
||||||
|
//
|
||||||
|
@Override
|
||||||
|
protected void configureNewInstance(Instance instance) {
|
||||||
|
instance.addAttributeListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void instanceAttributeChanged(Instance instance, Attribute<?> attr) {
|
||||||
|
instance.fireInvalidated();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,6 +103,9 @@ public class BitExtender extends InstanceFactory {
|
||||||
protected void instanceAttributeChanged(Instance instance, Attribute<?> attr) {
|
protected void instanceAttributeChanged(Instance instance, Attribute<?> attr) {
|
||||||
if (attr == ATTR_TYPE) {
|
if (attr == ATTR_TYPE) {
|
||||||
configurePorts(instance);
|
configurePorts(instance);
|
||||||
|
instance.fireInvalidated();
|
||||||
|
} else {
|
||||||
|
instance.fireInvalidated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,12 @@ class XnorGate extends AbstractGate {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Value computeOutput(Value[] inputs, int numInputs, InstanceState state) {
|
protected Value computeOutput(Value[] inputs, int numInputs, InstanceState state) {
|
||||||
return GateFunctions.computeOddParity(inputs, numInputs).not();
|
Object behavior = state.getAttributeValue(GateAttributes.ATTR_XOR);
|
||||||
|
if (behavior == GateAttributes.XOR_ODD) {
|
||||||
|
return GateFunctions.computeOddParity(inputs, numInputs).not();
|
||||||
|
} else {
|
||||||
|
return GateFunctions.computeExactlyOne(inputs, numInputs).not();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -28,8 +28,15 @@ class XorGate extends AbstractGate {
|
||||||
@Override
|
@Override
|
||||||
public String getRectangularLabel(AttributeSet attrs) {
|
public String getRectangularLabel(AttributeSet attrs) {
|
||||||
if (attrs == null) return "";
|
if (attrs == null) return "";
|
||||||
|
boolean isOdd = false;
|
||||||
Object behavior = attrs.getValue(GateAttributes.ATTR_XOR);
|
Object behavior = attrs.getValue(GateAttributes.ATTR_XOR);
|
||||||
return behavior == GateAttributes.XOR_ODD ? "2k+1" : "1";
|
if (behavior == GateAttributes.XOR_ODD) {
|
||||||
|
Object inputs = attrs.getValue(GateAttributes.ATTR_INPUTS);
|
||||||
|
if (inputs == null || ((Integer) inputs).intValue() != 2) {
|
||||||
|
isOdd = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isOdd ? "2k+1" : "=1";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -380,7 +380,18 @@ public class SelectTool extends Tool {
|
||||||
if (state == MOVING && e.getKeyCode() == KeyEvent.VK_SHIFT) {
|
if (state == MOVING && e.getKeyCode() == KeyEvent.VK_SHIFT) {
|
||||||
handleMoveDrag(canvas, curDx, curDy, e.getModifiersEx());
|
handleMoveDrag(canvas, curDx, curDy, e.getModifiersEx());
|
||||||
} else {
|
} else {
|
||||||
processKeyEvent(canvas, e, KeyConfigurationEvent.KEY_PRESSED);
|
switch (e.getKeyCode()) {
|
||||||
|
case KeyEvent.VK_BACK_SPACE:
|
||||||
|
case KeyEvent.VK_DELETE:
|
||||||
|
if (!canvas.getSelection().isEmpty()) {
|
||||||
|
Action act = SelectionActions.clear(canvas.getSelection());
|
||||||
|
canvas.getProject().doAction(act);
|
||||||
|
e.consume();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
processKeyEvent(canvas, e, KeyConfigurationEvent.KEY_PRESSED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,11 +68,25 @@ public class MoveResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void print(PrintStream out) {
|
public void print(PrintStream out) {
|
||||||
|
boolean printed = false;
|
||||||
for (Component w : replacements.getAdditions()) {
|
for (Component w : replacements.getAdditions()) {
|
||||||
|
printed = true;
|
||||||
out.println("add " + w);
|
out.println("add " + w);
|
||||||
}
|
}
|
||||||
for (Component w : replacements.getRemovals()) {
|
for (Component w : replacements.getRemovals()) {
|
||||||
|
printed = true;
|
||||||
out.println("del " + w);
|
out.println("del " + w);
|
||||||
}
|
}
|
||||||
|
for (Component w : replacements.getReplacedComponents()) {
|
||||||
|
printed = true;
|
||||||
|
out.print("repl " + w + " by");
|
||||||
|
for (Component w2 : replacements.getComponentsReplacing(w)) {
|
||||||
|
out.print(" " + w2);
|
||||||
|
}
|
||||||
|
out.println();
|
||||||
|
}
|
||||||
|
if (!printed) {
|
||||||
|
out.println("no replacements");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue