From 288a31898914e36ab537b713d7acddd4b30ce59b Mon Sep 17 00:00:00 2001 From: Alexey Novakov Date: Sat, 13 Mar 2021 20:11:25 +0100 Subject: [PATCH] add Image support --- core/shared/src/main/scala/plotly/Trace.scala | 23 ++++++++ .../main/scala/plotly/element/Alignment.scala | 9 ++++ .../scala/plotly/element/ColorModel.scala | 11 ++++ .../main/scala/plotly/element/HoverInfo.scala | 1 + .../scala/plotly/element/HoverLabel.scala | 12 +++++ .../scala/plotly/element/HoverLabelFont.scala | 9 ++++ .../internals/ArgonautCodecsInternals.scala | 3 ++ .../scala/plotly/doc/DocumentationTests.scala | 53 ++++++++++++++++++- 8 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 core/shared/src/main/scala/plotly/element/Alignment.scala create mode 100644 core/shared/src/main/scala/plotly/element/ColorModel.scala create mode 100644 core/shared/src/main/scala/plotly/element/HoverLabel.scala create mode 100644 core/shared/src/main/scala/plotly/element/HoverLabelFont.scala diff --git a/core/shared/src/main/scala/plotly/Trace.scala b/core/shared/src/main/scala/plotly/Trace.scala index 96f6ca4..95c9139 100755 --- a/core/shared/src/main/scala/plotly/Trace.scala +++ b/core/shared/src/main/scala/plotly/Trace.scala @@ -156,6 +156,29 @@ object Box { ) } +@data(optionSetters = true) class Image( + z: Seq[Seq[Seq[Double]]], + x0: Option[Element] = None, + y0: Option[Element] = None, + name: Option[String] = None, + text: Option[Seq[String]] = None, + opacity: Option[Double] = None, + ids: Option[Seq[String]] = None, + dx: Option[Double] = None, + dy: Option[Double] = None, + source: Option[String] = None, + hoverinfo: Option[HoverInfo] = None, + hovertemplate: Option[Seq[String]] = None, + meta: Option[String] = None, + customdata: Option[Seq[String]] = None, + xaxis: Option[AxisReference] = None, + yaxis: Option[AxisReference] = None, + colormodel: Option[ColorModel] = None, + zmax: Option[Seq[Double]] = None, + zmin: Option[Seq[Double]] = None, + hoverlabel: Option[HoverLabel] = None +) extends Trace + @data(optionSetters = true) class Bar( x: Sequence, y: Sequence, diff --git a/core/shared/src/main/scala/plotly/element/Alignment.scala b/core/shared/src/main/scala/plotly/element/Alignment.scala new file mode 100644 index 0000000..b09395a --- /dev/null +++ b/core/shared/src/main/scala/plotly/element/Alignment.scala @@ -0,0 +1,9 @@ +package plotly.element + +sealed abstract class Alignment(val label: String) extends Product with Serializable + +object Alignment { + case object Left extends Alignment("left") + case object Right extends Alignment("right") + case object Auto extends Alignment("auto") +} diff --git a/core/shared/src/main/scala/plotly/element/ColorModel.scala b/core/shared/src/main/scala/plotly/element/ColorModel.scala new file mode 100644 index 0000000..de972dc --- /dev/null +++ b/core/shared/src/main/scala/plotly/element/ColorModel.scala @@ -0,0 +1,11 @@ +package plotly.element + +sealed abstract class ColorModel(val label: String) extends Product with Serializable + +object ColorModel { + case object RGB extends ColorModel("rgb") + case object RGBA extends ColorModel("rgba") + case object RGBA256 extends ColorModel("rgba256") + case object HSL extends ColorModel("hsl") + case object HSLA extends ColorModel("hsla") +} diff --git a/core/shared/src/main/scala/plotly/element/HoverInfo.scala b/core/shared/src/main/scala/plotly/element/HoverInfo.scala index 09e5b76..02fe23c 100644 --- a/core/shared/src/main/scala/plotly/element/HoverInfo.scala +++ b/core/shared/src/main/scala/plotly/element/HoverInfo.scala @@ -20,6 +20,7 @@ object HoverInfo { case object Z extends Element("z") case object Text extends Element("text") case object Name extends Element("name") + case object Color extends Element("color") case object All extends HoverInfo { diff --git a/core/shared/src/main/scala/plotly/element/HoverLabel.scala b/core/shared/src/main/scala/plotly/element/HoverLabel.scala new file mode 100644 index 0000000..3938063 --- /dev/null +++ b/core/shared/src/main/scala/plotly/element/HoverLabel.scala @@ -0,0 +1,12 @@ +package plotly.element + +import dataclass.data + +@data(optionSetters = true) class HoverLabel( + bgcolor: Option[OneOrSeq[Color]] = None, + bordercolor: Option[OneOrSeq[Color]] = None, + font: Option[HoverLabelFont] = None, + align: Option[OneOrSeq[Alignment]] = None, + namelength: Option[OneOrSeq[Int]] = None, + uirevision: Option[Element] = None +) diff --git a/core/shared/src/main/scala/plotly/element/HoverLabelFont.scala b/core/shared/src/main/scala/plotly/element/HoverLabelFont.scala new file mode 100644 index 0000000..f6384c1 --- /dev/null +++ b/core/shared/src/main/scala/plotly/element/HoverLabelFont.scala @@ -0,0 +1,9 @@ +package plotly.element + +import dataclass.data + +@data(optionSetters = true) class HoverLabelFont( + family: Option[OneOrSeq[String]] = None, + size: Option[OneOrSeq[Double]] = None, + color: Option[OneOrSeq[Color]] = None +) diff --git a/render/shared/src/main/scala/plotly/internals/ArgonautCodecsInternals.scala b/render/shared/src/main/scala/plotly/internals/ArgonautCodecsInternals.scala index 414c6c4..6f1e270 100755 --- a/render/shared/src/main/scala/plotly/internals/ArgonautCodecsInternals.scala +++ b/render/shared/src/main/scala/plotly/internals/ArgonautCodecsInternals.scala @@ -149,6 +149,8 @@ object ArgonautCodecsInternals extends ArgonautCodecsExtra { implicit val tickModeIsEnum = IsEnum.instance[TickMode](_.mode) implicit val patternIsEnum = IsEnum.instance[Pattern](_.label) implicit val rowOrderIsEnum = IsEnum.instance[RowOrder](_.label) + implicit val alignmentIsEnum = IsEnum.instance[Alignment](_.label) + implicit val colorModelIsEnum = IsEnum.instance[ColorModel](_.label) def jsonSumDirectCodecFor(name: String): JsonSumCodec = new JsonSumCodec { def encodeEmpty: Nothing = @@ -225,6 +227,7 @@ object ArgonautCodecsInternals extends ArgonautCodecsExtra { case "x" => Right(HoverInfo.X) case "y" => Right(HoverInfo.Y) case "z" => Right(HoverInfo.Z) + case "color" => Right(HoverInfo.Color) case "text" => Right(HoverInfo.Text) case "name" => Right(HoverInfo.Name) case other => Left(s"Unrecognized hover info element: $other") diff --git a/tests/src/test/scala/plotly/doc/DocumentationTests.scala b/tests/src/test/scala/plotly/doc/DocumentationTests.scala index ff7cc26..b341bc0 100755 --- a/tests/src/test/scala/plotly/doc/DocumentationTests.scala +++ b/tests/src/test/scala/plotly/doc/DocumentationTests.scala @@ -4,13 +4,15 @@ package doc import java.io.{ByteArrayOutputStream, File, InputStream} import java.lang.{Double => JDouble} import java.nio.file.Files - import argonaut.Argonaut._ import argonaut.{Json, Parse} import plotly.layout.Layout import org.mozilla.javascript._ import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers +import plotly.element.HoverInfo +import plotly.element.HoverInfo.{X,Y,Z} +import plotly.element.ColorModel._ import scala.util.matching.Regex @@ -308,4 +310,53 @@ class DocumentationTests extends AnyFlatSpec with Matchers { } } + it should "demo Image Trace" in { + val js = + """ + |var data = [ + | { + | type: "image", + | opacity: 0.1, + | x0: 0.05, + | y0: 0.05, + | colormodel: "rgb", + | hoverinfo: "x+y+z+color", + | z: [[[255, 0, 0], [0, 255, 0], [0, 0, 255]]] + | } + |]; + | + |var layout = { + | width: 400, + | height: 400, + | title: "image with opacity 0.1" + |}; + | + |Plotly.newPlot('myDiv', data, layout); + |""".stripMargin + val (data, maybeLayout) = plotlyDemoElements(js) + maybeLayout should ===(Some( + Layout() + .withWidth(400) + .withHeight(400) + .withTitle("image with opacity 0.1") + )) + + data.headOption match { + case Some(image) => + val colors = Seq( + Seq(Seq(255d, 0d, 0d), Seq(0d, 255, 0), Seq(0d, 0, 255)), + ) + val expected = Image(z = colors) + .withOpacity(0.1) + .withX0(0.05) + .withY0(0.05) + .withHoverinfo(HoverInfo(X, Y, Z, HoverInfo.Color)) + .withColormodel(RGB) + + image should ===(expected) + case None => + fail("data must contain an image trace") + } + } + }