I have a class called Piece
, and many many subclasses of Piece
. I want to add an instance of every single subclass of Piece
(under the pieces
package) to my JTree
. Currently, I have this class with a huge function (well, 57 lines, but still) that increases in size every time I add functionality to my program.
My initial approach to this was "Hey, let's just use reflection or something to find out all of the classes under the package pieces
and add them to the tree!" but this SO question shot that down. My second, working approach is to add them all manually by hand. This seems like too much work though and it seems like there would be a better way to do this.
As always, miscellaneous comments on my code are very welcome.
initTree()
private void initTree(final UserInterface userInterface) {
tree = new JTree(createTree());
tree.setRootVisible(false);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.addTreeSelectionListener(new TreeSelectionListener(){
@Override
public void valueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)
tree.getLastSelectedPathComponent();
if (node == null){
return;
}
if (node.isLeaf() && node.getUserObject() instanceof Piece) {
Piece pieceCreated = (Piece) ((Piece)node.getUserObject()).getInstance();
userInterface.space.addPiece(pieceCreated);
}
}
});
add( new JScrollPane(tree), BorderLayout.CENTER );
}
createTree()
private DefaultMutableTreeNode createTree(){
//create the root node
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
//create the child nodes
DefaultMutableTreeNode gatesNode = new DefaultMutableTreeNode("Gates");
DefaultMutableTreeNode arithmeticNode = new DefaultMutableTreeNode("Arithmetic");
arithmeticNode.add(new DefaultMutableTreeNode(new Add(0,0)));
arithmeticNode.add(new DefaultMutableTreeNode(new Subtract(0,0)));
arithmeticNode.add(new DefaultMutableTreeNode(new Multiply(0,0)));
arithmeticNode.add(new DefaultMutableTreeNode(new Divide(0,0)));
arithmeticNode.add(new DefaultMutableTreeNode(new Modulo(0,0)));
arithmeticNode.add(new DefaultMutableTreeNode(new Random(0,0)));
gatesNode.add(arithmeticNode);
DefaultMutableTreeNode bitwiseNode = new DefaultMutableTreeNode("Bitwise");
bitwiseNode.add(new DefaultMutableTreeNode(new BitwiseAnd(0,0)));
bitwiseNode.add(new DefaultMutableTreeNode(new BitwiseNand(0,0)));
bitwiseNode.add(new DefaultMutableTreeNode(new BitwiseNor(0,0)));
bitwiseNode.add(new DefaultMutableTreeNode(new BitwiseNot(0,0)));
bitwiseNode.add(new DefaultMutableTreeNode(new BitwiseOr(0,0)));
bitwiseNode.add(new DefaultMutableTreeNode(new BitwiseXor(0,0)));
bitwiseNode.add(new DefaultMutableTreeNode(new BitwiseXnor(0,0)));
bitwiseNode.add(new DefaultMutableTreeNode(new BitwiseLeftshift(0,0)));
bitwiseNode.add(new DefaultMutableTreeNode(new BitwiseRightshift(0,0)));
gatesNode.add(bitwiseNode);
//etc with more subclasses of Piece
return root;
}
Piece.java
public abstract class Piece implements Serializable{
private static final long serialVersionUID = 2022414861350098747L;
private static final Color BACKGROUND_COLOR = new Color(200,200,200);
static final BasicStroke PORT_STROKE = new BasicStroke(1);
protected int x, y, width, height;
protected Input input;
protected Output output;
public Piece(int x, int y, int width, int height, int inputs, int outputs){
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.input = new Input(inputs, this);
this.output = new Output(outputs, this);
}
public abstract void draw(Graphics2D g);
public void drawBackground(Graphics2D g){
g.setColor(BACKGROUND_COLOR);
g.fillRoundRect(x, y, width, height,10,10);
input.draw(g);
output.draw(g);
}
public void drawConnections(Graphics2D g){
output.drawConnections(g);
}
public void connect(Piece other, int outputPort, int inputPort){
output.connect(other, outputPort, inputPort);
update();
}
public void disconnect(final int outputPort){
output.disconnect(outputPort);
update();
}
public void update(){
output.update();
}
public abstract Value send(int outputPort);
public abstract void recieve(int inputPort, Value v);
public abstract void doubleClicked();
public abstract Piece getInstance();
public String toString(){
return this.getClass().getSimpleName();
}
public void setPosition(final Point point) {
x = point.x;
y = point.y;
}
public boolean contains(final Point p){
return x < p.getX() &&
y < p.getY() &&
x + width > p.getX() &&
y + height > p.getY();
}
public Integer getOutputPortFromPoint(final Point p){
if(output.contains(p)){
if(output.getConnections().length == 0)
return null;
return output.getOuputFromY(p.y);
}
return null;
}
public Integer getInputPortFromPoint(final Point p){
if(input.contains(p)){
if(input.getConnections().length == 0){
return null;
}
return input.getInputFromY(p.y);
}
return null;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getWidth(){
return width;
}
public int getHeight(){
return height;
}
public Point getPointFromOutputPort(int portSelected) {
return output.getPointFromPort(portSelected);
}
}
Add.java (Example subclass of Piece
)
public class Add extends Piece{
private static final long serialVersionUID = -1786155220275379870L;
//v1 + v2 = v
private ValueInteger param1;
private ValueInteger param2;
private ValueInteger result;
private Title title;
public Add(int x, int y) {
super(x,y,150,75, 2, 1);
title = new Title("Add", this);
param1 = new ValueInteger(0);
result = new ValueInteger(0);
param2 = new ValueInteger(0);
}
@Override
public void draw(Graphics2D g) {
drawBackground(g);
title.draw(g);
g.setColor(Color.BLUE);
if(result != null)
g.drawString(result.toString(), x + 10, y + 20);
}
@Override
public Value send(int outputPort) {
return result;
}
@Override
public void recieve(int inputPort, Value v) {
if(inputPort == 0)
param1 = (ValueInteger) v;
else if (inputPort == 1)
param2 = (ValueInteger) v;
this.result = new ValueInteger(param1.add(param2));
}
@Override
public void doubleClicked() {
// TODO Auto-generated method stub
}
@Override
public Piece getInstance() {
return new Add(10,10);
}
}
Piece
? Perhaps you meanLogicComponent
? The fact that you have so many subclasses is a sign that maybe inheritance is not the best approach. There might be a violation of the Single Responsibility Principle. Or, maybe your application needs to be more data-driven than code-driven. – 200_success♦ Apr 30 '14 at 20:20