switched to java 7, using a single group instead of bank and board, moved target and source creation to separate methods, fixed crash when moving the only placed piece
M core/src/net/dermetfan/jigsawPuzzle/puzzle/JigsawPuzzle.java +37 -66
@@ 26,8 26,8 @@ import com.badlogic.gdx.scenes.scene2d.u
 import com.badlogic.gdx.scenes.scene2d.utils.DragAndDrop.Source;
 import com.badlogic.gdx.scenes.scene2d.utils.DragAndDrop.Target;
 import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
+import com.badlogic.gdx.utils.Array;
 import com.badlogic.gdx.utils.Pools;
-import com.badlogic.gdx.utils.SnapshotArray;
 import net.dermetfan.jigsawPuzzle.Constants;
 import net.dermetfan.jigsawPuzzle.utils.PolygonRegionDrawable;
 import net.dermetfan.utils.libgdx.math.GeometryUtils;

          
@@ 37,23 37,23 @@ import net.dermetfan.utils.libgdx.scene2
  *  @author dermetfan */
 public class JigsawPuzzle {
 
-	private final SnapshotArray<Piece> placedPieces, remainingPieces;
+	private final Array<Piece> placedPieces, remainingPieces;
 
 	public JigsawPuzzle() {
-		remainingPieces = new SnapshotArray<Piece>(Piece.class);
-		placedPieces = new SnapshotArray<Piece>(Piece.class);
+		remainingPieces = new Array<>(Piece.class);
+		placedPieces = new Array<>(Piece.class);
 	}
 
 	/** @param pieces the amount of pieces that will probably be in this puzzle */
 	public JigsawPuzzle(int pieces) {
-		remainingPieces = new SnapshotArray<Piece>(pieces);
-		placedPieces = new SnapshotArray<Piece>(pieces);
+		remainingPieces = new Array<>(pieces);
+		placedPieces = new Array<>(pieces);
 	}
 
 	/** @param pieces the {@link #remainingPieces remaining pieces} */
 	public JigsawPuzzle(Piece... pieces) {
-		remainingPieces = new SnapshotArray<Piece>(pieces);
-		placedPieces = new SnapshotArray<Piece>(pieces.length);
+		remainingPieces = new Array<>(pieces);
+		placedPieces = new Array<>(pieces.length);
 	}
 
 	/** Solves the puzzle by {@link #place(Piece) placing} all {@link #remainingPieces remaining pieces}.

          
@@ 117,43 117,33 @@ public class JigsawPuzzle {
 	}
 
 	/** @return the {@link #placedPieces} */
-	public Piece[] getPlacedPieces() {
-		placedPieces.end();
-		placedPieces.shrink();
-		return placedPieces.begin();
+	public Array<Piece> getPlacedPieces() {
+		return placedPieces;
 	}
 
 	/** @return the {@link #remainingPieces} */
-	public Piece[] getRemainingPieces() {
-		remainingPieces.end();
-		remainingPieces.shrink();
-		return remainingPieces.begin();
+	public Array<Piece> getRemainingPieces() {
+		return remainingPieces;
 	}
 
-	public void setUp(Group bank, Group board) {
-		setUp(bank, board, null);
-	}
-
-	public void setUp(final Group bank, final Group board, final Runnable solvedCallback) {
-		final DragAndDrop dnd = new DragAndDrop();
-
-		dnd.addSource(new Source(bank) {
+	public Source createSource(final Group board, final DragAndDrop dnd) {
+		return new Source(board) {
 			Payload payload = new Payload(); // the Payload object we're gonna use (to avoid having to create new ones all the time/GC)
 			Vector2 tmp = new Vector2();
 
 			@Override
 			public Payload dragStart(InputEvent event, float x, float y, int pointer) {
 				Actor actor = getActor().hit(x, y, true); // select actor under the mouse
-				if(actor == bank) // don't drag the board itself
+				if(actor == board) // don't drag the board itself
 					return null;
 
 				payload.setDragActor(actor);
 
 				// put the actor in the right position under the mouse
-				bank.localToDescendantCoordinates(actor, tmp.set(x, y));
+				board.localToDescendantCoordinates(actor, tmp.set(x, y));
 				dnd.setDragActorPosition(-tmp.x, -tmp.y + actor.getHeight());
 
-				tmp.set(actor.getX(), actor.getY()); // set tmp for dragStop (the current position, to return to it if it wasn't dragged on the  correctly)
+				tmp.set(actor.getX(), actor.getY()); // set tmp for dragStop (the current position, to return to it if it wasn't dragged on the board correctly)
 				return payload;
 			}
 

          
@@ 162,51 152,28 @@ public class JigsawPuzzle {
 				final Actor actor = payload.getDragActor();
 				if(actor.getParent() == null) { // move back to where the piece was dragged from
 					// put it on the stage in the correct position
-					bank.getStage().addActor(actor); // (could use something else instead of bank's stage)
-					bank.localToStageCoordinates(tmp);
+					board.getStage().addActor(actor); // (could use something else instead of board's stage)
+					board.localToStageCoordinates(tmp);
 					// move back
 					actor.addAction(Actions.sequence(Actions.moveTo(tmp.x, tmp.y, Constants.moveBackDuration), Actions.run(new Runnable() {
 						@Override
 						public void run() {
-							bank.addActor(actor);
-							// set position correctly on bank
-							bank.stageToLocalCoordinates(tmp);
+							board.addActor(actor);
+							// set position correctly on the board
+							board.stageToLocalCoordinates(tmp);
 							actor.setPosition(tmp.x, tmp.y);
 						}
 					})));
 				}
 			}
-		});
+		};
+	}
 
-		final Vector2 tmp = new Vector2();
-
-		dnd.addTarget(new Target(bank) { // add bank as target to be able to move pieces on it
+	public Target createTarget(final Group board, final Runnable solvedCallback) {
+		return new Target(board) {
 			@Override
 			public boolean drag(Source source, Payload payload, float x, float y, int pointer) {
-				return true; // return if the actor should be shown as accepted while dragging it over the bank
-			}
-
-			@Override
-			public void drop(Source source, Payload payload, float x, float y, int pointer) {
-				Actor dragged = payload.getDragActor();
-				bank.addActor(dragged); // add to bank again
-				// set to new coordinates
-				tmp.set(dragged.getX(), dragged.getY());
-				bank.stageToLocalCoordinates(tmp);
-				dragged.setPosition(tmp.x, tmp.y);
-			}
-		});
-
-		dnd.addTarget(new Target(board) { // add board as target to be able to actually solve the puzzle
-			@Override
-			public boolean drag(Source source, Payload payload, float x, float y, int pointer) {
-				Actor dragged = payload.getDragActor();
-				if(dragged instanceof Piece) {
-					Piece piece = (Piece) dragged;
-					if(isCorrectlyPlaced(piece, Constants.tolerance)) // if the piece is in correct relation to some (in this case the last) piece of the already places pieces, show it would be okay to place it here
-						return true;
-				}
-				return false;
+				return true;
 			}
 
 			@Override

          
@@ 215,12 182,15 @@ public class JigsawPuzzle {
 				Scene2DUtils.addAtStageCoordinates(dragged, board);
 				if(dragged instanceof Piece) {
 					Piece piece = (Piece) dragged;
-					place(piece); // snap it into its perfect position in relation to some already placed piece
-					if(isSolved() && solvedCallback != null)
-						solvedCallback.run();
+					if(isCorrectlyPlaced(piece, Constants.tolerance)) {
+						if(remainingPieces.contains(piece, true)) // TODO remove this condition (not the body!) when Puzzle doesn't know the difference between remaining and placed Pieces anymore
+							place(piece); // snap it into its perfect position in relation to some already placed piece
+						if(isSolved() && solvedCallback != null)
+							solvedCallback.run();
+					}
 				}
 			}
-		});
+		};
 	}
 
 	/** a piece on a {@link JigsawPuzzle}

          
@@ 250,8 220,9 @@ public class JigsawPuzzle {
 		@Override
 		public Actor hit(float x, float y, boolean touchable) {
 			Actor hit = super.hit(x, y, touchable);
-			if(hit == this) {
-				tmpPolygon.setVertices(((PolygonRegionDrawable) getDrawable()).getRegion().getVertices());
+			PolygonRegionDrawable drawable = getDrawable() instanceof PolygonRegionDrawable ? (PolygonRegionDrawable) getDrawable() : null;
+			if(hit == this && drawable != null) {
+				tmpPolygon.setVertices(drawable.getRegion().getVertices());
 				tmpPolygon.setPosition(-slotX, -slotY);
 				if(!tmpPolygon.contains(x / getWidth() * GeometryUtils.width(tmpPolygon.getVertices()), y / getHeight() * GeometryUtils.height(tmpPolygon.getVertices())))
 					return null;

          
M core/src/net/dermetfan/jigsawPuzzle/screens/PlayScreen.java +7 -6
@@ 26,6 26,7 @@ import com.badlogic.gdx.scenes.scene2d.u
 import com.badlogic.gdx.scenes.scene2d.ui.Skin;
 import com.badlogic.gdx.scenes.scene2d.ui.Table;
 import com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;
+import com.badlogic.gdx.scenes.scene2d.utils.DragAndDrop;
 import com.badlogic.gdx.utils.viewport.ScreenViewport;
 import net.dermetfan.jigsawPuzzle.Assets;
 import net.dermetfan.jigsawPuzzle.Constants;

          
@@ 78,20 79,21 @@ public class PlayScreen extends ScreenAd
 		dialog.setResizable(true);
 
 		final JigsawPuzzle puzzle = new JigsawPuzzle();
-		final WidgetGroup bank = new WidgetGroup(); // the group that pieces will be dragged from
 		final WidgetGroup board = new WidgetGroup(); // the group that pieces will be dropped on
 		float nextX = 0, tallest = 0;
 		for(FileHandle psh : Assets.puzzlePSHs(level)) { // set up the pieces on the bank
 			Piece piece = new Piece(new PolygonRegionDrawable(Assets.manager.get(psh.path(), PolygonRegion.class)));
 			puzzle.addRemaining(piece);
-			bank.addActor(piece);
+			board.addActor(piece);
 			piece.setX(nextX);
 			nextX += piece.getWidth();
 			if(piece.getHeight() > tallest)
 				tallest = piece.getHeight();
 		}
 
-		puzzle.setUp(bank, board, new Runnable() {
+		DragAndDrop dnd = new DragAndDrop();
+		dnd.addSource(puzzle.createSource(board, dnd));
+		dnd.addTarget(puzzle.createTarget(board, new Runnable() {
 			@Override
 			public void run() {
 				dialog.hide();

          
@@ 109,10 111,9 @@ public class PlayScreen extends ScreenAd
 
 				}, "Puzzle solved!", "", "Play again? Enter level name");
 			}
-		});
+		}));
 
-		dialog.getContentTable().add(board).expand().fill().row();
-		dialog.getContentTable().add(bank).expandX().fill().minSize(nextX, tallest);
+		dialog.getContentTable().add(board).expand().fill().minSize(nextX, tallest);
 
 		dialog.show(stage);
 	}