this is confusing, I wrote this a while ago, and it didn't work right, I am almost sure that it is a simple small error somewhere that I am just missing. when i wrote it I didn't think that it would be good to post it here because of the amount of code, I know that most people don't want to sift through pages of code. I have come to the conclusion to post it and see if I get any replies.
it works, occasionally, and sometimes doesn't, and i cannot explain why
I think that the problem may be that the method i wrote to snap the gates to the grid may not be consistent, i did test it, but that doesn't mean that I got a thorough sampling.
the problem may also lie in where the inputs and outputs check to see what they are touching and what they need to update.
a lot of the files are short, much of the code is actually to draw the gates, so it may not be as hard to read if the ".draw(Graphics)" methods are skipped. i now am realizing that all the casting looks a bit dumb, maybe i should revise Gate to be abstract to avoid it all, but I originally did it to make it clear, but it makes it a bit harder to understand =(
there is a lot of code... i recommend the toggle plain text to shorten it.
Main.java
import java.awt.* ;
import java.awt.event.* ;
import java.awt.geom.* ;
import javax.swing.* ;
import javax.swing.event.* ;
public class Main extends JFrame implements ActionListener {
PaintSurface ps = new PaintSurface ( ) ;
JMenuItem closeButton = new JMenuItem ( "Close" ) ;
JMenuItem moveButton = new JMenuItem ( "Move" ) ;
JMenuItem inputButton = new JMenuItem ( "Add Input" ) ;
JMenuItem wireButton = new JMenuItem ( "Add Wire" ) ;
JMenuItem andButton = new JMenuItem ( "Add And Gate" ) ;
JMenuItem orButton = new JMenuItem ( "Add Or Gate" ) ;
JMenuItem notButton = new JMenuItem ( "Add Not Gate" ) ;
JMenuItem delButton = new JMenuItem ( "Delete Gate" ) ;
public void actionPerformed ( ActionEvent e ) {
if ( e.getSource ( ) == closeButton ) {
System.exit ( 0 ) ;
} else if ( e.getSource ( ) == moveButton ) {
ps.setAddType ( PaintSurface.ADD_NONE ) ;
} else if ( e.getSource ( ) == wireButton ) {
ps.setAddType ( PaintSurface.ADD_WIRE ) ;
} else if ( e.getSource ( ) == andButton ) {
ps.setAddType ( PaintSurface.ADD_AND ) ;
} else if ( e.getSource ( ) == orButton ) {
ps.setAddType ( PaintSurface.ADD_OR ) ;
} else if ( e.getSource ( ) == notButton ) {
ps.setAddType ( PaintSurface.ADD_NOT ) ;
} else if ( e.getSource ( ) == delButton ) {
ps.setAddType ( PaintSurface.ADD_DELETE ) ;
} else if ( e.getSource ( ) == inputButton ) {
ps.setAddType ( PaintSurface.ADD_INPUT ) ;
}
}
public Main ( ) {
closeButton.addActionListener ( this ) ;
moveButton.addActionListener ( this ) ;
inputButton.addActionListener ( this ) ;
wireButton.addActionListener ( this ) ;
andButton.addActionListener ( this ) ;
orButton.addActionListener ( this ) ;
notButton.addActionListener ( this ) ;
delButton.addActionListener ( this ) ;
JMenuBar mb = new JMenuBar ( ) ;
JMenu m = new JMenu ( "File" ) ;
m.add ( closeButton ) ;
mb.add ( m ) ;
m = new JMenu ( "Edit" ) ;
m.add ( moveButton ) ;
m.add ( inputButton ) ;
m.add ( wireButton ) ;
m.add ( andButton ) ;
m.add ( orButton ) ;
m.add ( notButton ) ;
m.add ( delButton ) ;
mb.add ( m ) ;
setJMenuBar ( mb ) ;
this.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE ) ;
this.add ( ps ) ;
this.pack ( ) ;
this.setVisible ( true ) ;
}
public static void main ( String [ ] args ) {
new Main ( ) ;
}
}
PaintSurface.java
import java.awt.* ;
import java.awt.event.* ;
import java.awt.geom.* ;
import javax.swing.* ;
import javax.swing.event.* ;
import java.util.ArrayList ;
public class PaintSurface extends JComponent implements MouseListener ,
MouseMotionListener {
public Main m ;
public static final int ADD_NONE = - 1 ;
public static final int ADD_INPUT = 0 ;
public static final int ADD_WIRE = 1 ;
public static final int ADD_AND = 2 ;
public static final int ADD_OR = 3 ;
public static final int ADD_NOT = 4 ;
public static final int ADD_DELETE = 5 ;
public static final double gridsize = Math.min ( Gate.width , Gate.height ) / 4 ;
private int addType = ADD_NONE ;
ArrayList < Gate > gates = new ArrayList < Gate > ( ) ;
ArrayList < UserInput > inputs = new ArrayList < UserInput > ( ) ;
Gate selected ;
UserInput selected2 ;
int wireSel = 0 ;
public void setAddType ( int type ) {
addType = type ;
}
public void mouseEntered ( MouseEvent e ) {}
public void mouseExited ( MouseEvent e ) {}
public void mousePressed ( MouseEvent e ) {
switch ( addType ) {
case ADD_NONE :
select ( e ) ;
break ;
case ADD_INPUT :
inputs.add ( new UserInput ( toGrid ( e.getX ( ) ) , toGrid ( e
.getY ( ) ) , false , this ) ) ;
selected = null ;
selected2 = inputs.get ( inputs.size ( ) - 1 ) ;
break ;
case ADD_WIRE :
gates.add ( new WIRE ( toGrid ( e.getX ( ) ) , toGrid ( e
.getY ( ) ) , toGrid ( e.getX ( ) ) , toGrid ( e
.getY ( ) ) , this ) ) ;
wireSel = 2 ;
selected = gates.get ( gates.size ( ) - 1 ) ;
selected2 = null ;
break ;
case ADD_AND :
gates.add ( new AND ( toGrid ( e.getX ( ) ) , toGrid ( e
.getY ( ) ) , this ) ) ;
selected = gates.get ( gates.size ( ) - 1 ) ;
selected2 = null ;
break ;
case ADD_OR :
gates.add ( new OR ( toGrid ( e.getX ( ) ) ,
toGrid ( e.getY ( ) ) , this ) ) ;
selected = gates.get ( gates.size ( ) - 1 ) ;
selected2 = null ;
break ;
case ADD_NOT :
gates.add ( new NOT ( toGrid ( e.getX ( ) ) , toGrid ( e
.getY ( ) ) , this ) ) ;
selected = gates.get ( gates.size ( ) - 1 ) ;
selected2 = null ;
break ;
case ADD_DELETE :
select ( e ) ;
if ( selected != null ) {
gates.remove ( selected ) ;
selected = null ;
}
if ( selected2 != null ) {
inputs.remove ( selected2 ) ;
selected2 = null ;
}
break ;
default :
System.out.println ( "THIS SHOULD\'t HAPPEN" ) ;
}
repaint ( ) ;
}
public void mouseClicked ( MouseEvent e ) {
for ( UserInput ui : inputs ) {
if ( ui.contains ( e.getX ( ) , e.getY ( ) ) ) {
ui.doChange ( ) ;
}
}
repaint();
}
public void mouseReleased ( MouseEvent e ) {
selected = null ;
selected2 = null ;
repaint ( ) ;
}
public void mouseMoved ( MouseEvent e ) {}
public void mouseDragged ( MouseEvent e ) {
if ( selected != null ) {
if ( selected instanceof AND ) {
( ( AND ) selected ).setXY ( toGrid ( e.getX ( ) ) , toGrid ( e
.getY ( ) ) ) ;
} else if ( selected instanceof OR ) {
( ( OR ) selected ).setXY ( toGrid ( e.getX ( ) ) , toGrid ( e
.getY ( ) ) ) ;
} else if ( selected instanceof WIRE ) {
WIRE w = ( WIRE ) selected ;
if ( wireSel == 1 ) {
w.setXY ( toGrid ( e.getX ( ) ) , toGrid ( e.getY ( ) ) ) ;
} else {
w.setXY2 ( toGrid ( e.getX ( ) ) , toGrid ( e.getY ( ) ) ) ;
}
} else if ( selected instanceof NOT ) {
( ( NOT ) selected ).setXY ( toGrid ( e.getX ( ) ) , toGrid ( e
.getY ( ) ) ) ;
}
} else if ( selected2 != null ) {
selected2.x = toGrid ( e.getX ( ) ) ;
selected2.y = toGrid ( e.getY ( ) ) ;
}
repaint ( ) ;
}
public PaintSurface ( ) {
this.setPreferredSize ( new Dimension ( ( int ) ( 40 * gridsize ) ,
( int ) ( 40 * gridsize ) ) ) ;
this.addMouseListener ( this ) ;
this.addMouseMotionListener ( this ) ;
}
public void paint ( Graphics g ) {
Graphics2D g2 = ( Graphics2D ) g ;
g2.setColor ( new Color ( 255 , 0 , 0 ) ) ;
g2.setStroke ( new BasicStroke ( 3 , BasicStroke.CAP_BUTT ,
BasicStroke.JOIN_ROUND ) ) ;
for ( Gate gate : gates ) {
gate.draw ( g2 ) ;
}
for ( UserInput ui : inputs ) {
ui.draw ( g2 ) ;
}
doLogic ( ) ;
}
public double toGrid ( double d ) {
double grido2 = gridsize / 2 ;
double div = d / gridsize ;
double d2 ;
if ( div == ( ( int ) div ) ) {
d2 = d ;
} else {
double d1 = div - ( int ) div ;
d1 *= gridsize ;
if ( d1 < grido2 ) {
d2 = d - d1 ;
} else {
d2 = d + ( gridsize - d1 ) ;
}
}
return d2 ;
}
public void select ( MouseEvent e ) {
boolean found = false ;
for ( Gate g : gates ) {
if ( g instanceof AND ) {
if ( ( ( AND ) g ).contains ( e.getX ( ) , e.getY ( ) ) ) {
found = true ;
selected = g ;
break ;
}
} else if ( g instanceof OR ) {
if ( ( ( OR ) g ).contains ( e.getX ( ) , e.getY ( ) ) ) {
found = true ;
selected = g ;
break ;
}
} else if ( g instanceof WIRE ) {
if ( ( ( WIRE ) g ).contains ( e.getX ( ) , e.getY ( ) ) ) {
found = true ;
wireSel = ( ( WIRE ) g ).which ( e.getX ( ) , e.getY ( ) ) ;
selected = g ;
break ;
}
} else if ( g instanceof NOT ) {
if ( ( ( NOT ) g ).contains ( e.getX ( ) , e.getY ( ) ) ) {
found = true ;
selected = g ;
break ;
}
}
}
if ( ! found ) {
selected = null ;
boolean found2 = false ;
for ( UserInput ui : inputs ) {
if ( ui.contains ( e.getX ( ) , e.getY ( ) ) ) {
found2 = true ;
selected2 = ui ;
break ;
}
}
if ( ! found2 ) {
selected2 = null ;
}
}
}
public void doLogic ( ) {
for ( UserInput ui : inputs ) {
ui.fillList ( ) ;
ui.changeInputs ( ) ;
}
for ( Gate gate : gates ) {
if ( gate instanceof AND ) {
( ( AND ) gate ).doFigure ( ) ;
( ( AND ) gate ).out.fillList ( ) ;
( ( AND ) gate ).out.changeInputs ( ) ;
} else if ( gate instanceof OR ) {
( ( OR ) gate ).doFigure ( ) ;
( ( OR ) gate ).out.fillList ( ) ;
( ( OR ) gate ).out.changeInputs ( ) ;
} else if ( gate instanceof WIRE ) {
( ( WIRE ) gate ).doFigure ( ) ;
( ( WIRE ) gate ).out.fillList ( ) ;
( ( WIRE ) gate ).out.changeInputs ( ) ;
} else if ( gate instanceof NOT ) {
( ( NOT ) gate ).doFigure ( ) ;
( ( NOT ) gate ).out.fillList ( ) ;
( ( NOT ) gate ).out.changeInputs ( ) ;
}
}
}
}
Gate.java
import java.awt.* ;
import java.awt.event.* ;
import java.awt.geom.* ;
import javax.swing.* ;
import javax.swing.event.* ;
public class Gate {
double x ;
double y ;
static double width = 50 ;
static double height = 50 ;
public Gate ( double x , double y , PaintSurface ps ) {
this.x = x ;
this.y = y ;
}
public void draw ( Graphics2D g ) {
g.draw ( new Rectangle2D.Double ( x , y , width , height ) ) ;
g.drawString ( "NONE!" , ( int ) ( x + 1 ) , ( int ) ( y + 1 ) ) ;
}
public boolean contains(double x, double y){
return ((y>=this.y&&y<=this.y+height)&&(x>=this.x&&x<=this.x+width));
}
public void setXY ( double x , double y ) {}
public void doFigure ( ) {}
}
GateInput.java
import java.awt.* ;
import java.awt.event.* ;
import java.awt.geom.* ;
import javax.swing.* ;
import javax.swing.event.* ;
public class GateInput {
double x ;
double y ;
double len = PaintSurface.gridsize ;
boolean value ;
public GateInput ( double x , double y , boolean value ) {
this.x = x ;
this.y = y ;
this.value = value ;
}
public void draw ( Graphics2D g ) {
if ( value ) {
g.setColor ( new Color ( 0 , 255 , 0 ) ) ;
} else {
g.setColor ( new Color ( 255 , 0 , 0 ) ) ;
}
g.draw ( new Line2D.Double ( x , y , x - len , y ) ) ;
g.fill ( new Ellipse2D.Double ( x - len - 4 , y - 4 , 8 , 8 ) ) ;
}
public boolean contains ( double x , double y ) {
return ( ( x > ( this.x - len ) && x < ( this.x ) ) && ( y > ( this.y - len ) && y < ( this.y + len ) ) ) ;
}
public boolean connectsWith ( GateOutput go ) {
return ( ( ( x - len ) == ( go.x + len ) ) && ( y == go.y ) ) ;
}
}
GateOutput.java
import java.awt.* ;
import java.awt.event.* ;
import java.awt.geom.* ;
import javax.swing.* ;
import javax.swing.event.* ;
import java.util.ArrayList ;
public class GateOutput {
double x ;
double y ;
double len = PaintSurface.gridsize ;
boolean value ;
ArrayList < GateInput > connections = new ArrayList < GateInput > ( ) ;
PaintSurface ps ;
public GateOutput ( double x , double y , boolean value , PaintSurface ps ) {
this.x = x ;
this.y = y ;
this.value = value ;
this.ps = ps ;
}
public void fillList ( ) {
connections.clear ( ) ;
for ( Gate gate : ps.gates ) {
if ( gate instanceof AND ) {
AND a = ( AND ) gate ;
if ( a.in.connectsWith ( this ) ) {
connections.add ( a.in ) ;
} else if ( a.in2.connectsWith ( this ) ) {
connections.add ( a.in2 ) ;
}
} else if ( gate instanceof OR ) {
OR o = ( OR ) gate ;
if ( o.in.connectsWith ( this ) ) {
connections.add ( o.in ) ;
} else if ( o.in2.connectsWith ( this ) ) {
connections.add ( o.in2 ) ;
}
} else if ( gate instanceof NOT ) {
NOT n = ( NOT ) gate ;
if ( n.in.connectsWith ( this ) ) {
connections.add ( n.in ) ;
}
} else if ( gate instanceof WIRE ) {
WIRE w = ( WIRE ) gate ;
if ( w.in.connectsWith ( this ) ) {
connections.add ( w.in ) ;
}
}
}
}
public void changeInputs ( ) {
for ( GateInput i : connections ) {
i.value = value ;
}
}
public boolean contains ( double x , double y ) {
return ( ( x > ( this.x ) && x < ( this.x + len ) ) && ( y > ( this.y - len ) && y < ( this.y + len ) ) ) ;
}
public void draw ( Graphics2D g ) {
if ( value ) {
g.setColor ( new Color ( 0 , 255 , 0 ) ) ;
} else {
g.setColor ( new Color ( 255 , 0 , 0 ) ) ;
}
g.draw ( new Line2D.Double ( x , y , x + len , y ) ) ;
g.fill ( new Ellipse2D.Double ( x + len - 4 , y - 4 , 8 , 8 ) ) ;
}
}
AND.java
import java.awt.* ;
import java.awt.event.* ;
import java.awt.geom.* ;
import javax.swing.* ;
import javax.swing.event.* ;
public class AND extends Gate {
public GateInput in ;
public GateInput in2 ;
public GateOutput out ;
public AND ( double x , double y , PaintSurface ps ) {
super ( x , y , ps ) ;
in = new GateInput ( x , y + PaintSurface.gridsize , false ) ;
in2 = new GateInput ( x , y + 3 * PaintSurface.gridsize , false ) ;
out = new GateOutput ( x + width , y + 2 * PaintSurface.gridsize ,
false , ps ) ;
}
public void draw ( Graphics2D g ) {
Ellipse2D.Double front1 = new Ellipse2D.Double ( ) ;
Rectangle2D.Double back1 = new Rectangle2D.Double ( ) ;
front1.setFrame ( x , y , width , height ) ;
back1.setFrame ( x , y , width / 2 , height ) ;
Area front = new Area ( front1 ) ;
Area back = new Area ( back1 ) ;
front.add ( back ) ;
Color pc = g.getColor ( ) ;
g.setColor ( new Color ( 128 , 128 , 128 ) ) ;
g.draw ( front ) ;
in.draw ( g ) ;
in2.draw ( g ) ;
out.draw ( g ) ;
g.setColor ( pc ) ;
}
public void doFigure ( ) {
out.value = ( in.value && in2.value ) ;
}
public void setXY ( double x , double y ) {
this.x = x ;
this.y = y ;
in.x = x ;
in2.x = x ;
in.y = y + PaintSurface.gridsize ;
in2.y = y + 3 * PaintSurface.gridsize ;
out.x = x + width ;
out.y = y + 2 * PaintSurface.gridsize ;
}
}
OR.java
import java.awt.* ;
import java.awt.event.* ;
import java.awt.geom.* ;
import javax.swing.* ;
import javax.swing.event.* ;
public class OR extends Gate {
public GateInput in ;
public GateInput in2 ;
public GateOutput out ;
public OR ( double x , double y , PaintSurface ps ) {
super ( x , y , ps ) ;
in = new GateInput ( x , y + PaintSurface.gridsize , false ) ;
in2 = new GateInput ( x , y + 3 * PaintSurface.gridsize , false ) ;
out = new GateOutput ( x + width , y + 2 * PaintSurface.gridsize ,
false , ps ) ;
}
public void draw ( Graphics2D g ) {
Ellipse2D.Double front1 = new Ellipse2D.Double ( ) ;
Rectangle2D.Double back1 = new Rectangle2D.Double ( ) ;
Ellipse2D.Double back2 = new Ellipse2D.Double ( ) ;
front1.setFrame ( x , y , width , height ) ;
back1.setFrame ( x , y , width / 2 , height ) ;
back2.setFrame ( x - ( width / 4 ) , y , ( width / 2 ) , height ) ;
Area front = new Area ( front1 ) ;
Area backa = new Area ( back1 ) ;
Area backa2 = new Area ( back2 ) ;
front.add ( backa ) ;
front.subtract ( backa2 ) ;
Color pc = g.getColor ( ) ;
g.setColor ( new Color ( 128 , 128 , 128 ) ) ;
g.draw ( front ) ;
in.draw ( g ) ;
in2.draw ( g ) ;
out.draw ( g ) ;
g.setColor ( pc ) ;
}
public void doFigure ( ) {
out.value = ( in.value || in2.value ) ;
}
public void setXY ( double x , double y ) {
this.x = x ;
this.y = y ;
in.x = x ;
in2.x = x ;
in.y = y + PaintSurface.gridsize ;
in2.y = y + 3 * PaintSurface.gridsize ;
out.x = x + width ;
out.y = y + 2 * PaintSurface.gridsize ;
}
}
WIRE.java
import java.awt.* ;
import java.awt.geom.* ;
public class WIRE extends Gate {
double x2 ;
double y2 ;
GateInput in ;
GateOutput out ;
public WIRE ( double x , double y , double x2 , double y2 , PaintSurface ps ) {
super ( x + PaintSurface.gridsize , y , ps ) ;
this.x2 = x2 - PaintSurface.gridsize ;
this.y2 = y2 ;
in = new GateInput ( x + PaintSurface.gridsize , y , false ) ;
out = new GateOutput ( x2 - PaintSurface.gridsize , y2 , false , ps ) ;
}
public void draw ( Graphics2D g ) {
if ( in.value ) {
g.setColor ( new Color ( 0 , 255 , 0 ) ) ;
} else {
g.setColor ( new Color ( 255 , 0 , 0 ) ) ;
}
g.draw ( new Line2D.Double ( x , y , x2 , y2 ) ) ;
in.draw ( g ) ;
out.draw ( g ) ;
}
public boolean contains(double x,double y){
return in.contains(x,y)||out.contains(x,y);
}
public int which(double x,double y){
if(in.contains(x,y)){
return 1;
} else {
return 2;
}
}
public void setXY ( double x , double y ) {
this.x = x + PaintSurface.gridsize ;
this.y = y ;
in.x = x + PaintSurface.gridsize ;
in.y = y ;
}
public void setXY2 ( double x2 , double y2 ) {
this.x2 = x2 - PaintSurface.gridsize ;
this.y2 = y2 ;
out.x = x2 - PaintSurface.gridsize ;
out.y = y2 ;
}
public void doFigure ( ) {
out.value = in.value ;
}
}
NOT.java
import java.awt.* ;
import java.awt.geom.* ;
public class NOT extends Gate {
GateInput in ;
GateOutput out ;
public NOT ( double x , double y , PaintSurface ps ) {
super ( x , y , ps ) ;
in = new GateInput ( x , y + 2 * PaintSurface.gridsize , false ) ;
out = new GateOutput ( x + width , y + 2 * PaintSurface.gridsize ,
true , ps ) ;
}
public void draw ( Graphics2D g ) {
g.draw ( new Line2D.Double ( x , y , x + width - PaintSurface.gridsize ,
y + height / 2 ) ) ;
g.draw ( new Line2D.Double ( x , y , x , y + height ) ) ;
g.draw ( new Line2D.Double ( x , y + height , x + width
- PaintSurface.gridsize , y + height / 2 ) ) ;
g.draw ( new Ellipse2D.Double ( x + 3 * PaintSurface.gridsize , y + 1.5
* PaintSurface.gridsize , PaintSurface.gridsize ,
PaintSurface.gridsize ) ) ;
in.draw ( g ) ;
out.draw ( g ) ;
}
public void setXY ( double x , double y ) {
this.x = x ;
this.y = y ;
in.x = x ;
in.y = y + 2 * PaintSurface.gridsize ;
out.x = x + width ;
out.y = y + 2 * PaintSurface.gridsize ;
}
public void doFigure ( ) {
out.value = ! in.value ;
}
}
UserInput.java
import java.awt.* ;
import java.awt.event.* ;
import java.awt.geom.* ;
import javax.swing.* ;
import javax.swing.event.* ;
import java.util.ArrayList ;
public class UserInput extends GateOutput {
public UserInput ( double x , double y , boolean value , PaintSurface ps ) {
super(x,y,value,ps);
}
public void draw(Graphics2D g){
super.draw(g);
if(value){
g.drawString("H",(int)(x-PaintSurface.gridsize),(int)(y-5));
} else {
g.drawString("L",(int)(x-PaintSurface.gridsize),(int)(y-5));
}
}
public void doChange(){
value=!value;
}
}
Thanks for putting up with that large amount of code. any advice would be appreciated, it's not important that this be done quickly, I just would like to be able to call this a completed project at some point.