Skip to content

Commit

Permalink
Feature/reactivex (#11)
Browse files Browse the repository at this point in the history
* Initial conversion to ReactiveX

* Flood-fill performance improvements

* Buffer depth bug fixes

* Minor API changes

* Readme improvements

* Javadoc updates
  • Loading branch information
defano authored Feb 2, 2018
1 parent 7f02dfd commit c8614fe
Show file tree
Hide file tree
Showing 235 changed files with 3,403 additions and 1,874 deletions.
78 changes: 43 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ An easy-to-use toolkit for incorporating paint tools similar to [MacPaint](https

## Features

* Offers a standard suite of paint tools with common modifier-key constraints (e.g., hold shift to snap lines to nearest 15-degree angle).
* Painting canvas supports undo and redo operations on all paint tool changes, plus cut, copy and paste integration with the system clipboard.
* Includes a variety of image transform tools like scale, rotate, shear, perspective and projection, plus the ability to adjust color depth, transparency and brightness.
* Standard suite of paint tools providing common modifier-key constraints (e.g., hold shift to snap lines to nearest 15-degree angle).
* Canvas supports undo and redo operations on all paint tool changes, plus cut, copy and paste integration with the system clipboard.
* Includes a variety of image transform tools like scale, rotate, shear, perspective and projection, plus the ability to adjust color depth, transparency and brightness.
* Painted images are zoomable via the Magnifier tool (displayed within a scrollable pane), and tools can be snapped to a grid.
* Lightweight toolkit integrates easily into Swing and JavaFX applications.
* All operations are backed by a standard Java `BufferedImage`; easy to import existing images and save changes.
* Lightweight toolkit integrates easily into Swing and JavaFX applications and utilizes [ReactiveX](https://github.com/ReactiveX/RxJava) for observables.
* All operations are backed by a standard Java `BufferedImage` making it easy to import and export graphics.

## Paint Tools

Expand Down Expand Up @@ -44,7 +44,7 @@ Icon | Tool | Description
![Slant](icons/slant.png) | Slant | Define a selection, then use the drag handles to apply an affine shear transform to the selected graphic.
![Scale](icons/scale.png) | Scale | Define a selection, then expand or shrink the selected image by dragging a handle. Hold shift to maintain selection's original aspect ratio.
![Projection](icons/distort.png) | Projection | Define a selection, then use the drag handles to project the image onto the geometry of an arbitrary quadrilateral.
![perspective](icons/perspective.png) | Perspective | Define a selection, then use the drag handles to warp the image onto an isosceles trapezoid, providing the effect of the left or right side of the image appearing nearer or farther from the viewer.
![Perspective](icons/perspective.png) | Perspective | Define a selection, then use the drag handles to warp the image onto an isosceles trapezoid, providing the effect of the left or right side of the image appearing nearer or farther from the viewer.
![Rubber Sheet](icons/distort.png) | Rubber Sheet | Similar to the projection transform, but utilizes a "rubber sheet" algorithm that preserves relative position over linearity.

#### Static transforms
Expand Down Expand Up @@ -76,7 +76,7 @@ JMonet is published to Maven Central; include the library in your Maven project'
<dependency>
<groupId>com.defano.jmonet</groupId>
<artifactId>jmonet</artifactId>
<version>0.1.0</version>
<version>0.2.0</version>
</dependency>
```

Expand All @@ -88,7 +88,7 @@ repositories {
}
dependencies {
compile 'com.defano.jmonet:jmonet:0.1.0'
compile 'com.defano.jmonet:jmonet:0.2.0'
}
```

Expand Down Expand Up @@ -156,6 +156,41 @@ activeTool.deactivate();

There's no technical limitation that prevents multiple tools from being active on the same canvas at the same time, but that's not usually desired behavior in a paint program.

### Migrating from older versions

JMonet versions 0.2.0 and later utilize [ReactiveX](https://github.com/ReactiveX/RxJava) for observables instead of the `Provider` classes that were present in earlier versions. Here's what you need to do to upgrade:

1. **Change API signatures:** JMonet APIs ending with `Provider` now end with `Observable`. For example, `JMonetCanvas#getGridSpacingProvider()` is now `JMonetCanvas#getGridSpacingObservable()`.
3. **Use `BehvaiorSubject` in lieu of `Provider`:** RxJava's `BehaviorSubject` is roughly equivalent to JMonet's former `Provider` class:

To create an observable property (that is, one that a paint tool or canvas will respond to dynamically):
```
BehaviorSubject<BasicStroke> lineStrokeSubject = BehaviorSubject<>.createDefault(new BasicStroke(1));
```

To make the paint tool observe changes to it:
```
PaintToolBuilder.create(PaintToolType.LINE)
.withStrokePaintObservable(lineStrokeSubject)
...
.build();
```

To change an `BehaviorSubject` that's providing an attribute to a tool or canvas:
```
lineStrokeSubject.onNext(new BasicStroke(2))
```

To listen to changes of a provided attribute:
```
lineStrokeSubject.subscribe(stroke -> System.out.println("Change: " + stroke.getLineWidth()));
```

To derive an observable attribute for another attribute:
```
Observable<Boolean> isSinglePxStroke = lineStrokeSubject.map(stroke -> stroke.getLineWidth() == 1);
```

## Implement cut, copy and paste

JMonet makes it easy to integrate cut, copy and paste functions into your app that utilize the operating system's clipboard so that you can copy and paste graphics from within your own application or between other applications on your system.
Expand Down Expand Up @@ -238,33 +273,6 @@ The code below provides an implementation that cuts, copies and pastes the activ
```

## Tool and canvas attribute providers

When building your paint application, you'll likely need to observe and/or make changes to various canvas and tool attributes from several locations in your codebase (i.e., change and observe the paint color from the menu, palette, picker dialogs, etc).

To simplify this, attributes are wrapped in a `Provider` class. A Provider is an extension to Java's `Observable` with a bit of syntactical sugar to support one-liner lambda expressions and to derive observable attributes from other attributes.

For example, create a provider of paint and inject it into the tool (you might keep this provider around globally to be shared across all tools whose paint you want to change):

```
Provider<Paint> paintProvider = new Provider(Color.BLACK);
activeTool.setFillPaintProvider(paintProvider);
```

Now, you can observe changes to the tool's paint:

```
strokePaintProvider.addObserver((o, newValue) -> System.out.println("Got new paint: " + newValue));
```

More importantly, you can derive new Providers that listen for changes to an existing Provider and transform them into a different type. This is useful, for example, for checkmarking menu items or highlighting palette tools based on a selection.

```
ImmutableProvider<Boolean> isBlackColorSelected = ImmutableProvider.derivedFrom(strokePaintProvider, p -> p == Color.BLACK);
```

An `ImmutableProvider` is one whose underlying value cannot be changed. In this example, it wouldn't make sense to mutate `isBlackSelected` directly; its value follows the color provided by `strokePaintProvider`.

## Frequently asked questions

#### I don't get it. Doesn't Java's `Graphics` already let me draw stuff?
Expand Down
10 changes: 4 additions & 6 deletions javadoc/allclasses-frame.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_131) on Sun Jan 14 09:36:42 CST 2018 -->
<!-- Generated by javadoc (1.8.0_131) on Thu Feb 01 20:02:34 CST 2018 -->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>All Classes (JMonet 0.1.0 API)</title>
<meta name="date" content="2018-01-14">
<title>All Classes (JMonet 0.2.0 API)</title>
<meta name="date" content="2018-02-01">
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
<script type="text/javascript" src="script.js"></script>
</head>
Expand All @@ -24,6 +24,7 @@ <h1 class="bar">All&nbsp;Classes</h1>
<li><a href="com/defano/jmonet/tools/AirbrushTool.html" title="class in com.defano.jmonet.tools" target="classFrame">AirbrushTool</a></li>
<li><a href="com/defano/jmonet/tools/ArrowTool.html" title="class in com.defano.jmonet.tools" target="classFrame">ArrowTool</a></li>
<li><a href="com/defano/jmonet/tools/brushes/BasicBrush.html" title="enum in com.defano.jmonet.tools.brushes" target="classFrame">BasicBrush</a></li>
<li><a href="com/defano/jmonet/algo/BoundaryFunction.html" title="interface in com.defano.jmonet.algo" target="classFrame"><span class="interfaceName">BoundaryFunction</span></a></li>
<li><a href="com/defano/jmonet/clipboard/CanvasClipboardActionListener.html" title="class in com.defano.jmonet.clipboard" target="classFrame">CanvasClipboardActionListener</a></li>
<li><a href="com/defano/jmonet/canvas/observable/CanvasCommitObserver.html" title="interface in com.defano.jmonet.canvas.observable" target="classFrame"><span class="interfaceName">CanvasCommitObserver</span></a></li>
<li><a href="com/defano/jmonet/clipboard/CanvasFocusDelegate.html" title="interface in com.defano.jmonet.clipboard" target="classFrame"><span class="interfaceName">CanvasFocusDelegate</span></a></li>
Expand All @@ -43,7 +44,6 @@ <h1 class="bar">All&nbsp;Classes</h1>
<li><a href="com/defano/jmonet/tools/FreeformShapeTool.html" title="class in com.defano.jmonet.tools" target="classFrame">FreeformShapeTool</a></li>
<li><a href="com/defano/jmonet/tools/util/Geometry.html" title="class in com.defano.jmonet.tools.util" target="classFrame">Geometry</a></li>
<li><a href="com/defano/jmonet/algo/GrayscaleQuantizer.html" title="class in com.defano.jmonet.algo" target="classFrame">GrayscaleQuantizer</a></li>
<li><a href="com/defano/jmonet/model/ImmutableProvider.html" title="class in com.defano.jmonet.model" target="classFrame">ImmutableProvider</a></li>
<li><a href="com/defano/jmonet/canvas/JFXPaintCanvasNode.html" title="class in com.defano.jmonet.canvas" target="classFrame">JFXPaintCanvasNode</a></li>
<li><a href="com/defano/jmonet/canvas/JMonetCanvas.html" title="class in com.defano.jmonet.canvas" target="classFrame">JMonetCanvas</a></li>
<li><a href="com/defano/jmonet/tools/LassoTool.html" title="class in com.defano.jmonet.tools" target="classFrame">LassoTool</a></li>
Expand All @@ -66,8 +66,6 @@ <h1 class="bar">All&nbsp;Classes</h1>
<li><a href="com/defano/jmonet/tools/PolygonTool.html" title="class in com.defano.jmonet.tools" target="classFrame">PolygonTool</a></li>
<li><a href="com/defano/jmonet/algo/Projection.html" title="class in com.defano.jmonet.algo" target="classFrame">Projection</a></li>
<li><a href="com/defano/jmonet/tools/ProjectionTool.html" title="class in com.defano.jmonet.tools" target="classFrame">ProjectionTool</a></li>
<li><a href="com/defano/jmonet/model/Provider.html" title="class in com.defano.jmonet.model" target="classFrame">Provider</a></li>
<li><a href="com/defano/jmonet/model/ProviderTransform.html" title="interface in com.defano.jmonet.model" target="classFrame"><span class="interfaceName">ProviderTransform</span></a></li>
<li><a href="com/defano/jmonet/algo/QuantizationFunction.html" title="interface in com.defano.jmonet.algo" target="classFrame"><span class="interfaceName">QuantizationFunction</span></a></li>
<li><a href="com/defano/jmonet/tools/RectangleTool.html" title="class in com.defano.jmonet.tools" target="classFrame">RectangleTool</a></li>
<li><a href="com/defano/jmonet/tools/RotateTool.html" title="class in com.defano.jmonet.tools" target="classFrame">RotateTool</a></li>
Expand Down
10 changes: 4 additions & 6 deletions javadoc/allclasses-noframe.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc (1.8.0_131) on Sun Jan 14 09:36:42 CST 2018 -->
<!-- Generated by javadoc (1.8.0_131) on Thu Feb 01 20:02:34 CST 2018 -->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>All Classes (JMonet 0.1.0 API)</title>
<meta name="date" content="2018-01-14">
<title>All Classes (JMonet 0.2.0 API)</title>
<meta name="date" content="2018-02-01">
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
<script type="text/javascript" src="script.js"></script>
</head>
Expand All @@ -24,6 +24,7 @@ <h1 class="bar">All&nbsp;Classes</h1>
<li><a href="com/defano/jmonet/tools/AirbrushTool.html" title="class in com.defano.jmonet.tools">AirbrushTool</a></li>
<li><a href="com/defano/jmonet/tools/ArrowTool.html" title="class in com.defano.jmonet.tools">ArrowTool</a></li>
<li><a href="com/defano/jmonet/tools/brushes/BasicBrush.html" title="enum in com.defano.jmonet.tools.brushes">BasicBrush</a></li>
<li><a href="com/defano/jmonet/algo/BoundaryFunction.html" title="interface in com.defano.jmonet.algo"><span class="interfaceName">BoundaryFunction</span></a></li>
<li><a href="com/defano/jmonet/clipboard/CanvasClipboardActionListener.html" title="class in com.defano.jmonet.clipboard">CanvasClipboardActionListener</a></li>
<li><a href="com/defano/jmonet/canvas/observable/CanvasCommitObserver.html" title="interface in com.defano.jmonet.canvas.observable"><span class="interfaceName">CanvasCommitObserver</span></a></li>
<li><a href="com/defano/jmonet/clipboard/CanvasFocusDelegate.html" title="interface in com.defano.jmonet.clipboard"><span class="interfaceName">CanvasFocusDelegate</span></a></li>
Expand All @@ -43,7 +44,6 @@ <h1 class="bar">All&nbsp;Classes</h1>
<li><a href="com/defano/jmonet/tools/FreeformShapeTool.html" title="class in com.defano.jmonet.tools">FreeformShapeTool</a></li>
<li><a href="com/defano/jmonet/tools/util/Geometry.html" title="class in com.defano.jmonet.tools.util">Geometry</a></li>
<li><a href="com/defano/jmonet/algo/GrayscaleQuantizer.html" title="class in com.defano.jmonet.algo">GrayscaleQuantizer</a></li>
<li><a href="com/defano/jmonet/model/ImmutableProvider.html" title="class in com.defano.jmonet.model">ImmutableProvider</a></li>
<li><a href="com/defano/jmonet/canvas/JFXPaintCanvasNode.html" title="class in com.defano.jmonet.canvas">JFXPaintCanvasNode</a></li>
<li><a href="com/defano/jmonet/canvas/JMonetCanvas.html" title="class in com.defano.jmonet.canvas">JMonetCanvas</a></li>
<li><a href="com/defano/jmonet/tools/LassoTool.html" title="class in com.defano.jmonet.tools">LassoTool</a></li>
Expand All @@ -66,8 +66,6 @@ <h1 class="bar">All&nbsp;Classes</h1>
<li><a href="com/defano/jmonet/tools/PolygonTool.html" title="class in com.defano.jmonet.tools">PolygonTool</a></li>
<li><a href="com/defano/jmonet/algo/Projection.html" title="class in com.defano.jmonet.algo">Projection</a></li>
<li><a href="com/defano/jmonet/tools/ProjectionTool.html" title="class in com.defano.jmonet.tools">ProjectionTool</a></li>
<li><a href="com/defano/jmonet/model/Provider.html" title="class in com.defano.jmonet.model">Provider</a></li>
<li><a href="com/defano/jmonet/model/ProviderTransform.html" title="interface in com.defano.jmonet.model"><span class="interfaceName">ProviderTransform</span></a></li>
<li><a href="com/defano/jmonet/algo/QuantizationFunction.html" title="interface in com.defano.jmonet.algo"><span class="interfaceName">QuantizationFunction</span></a></li>
<li><a href="com/defano/jmonet/tools/RectangleTool.html" title="class in com.defano.jmonet.tools">RectangleTool</a></li>
<li><a href="com/defano/jmonet/tools/RotateTool.html" title="class in com.defano.jmonet.tools">RotateTool</a></li>
Expand Down
Loading

0 comments on commit c8614fe

Please sign in to comment.