Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement DefaultFrame type class #153

Merged
merged 5 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
- name: Setup Java (temurin@8)
id: setup-java-temurin-8
if: matrix.java == 'temurin@8'
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 8
Expand Down Expand Up @@ -79,7 +79,7 @@ jobs:

- name: Upload target directories
if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main')
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: target-${{ matrix.os }}-${{ matrix.java }}-${{ matrix.scala }}
path: targets.tar
Expand All @@ -102,7 +102,7 @@ jobs:
- name: Setup Java (temurin@8)
id: setup-java-temurin-8
if: matrix.java == 'temurin@8'
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 8
Expand All @@ -113,7 +113,7 @@ jobs:
run: sbt +update

- name: Download target directories (3)
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: target-${{ matrix.os }}-${{ matrix.java }}-3

Expand Down Expand Up @@ -163,7 +163,7 @@ jobs:
- name: Setup Java (temurin@8)
id: setup-java-temurin-8
if: matrix.java == 'temurin@8'
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 8
Expand Down Expand Up @@ -195,7 +195,7 @@ jobs:
- name: Setup Java (temurin@8)
id: setup-java-temurin-8
if: matrix.java == 'temurin@8'
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 8
Expand All @@ -208,7 +208,7 @@ jobs:
- name: Setup Java (temurin@11)
id: setup-java-temurin-11
if: matrix.java == 'temurin@11'
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 11
Expand Down
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ ThisBuild / developers := List(
// true by default, set to false to publish to s01.oss.sonatype.org
ThisBuild / tlSonatypeUseLegacyHost := true

lazy val scala3 = "3.3.1"
lazy val scala3 = "3.3.3"

ThisBuild / crossScalaVersions := List(scala3)
ThisBuild / scalaVersion := scala3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package effect
import cats.effect.IO
import doodle.algebra.Algebra
import doodle.algebra.Picture

import java.awt.image.BufferedImage

/** The BufferedImageWriter type represent the ability to encode an image as a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import cats.effect.unsafe.IORuntime
import doodle.algebra.Algebra
import doodle.algebra.Picture
import doodle.effect.BufferedImageWriter

import java.awt.image.BufferedImage

trait BufferedImageWriterSyntax {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,16 @@
* limitations under the License.
*/

package doodle
package effect
package doodle.effect

import doodle.algebra.Algebra

/** The `DefaultRenderer` typeclass is a `Renderer` that has a reasonable
* default frame.
/** The `DefaultFrame` typeclass provides a reasonable default `Frame`. This is
* a convenience for `Renderer` or `Writer` users that don't want to have to
* create a `Frame` instance.
*/
trait DefaultRenderer[+Alg <: Algebra, Frame, Canvas]
extends Renderer[Alg, Frame, Canvas] {
trait DefaultFrame[Frame] {
def default: Frame
}
object DefaultRenderer {
def apply[Alg <: Algebra, Frame, Canvas](implicit
renderer: DefaultRenderer[Alg, Frame, Canvas]
): DefaultRenderer[Alg, Frame, Canvas] = renderer
object DefaultFrame {
def apply[Frame](implicit frame: DefaultFrame[Frame]): DefaultFrame[Frame] =
frame
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ import cats.effect.IO
import cats.effect.unsafe.IORuntime
import doodle.algebra.Algebra
import doodle.algebra.Picture
import doodle.effect.DefaultRenderer
import doodle.effect.DefaultFrame
import doodle.effect.Renderer

/** Rendering works differently on different platforms. The Javascript runtime
* must render asynchronously. The JVM runtime can render asychronously or
* sychronously. However, rendering in a Swing / Java2D context takes places on
* a daemon thread. This means the JVM will exit if this is the only thread
* running. The implication is that short Doodle program that does not block
* running. The implication is that a short Doodle program that does not block
* the main thread waiting for the Swing thread to complete will usually exit
* before the output appears. Therefore, at least in the common case of calling
* `draw`, rendering should be synchronous on the JVM.
Expand All @@ -48,7 +48,8 @@ trait AbstractRendererSyntax {
* options for this `Renderer`.
*/
def draw[Frame, Canvas]()(implicit
renderer: DefaultRenderer[Alg, Frame, Canvas],
renderer: Renderer[Alg, Frame, Canvas],
frame: DefaultFrame[Frame],
r: IORuntime
): Unit =
runIO(drawToIO())
Expand All @@ -73,10 +74,11 @@ trait AbstractRendererSyntax {
* `Frame` for this `Renderer`.
*/
def drawToIO[Frame, Canvas]()(implicit
renderer: DefaultRenderer[Alg, Frame, Canvas]
renderer: Renderer[Alg, Frame, Canvas],
frame: DefaultFrame[Frame]
): IO[A] =
renderer
.canvas(renderer.default)
.canvas(frame.default)
.flatMap(canvas => drawWithCanvasToIO(canvas))

/** Create an effect that, when run, will draw the `Picture` using the given
Expand Down
11 changes: 9 additions & 2 deletions docs/src/pages/effect/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Effects

A picture is a description of what should be drawn. An effect carries out the description by, for example, drawing a picture to the screen. Another example includes converting a picture to a different type or saving it to a file which is managed by a special class of effects called `Writers`.
A picture is a description of what should be drawn. An effect carries out the description by, for example, drawing a picture to the screen or writing it to a file. Effects are implemented as type classes and defined in the @:api(doodle.effect) package. Users will not usually interact directly with effects, but instead work with the syntax defined for them. For example calling `draw` on a `Picture` is syntax that uses the @:api(doodle.effect.Renderer) effect.

Effects are defined in the @:api(doodle.effect.index) package. All effects have @:api(doodle.syntax.index) that makes them easier to use. You should not have to use effects directly unless you are extending Doodle.
The main effects are:

* @:api(doodle.effect.Renderer), which draws a `Picture` to the screen.
* @:api(doodle.effect.Writer), is a marker trait for effects that convert a `Picture` to some other type or write it to a file.
* @:api(doodle.effect.FileWriter), for writing to a `File`.
* @:api(doodle.effect.Base64Writer), for writing to a base 64 encoded value.
* @:api(doodle.effect.BufferedImageWriter), for writing to a `BufferedImage` on the JVM.
* @:api(doodle.effect.DefaultFrame), not strictly an effect but a useful for utility to obtain a default frame instance. This makes other operations more convenient, as the user does not need to specify a frame.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package image
package syntax

import cats.effect.unsafe.IORuntime
import doodle.effect.DefaultRenderer
import doodle.effect.DefaultFrame
import doodle.effect.Renderer
import doodle.language.Basic
import doodle.syntax.AbstractRendererSyntax
Expand All @@ -34,7 +34,8 @@ abstract class AbstractImageSyntax(rendererSyntax: AbstractRendererSyntax) {
image.compile[Alg].drawWithFrame(frame)

def draw[Alg <: Basic, Frame, Canvas]()(implicit
renderer: DefaultRenderer[Alg, Frame, Canvas],
renderer: Renderer[Alg, Frame, Canvas],
frame: DefaultFrame[Frame],
r: IORuntime
): Unit =
image.compile[Alg].draw()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import cats.Monoid
import cats.effect.IO
import doodle.algebra.Algebra
import doodle.algebra.Picture
import fs2.Stream
import doodle.effect.Writer
import fs2.Stream

import java.io.File

Expand Down
23 changes: 23 additions & 0 deletions java2d/src/main/scala/doodle/java2d/effect/DefaultFrame.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2015 Creative Scala
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package doodle.java2d.effect

import doodle.effect.DefaultFrame

object Java2dDefaultFrame extends DefaultFrame[Frame] {
val default: Frame = Frame.default.withSizedToPicture(20)
}
9 changes: 4 additions & 5 deletions java2d/src/main/scala/doodle/java2d/effect/Java2d.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,15 @@ package java2d
package effect

import cats.effect.IO
import doodle.algebra.generic.*
import doodle.core.BoundingBox
import doodle.core.{Transform => Tx}
import doodle.core.Color
import doodle.core.Transform

import doodle.algebra.generic.*
import doodle.java2d.algebra.Graphics2DGraphicsContext
import doodle.java2d.algebra.reified.Reified
import doodle.core.{Transform => Tx}
import doodle.java2d.algebra.Algebra
import doodle.java2d.algebra.Graphics2DGraphicsContext
import doodle.java2d.algebra.reified.Reification
import doodle.java2d.algebra.reified.Reified
import doodle.java2d.algebra.{Java2D => Java2dAlgebra}

import java.awt.Graphics2D
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package effect
import cats.effect.IO
import doodle.effect.*
import doodle.java2d.effect.{Java2d => Java2dEffect}

import java.awt.image.BufferedImage

object Java2dBufferedImageWriter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,16 @@ package java2d
package effect

import cats.effect.IO
import doodle.effect.DefaultRenderer
import doodle.effect.Renderer

import javax.swing.JFrame

object Java2dRenderer extends DefaultRenderer[Algebra, Frame, Canvas] {
object Java2dRenderer extends Renderer[Algebra, Frame, Canvas] {

import cats.effect.unsafe.implicits.global

private var jFrames: List[JFrame] = List.empty

val default: Frame = Frame.default.withSizedToPicture(20)

def canvas(description: Frame): IO[Canvas] =
Canvas(description).flatMap { jFrame =>
IO {
Expand Down
9 changes: 6 additions & 3 deletions java2d/src/main/scala/doodle/java2d/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@ package doodle
import doodle.algebra._
import doodle.core.format._
import doodle.effect.Base64Writer
import doodle.effect.DefaultRenderer
import doodle.effect.BufferedImageWriter
import doodle.effect.DefaultFrame
import doodle.effect.FileWriter
import doodle.effect.Renderer
import doodle.interact.algebra._
import doodle.interact.effect.AnimationRenderer
import doodle.interact.effect.AnimationWriter
import doodle.java2d.algebra.reified.Reification
import doodle.language.Basic
import doodle.effect.BufferedImageWriter

package object java2d extends Java2dToPicture {
type Algebra =
Expand All @@ -52,8 +53,10 @@ package object java2d extends Java2dToPicture {
doodle.java2d.effect.Java2dAnimationWriter

implicit val java2dRenderer
: DefaultRenderer[Algebra, doodle.java2d.effect.Frame, Canvas] =
: Renderer[Algebra, doodle.java2d.effect.Frame, Canvas] =
doodle.java2d.effect.Java2dRenderer
implicit val java2dFrame: DefaultFrame[doodle.java2d.effect.Frame] =
doodle.java2d.effect.Java2dDefaultFrame
implicit val java2dGifWriter
: FileWriter[Algebra, Frame, Gif] with Base64Writer[Algebra, Frame, Gif] =
doodle.java2d.effect.Java2dGifWriter
Expand Down
4 changes: 2 additions & 2 deletions project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import org.portablescala.sbtplatformdeps.PlatformDepsPlugin.autoImport._
object Dependencies {
// Library Versions
val catsVersion = "2.10.0"
val catsEffectVersion = "3.5.2"
val fs2Version = "3.9.3"
val catsEffectVersion = "3.5.4"
val fs2Version = "3.10.0"

val scalatagsVersion = "0.12.0"

Expand Down
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=1.9.7
sbt.version=1.9.9
8 changes: 4 additions & 4 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.14.0")
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.16.0")
addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.6.4")
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.2")
addSbtPlugin("com.github.sbt" % "sbt-unidoc" % "0.5.0")
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.11.1")
addSbtPlugin("org.typelevel" % "sbt-typelevel" % "0.6.2")
addSbtPlugin("org.typelevel" % "sbt-typelevel-site" % "0.6.2")
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.12.0")
addSbtPlugin("org.typelevel" % "sbt-typelevel" % "0.6.7")
addSbtPlugin("org.typelevel" % "sbt-typelevel-site" % "0.6.7")
5 changes: 3 additions & 2 deletions reactor/shared/src/main/scala/doodle/reactor/Reactor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,12 @@ final case class Reactor[A](
}

def draw[Alg <: Basic, Frame, Canvas]()(implicit
renderer: DefaultRenderer[Alg, Frame, Canvas],
renderer: Renderer[Alg, Frame, Canvas],
frame: DefaultFrame[Frame],
runtime: IORuntime
): Unit = {
import doodle.image.syntax.all._
this.image.draw()(renderer, runtime)
this.image.draw()(renderer, frame, runtime)
}
}
object Reactor {
Expand Down
Loading