Created
September 11, 2013 21:13
-
-
Save hetelek/6529869 to your computer and use it in GitHub Desktop.
An application which simulates a simple flip of a page in a book. Ported from C# - https://github.com/hetelek/BookFlip
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.awt.Color; | |
import java.awt.Graphics; | |
import java.awt.Graphics2D; | |
import java.awt.Point; | |
import java.awt.event.MouseAdapter; | |
import java.awt.event.MouseEvent; | |
import javax.swing.JFrame; | |
import javax.swing.JPanel; | |
// Ported from C# - https://github.com/hetelek/BookFlip | |
class MainForm | |
{ | |
public static void main(String[] args) | |
{ | |
JFrame frame = new JFrame("BookFlip"); | |
frame.add(new BookFlip()); | |
frame.setSize(200, 200); | |
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | |
frame.setVisible(true); | |
} | |
} | |
public class BookFlip extends JPanel | |
{ | |
static final boolean POLYGON_MODE = true; | |
MouseHandler mouseHandler = new MouseHandler(); | |
Point creaseOrigin, bottomRight, mousePoint; | |
int pageWidth, pageHeight; | |
boolean isBendingPaper; | |
public BookFlip() | |
{ | |
super(); | |
this.addMouseListener(mouseHandler); | |
this.addMouseMotionListener(mouseHandler); | |
} | |
private void redrawPanel(Graphics2D g) | |
{ | |
pageWidth = this.getWidth() / 2; | |
pageHeight = this.getHeight(); | |
bottomRight = new Point(this.getWidth(), pageHeight); | |
creaseOrigin = new Point(pageWidth, pageHeight); | |
drawPages(g); | |
} | |
private void drawPages(Graphics2D g) | |
{ | |
g.clearRect(0, 0, this.getWidth(), this.getHeight()); | |
g.setColor(Color.BLUE); | |
g.fillRect(0, 0, pageWidth, pageHeight); | |
g.setColor(Color.RED); | |
g.fillRect(pageWidth, 0, pageWidth, pageHeight); | |
} | |
@Override | |
public void paintComponent(Graphics g) | |
{ | |
super.paintComponent(g); | |
Graphics2D g2d = (Graphics2D)g; | |
this.redrawPanel(g2d); | |
if (isBendingPaper) | |
{ | |
double distance = getDistance(mousePoint, creaseOrigin); | |
if (distance > pageWidth) | |
mousePoint = getClosestPointOnCircle(mousePoint); | |
if (mousePoint.y >= pageHeight) | |
return; | |
Point midpoint = getMidpoint(mousePoint, bottomRight); | |
double m = -(double)(mousePoint.x - bottomRight.x) / (mousePoint.y - bottomRight.y); | |
double b = -((m * midpoint.x) - midpoint.y); | |
double x = (pageHeight - b) / m; | |
int yForEdgePoint = (int)(m * (pageWidth * 2) + b); | |
Point bottomPoint = new Point((int)x, pageHeight); | |
Point rightEdgePoint = new Point(pageWidth * 2, yForEdgePoint); | |
g2d.setColor(Color.GREEN); | |
if (POLYGON_MODE) | |
{ | |
int[] xPoints = { rightEdgePoint.x, mousePoint.x, bottomPoint.x }; | |
int[] yPoints = { rightEdgePoint.y, mousePoint.y, bottomPoint.y }; | |
g2d.fillPolygon(xPoints, yPoints, xPoints.length); | |
xPoints[1] = bottomRight.x; | |
yPoints[1] = bottomRight.y; | |
g2d.setColor(Color.YELLOW); | |
g2d.fillPolygon(xPoints, yPoints, xPoints.length); | |
} | |
else | |
{ | |
g2d.drawLine(rightEdgePoint.x, rightEdgePoint.y, bottomPoint.x, bottomPoint.y); | |
g2d.drawLine(mousePoint.x, mousePoint.y, bottomPoint.x, bottomPoint.y); | |
g2d.drawLine(mousePoint.x, mousePoint.y, rightEdgePoint.x, rightEdgePoint.y); | |
} | |
isBendingPaper = false; | |
} | |
} | |
private Point getMidpoint(Point p1, Point p2) | |
{ | |
int x = (p1.x + p2.x) / 2; | |
int y = (p1.y + p2.y) / 2; | |
return new Point(x, y); | |
} | |
private double getDistance(Point p1, Point p2) | |
{ | |
double x = Math.pow(p2.x - p1.x, 2); | |
double y = Math.pow(p2.y - p1.y, 2); | |
return Math.sqrt(x + y); | |
} | |
private Point getClosestPointOnCircle(Point p) | |
{ | |
// no idea how this works, source below | |
// http://stackoverflow.com/questions/300871/best-way-to-find-a-point-on-a-circle-closest-to-a-given-point | |
double vX = p.x - creaseOrigin.x; | |
double vY = p.y - creaseOrigin.y; | |
double magV = Math.sqrt(vX * vX + vY * vY); | |
double aX = creaseOrigin.x + vX / magV * pageWidth; | |
double aY = creaseOrigin.y + vY / magV * pageWidth; | |
return new Point((int)aX, (int)aY); | |
} | |
private class MouseHandler extends MouseAdapter | |
{ | |
@Override | |
public void mouseDragged(MouseEvent e) | |
{ | |
mousePoint = new Point(e.getX(), e.getY()); | |
isBendingPaper = true; | |
repaint(); | |
} | |
@Override | |
public void mouseReleased(MouseEvent e) | |
{ | |
mousePoint = new Point(e.getX(), e.getY()); | |
isBendingPaper = false; | |
repaint(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment