Skip to content

Commit

Permalink
Added source code
Browse files Browse the repository at this point in the history
  • Loading branch information
defano committed Jan 16, 2017
1 parent 1c261f1 commit da6b42f
Show file tree
Hide file tree
Showing 57 changed files with 3,652 additions and 18 deletions.
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
*.class

# Package Files #
*.jar
*.war
*.ear

.idea/*
*.iml
target/*
36 changes: 18 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@ A rudimentary toolkit for incorporating [MacPaint](https://en.wikipedia.org/wiki

## Paint tools

Tool | Description
----------------| -------------
![Airbrush](icons/spraypaint.png) Airbrush | Paints translucent color or texture onto the canvas.
![Curve](icons/curve.png) Curve | Draws quadratic (Bezier) curves by clicking to specify points on the curve.
![Eraser](icons/eraser.png) Eraser | Removes paint from the canvas by restoring affected pixels to their fully-transparent state.
![Fill](icons/fill.png) Fill | Shades an enclosed area with paint using a [flood-fill](https://en.wikipedia.org/wiki/Flood_fill) algorithm.
![Lasso](icons/lasso.png) Lasso | Define a free-form selection boundary ([marching ants](https://en.wikipedia.org/wiki/Marching_ants)) for clearing or moving paint.
![Line](icons/line.png) Line | Draws straight lines; hold `shift` to restrict lines to 15-degree angles.
![Oval](icons/oval.png) Oval | Draws filled or outlined oval shapes; hold `shift` to constrain boundary to circle.
![Paintbrush](icons/paintbrush.png) Paintbrush | Draws paint on the canvas (using configurable stroke and color/texture).
![Pencil](icons/pencil.png) Pencil | Draws a free-form, narrow black path on the canvas.
![Polygon](icons/polygon.png) Polygon | Draws filled or outlined irregular polygons by clicking to specify points. Double-click to complete the polygon; press `esc` to keep only the lines visible; hold `shift` to restrict line angles to 15 degree multiples.
![Rectangle](icons/rectangle.png) Rectangle | Draws filled or outlined rectangles on the canvas; hold `shift` to constrain boundary to a square.
![Round Rect](icons/roundrect.png) Round Rect | Draws filled or outlined round-rectangles on the canvas.
![Selection](icons/selection.png) Selection | Define a selection rectangle ([marching ants](https://en.wikipedia.org/wiki/Marching_ants)) whose underlying graphic can be moved or cleared (press `delete`)
![Shape](icons/shape.png) Shape | Draws filled or outlined regular polygons (i.e., shapes--triangles, squares, polygons, hexagons, etc.)
![Text](icons/text.png) Text | Draws rasterized text (of a configurable font, size and style) on the canvas. Text remains editable until user clicks away.
| Tool | Description
| ----------------| -------------
![Airbrush](icons/spraypaint.png) | Airbrush | Paints translucent color or texture onto the canvas.
![Curve](icons/curve.png) | Curve | Draws quadratic (Bezier) curves by clicking to specify points on the curve.
![Eraser](icons/eraser.png) | Eraser | Removes paint from the canvas by restoring affected pixels to their fully-transparent state.
![Fill](icons/fill.png) | Fill | Shades an enclosed area with paint using a [flood-fill](https://en.wikipedia.org/wiki/Flood_fill) algorithm.
![Lasso](icons/lasso.png) | Lasso | Define a free-form selection boundary ([marching ants](https://en.wikipedia.org/wiki/Marching_ants)) for clearing or moving paint.
![Line](icons/line.png) | Line | Draws straight lines; hold `shift` to restrict lines to 15-degree angles.
![Oval](icons/oval.png) | Oval | Draws filled or outlined oval shapes; hold `shift` to constrain boundary to circle.
![Paintbrush](icons/paintbrush.png) | Paintbrush | Draws paint on the canvas (using configurable stroke and color/texture).
![Pencil](icons/pencil.png) | Pencil | Draws a free-form, narrow black path on the canvas.
![Polygon](icons/polygon.png) | Polygon | Draws filled or outlined irregular polygons by clicking to specify points. Double-click to complete the polygon; press `esc` to keep only the lines visible; hold `shift` to restrict line angles to 15 degree multiples.
![Rectangle](icons/rectangle.png) | Rectangle | Draws filled or outlined rectangles on the canvas; hold `shift` to constrain boundary to a square.
![Round Rect](icons/roundrect.png) | Round Rect | Draws filled or outlined round-rectangles on the canvas.
![Selection](icons/selection.png) | Selection | Define a selection rectangle ([marching ants](https://en.wikipedia.org/wiki/Marching_ants)) whose underlying graphic can be moved or cleared (press `delete`)
![Shape](icons/shape.png) | Shape | Draws filled or outlined regular polygons (i.e., shapes--triangles, squares, polygons, hexagons, etc.)
![Text](icons/text.png) | Text | Draws rasterized text (of a configurable font, size and style) on the canvas. Text remains editable until user clicks away.

(There's also an "Arrow" tool that functions as a no-op that does not modify the canvas in any way.)

Expand Down Expand Up @@ -201,7 +201,7 @@ Tool Base | Description

#### How can I layer canvases atop one another, or place other UI elements (like buttons and fields) on top of the painted graphics?

Place the canvas(es) and/or other UI components in a `LayeredPane`. Use the `LayeredPane` to control z-order.
Place the canvas(es) and/or other UI components in a `LayeredPane`. Use the `LayeredPane` to control z-order.

#### What about vector graphic tools (i.e., "draw" apps)?

Expand Down
19 changes: 19 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>

<packaging>jar</packaging>
<groupId>com.defano</groupId>
<artifactId>jmonet</artifactId>
<version>0.0.1</version>

</project>
122 changes: 122 additions & 0 deletions src/main/java/com/defano/jmonet/canvas/BasicCanvas.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package com.defano.jmonet.canvas;

import com.defano.jmonet.canvas.surface.AbstractSurface;
import com.defano.jmonet.model.Provider;

import java.awt.*;
import java.awt.image.BufferedImage;

public class BasicCanvas extends AbstractSurface implements Canvas {

private Point imageLocation = new Point(0, 0);
private Provider<Double> scale = new Provider<>(1.0);
private Provider<Integer> gridSpacing = new Provider<>(1);

private BufferedImage image;
private BufferedImage scratch;

public BasicCanvas() {
this(null);
}

public BasicCanvas(BufferedImage initialImage) {

if (initialImage == null) {
image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
} else {
image = initialImage;
}

scratch = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
}

public void clearCanvas() {
Graphics2D g2 = (Graphics2D) getScratchImage().getGraphics();
g2.setColor(Color.WHITE);
g2.fillRect(0, 0, getWidth(), getHeight());
commit(AlphaComposite.getInstance(AlphaComposite.DST_OUT, 1.0f));
}

protected void overlayImage(BufferedImage source, BufferedImage destination, AlphaComposite composite) {

Graphics2D g2d = (Graphics2D) destination.getGraphics();
g2d.setComposite(composite);
g2d.drawImage(source, 0,0, null);
g2d.dispose();
}

public BufferedImage getCanvasImage() {
return image;
}

public BufferedImage getScratchImage() {
return scratch;
}

@Override
public void setCanvasImage(BufferedImage image) {
this.image = image;
}

@Override
public void setScratchImage(BufferedImage image) {
this.scratch = image;
}

public void commit() {
commit(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
}

/**
* Copies the image contents of the scratch buffer to the Canvas' image.
*/
public void commit(AlphaComposite composite) {
BufferedImage scratchImage = getScratchImage();
BufferedImage canvasImage = getCanvasImage();

overlayImage(scratchImage, canvasImage, composite);
fireObservers(this, scratchImage, canvasImage);

clearScratch();
invalidateCanvas();
}

/**
* Creates a clean scratch buffer (replacing all pixels in the graphics context with transparent pixels).
*/
public void clearScratch() {
scratch = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
}

@Override
public void setImageLocation(Point location) {
imageLocation = location;
}

@Override
public Point getImageLocation() {
return imageLocation;
}

@Override
public Provider<Double> getScaleProvider() {
return scale;
}

@Override
public void setGridSpacing(int grid) {
this.gridSpacing.set(grid);
}

@Override
public Provider<Integer> getGridSpacingProvider() {
return gridSpacing;
}

@Override
public void setScale(double scale) {
this.scale.set(scale);
invalidateCanvas();
}

}
19 changes: 19 additions & 0 deletions src/main/java/com/defano/jmonet/canvas/Canvas.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.defano.jmonet.canvas;

import com.defano.jmonet.canvas.surface.PaintableSurface;

import java.awt.*;

public interface Canvas extends PaintableSurface {
boolean isVisible();

void setCursor(Cursor cursor);

void addObserver(CanvasCommitObserver observer);
boolean removeObserver(CanvasCommitObserver observer);

void invalidateCanvas();

void commit();
void commit(AlphaComposite composite);
}
14 changes: 14 additions & 0 deletions src/main/java/com/defano/jmonet/canvas/CanvasCommitObserver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.defano.jmonet.canvas;

import java.awt.image.BufferedImage;

public interface CanvasCommitObserver {
/**
* Fires when an new shape or image is committed from scratch onto the canvas.
*
* @param canvas The canvas on which the commit is occurring.
* @param committedElement An image representing just the change being committed.
* @param canvasImage The resulting canvas image (including the committed change)
*/
void onCommit(Canvas canvas, BufferedImage committedElement, BufferedImage canvasImage);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.defano.jmonet.canvas;

import java.awt.event.*;

public interface CanvasInteractionObserver extends KeyListener {

/**
* Invoked when the mouse button has been clicked (pressed
* and released) on the canvas.
*/
void mouseClicked(MouseEvent e, int scaleX, int scaleY);

/**
* Invoked when a mouse button has been pressed on a component.
*/
void mousePressed(MouseEvent e, int scaleX, int scaleY);

/**
* Invoked when a mouse button has been released on a component.
*/
void mouseReleased(MouseEvent e, int scaleX, int scaleY);

/**
* Invoked when the mouse enters a component.
*/
void mouseEntered(MouseEvent e, int scaleX, int scaleY);

/**
* Invoked when the mouse exits a component.
*/
void mouseExited(MouseEvent e, int scaleX, int scaleY);

/**
* Invoked when a mouse button is pressed on a component and then
* dragged. <code>MOUSE_DRAGGED</code> events will continue to be
* delivered to the component where the drag originated until the
* mouse button is released (regardless of whether the mouse position
* is within the bounds of the component).
* <p>
* Due to platform-dependent Drag&amp;Drop implementations,
* <code>MOUSE_DRAGGED</code> events may not be delivered during a native
* Drag&amp;Drop operation.
*/
void mouseDragged(MouseEvent e, int scaleX, int scaleY);

/**
* Invoked when the mouse cursor has been moved onto a component
* but no buttons have been pushed.
*/
void mouseMoved(MouseEvent e, int scaleX, int scaleY);
}
19 changes: 19 additions & 0 deletions src/main/java/com/defano/jmonet/canvas/JFXCanvasNode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.defano.jmonet.canvas;

import javafx.application.Platform;
import javafx.embed.swing.SwingNode;

public class JFXCanvasNode extends SwingNode {

private final BasicCanvas canvas;

public JFXCanvasNode(BasicCanvas canvas) {
this.canvas = canvas;
Platform.runLater(() -> JFXCanvasNode.super.setContent(canvas));
}

public Canvas getCanvas() {
return canvas;
}

}
Loading

0 comments on commit da6b42f

Please sign in to comment.