diff --git a/build.sbt b/build.sbt index 8cd59e9..897fed2 100644 --- a/build.sbt +++ b/build.sbt @@ -1,11 +1,29 @@ -name := "Scurses" +import sbt.Keys._ +import sbt._ -version := "1.0" -scalaVersion := "2.11.7" +lazy val commonSettings: Seq[Setting[_]] = Seq( + version := "1.0", + scalaVersion := "2.11.7", + scalacOptions ++= Seq("-feature", "-unchecked") +) -scalacOptions ++= Seq("-feature", "-unchecked") +lazy val root = (project in file(".")) + .settings(commonSettings: _*) + .aggregate(scurses, onions) -libraryDependencies += "com.lihaoyi" %% "fastparse" % "0.2.1" +lazy val scurses = (project in file("scurses")) + .settings(commonSettings: _*) + .settings( + name := "Scurses", + libraryDependencies += "com.lihaoyi" %% "fastparse" % "0.2.1", + mainClass in (Compile, run) := Some("net.team2xh.scurses.examples.GameOfLife") + ) -mainClass in (Compile, run) := Some("net.team2xh.scurses.examples.StressTest") \ No newline at end of file +lazy val onions = (project in file("onions")) + .settings(commonSettings: _*) + .dependsOn(scurses) + .settings( + name := "Onions", + mainClass in (Compile, run) := Some("net.team2xh.onions.examples.ExampleUI") + ) \ No newline at end of file diff --git a/src/main/scala/net/team2xh/onions/Component.scala b/onions/src/main/scala/net/team2xh/onions/Component.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/Component.scala rename to onions/src/main/scala/net/team2xh/onions/Component.scala diff --git a/src/main/scala/net/team2xh/onions/Palettes.scala b/onions/src/main/scala/net/team2xh/onions/Palettes.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/Palettes.scala rename to onions/src/main/scala/net/team2xh/onions/Palettes.scala diff --git a/src/main/scala/net/team2xh/onions/Symbols.scala b/onions/src/main/scala/net/team2xh/onions/Symbols.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/Symbols.scala rename to onions/src/main/scala/net/team2xh/onions/Symbols.scala diff --git a/src/main/scala/net/team2xh/onions/Themes.scala b/onions/src/main/scala/net/team2xh/onions/Themes.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/Themes.scala rename to onions/src/main/scala/net/team2xh/onions/Themes.scala diff --git a/src/main/scala/net/team2xh/onions/components/Frame.scala b/onions/src/main/scala/net/team2xh/onions/components/Frame.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/components/Frame.scala rename to onions/src/main/scala/net/team2xh/onions/components/Frame.scala diff --git a/src/main/scala/net/team2xh/onions/components/FramePanel.scala b/onions/src/main/scala/net/team2xh/onions/components/FramePanel.scala similarity index 98% rename from src/main/scala/net/team2xh/onions/components/FramePanel.scala rename to onions/src/main/scala/net/team2xh/onions/components/FramePanel.scala index 9c0bc6a..889c60c 100644 --- a/src/main/scala/net/team2xh/onions/components/FramePanel.scala +++ b/onions/src/main/scala/net/team2xh/onions/components/FramePanel.scala @@ -351,9 +351,9 @@ case class FramePanel(parent: Component) else " " + ts if (title != "") { - screen.put(2, 0, r"[[$title$tabText]", theme) + screen.putRichText(2, 0, r"[[$title$tabText]", theme.foreground, theme.background) } else if (tabText != "") { - screen.put(2, 0, r"[[$tabText]", theme) + screen.putRichText(2, 0, r"[[$tabText]", theme.foreground, theme.background) } } diff --git a/src/main/scala/net/team2xh/onions/components/Widget.scala b/onions/src/main/scala/net/team2xh/onions/components/Widget.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/components/Widget.scala rename to onions/src/main/scala/net/team2xh/onions/components/Widget.scala diff --git a/src/main/scala/net/team2xh/onions/components/widgets/BarChart.scala b/onions/src/main/scala/net/team2xh/onions/components/widgets/BarChart.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/components/widgets/BarChart.scala rename to onions/src/main/scala/net/team2xh/onions/components/widgets/BarChart.scala diff --git a/src/main/scala/net/team2xh/onions/components/widgets/BigText.scala b/onions/src/main/scala/net/team2xh/onions/components/widgets/BigText.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/components/widgets/BigText.scala rename to onions/src/main/scala/net/team2xh/onions/components/widgets/BigText.scala diff --git a/src/main/scala/net/team2xh/onions/components/widgets/BitMap.scala b/onions/src/main/scala/net/team2xh/onions/components/widgets/BitMap.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/components/widgets/BitMap.scala rename to onions/src/main/scala/net/team2xh/onions/components/widgets/BitMap.scala diff --git a/src/main/scala/net/team2xh/onions/components/widgets/CheckBox.scala b/onions/src/main/scala/net/team2xh/onions/components/widgets/CheckBox.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/components/widgets/CheckBox.scala rename to onions/src/main/scala/net/team2xh/onions/components/widgets/CheckBox.scala diff --git a/src/main/scala/net/team2xh/onions/components/widgets/FontMapper.scala b/onions/src/main/scala/net/team2xh/onions/components/widgets/FontMapper.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/components/widgets/FontMapper.scala rename to onions/src/main/scala/net/team2xh/onions/components/widgets/FontMapper.scala diff --git a/src/main/scala/net/team2xh/onions/components/widgets/HeatMap.scala b/onions/src/main/scala/net/team2xh/onions/components/widgets/HeatMap.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/components/widgets/HeatMap.scala rename to onions/src/main/scala/net/team2xh/onions/components/widgets/HeatMap.scala diff --git a/src/main/scala/net/team2xh/onions/components/widgets/Input.scala b/onions/src/main/scala/net/team2xh/onions/components/widgets/Input.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/components/widgets/Input.scala rename to onions/src/main/scala/net/team2xh/onions/components/widgets/Input.scala diff --git a/src/main/scala/net/team2xh/onions/components/widgets/Label.scala b/onions/src/main/scala/net/team2xh/onions/components/widgets/Label.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/components/widgets/Label.scala rename to onions/src/main/scala/net/team2xh/onions/components/widgets/Label.scala diff --git a/src/main/scala/net/team2xh/onions/components/widgets/Radio.scala b/onions/src/main/scala/net/team2xh/onions/components/widgets/Radio.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/components/widgets/Radio.scala rename to onions/src/main/scala/net/team2xh/onions/components/widgets/Radio.scala diff --git a/src/main/scala/net/team2xh/onions/components/widgets/RichLabel.scala b/onions/src/main/scala/net/team2xh/onions/components/widgets/RichLabel.scala similarity index 91% rename from src/main/scala/net/team2xh/onions/components/widgets/RichLabel.scala rename to onions/src/main/scala/net/team2xh/onions/components/widgets/RichLabel.scala index e3b0eb2..f408f85 100644 --- a/src/main/scala/net/team2xh/onions/components/widgets/RichLabel.scala +++ b/onions/src/main/scala/net/team2xh/onions/components/widgets/RichLabel.scala @@ -14,7 +14,7 @@ case class RichLabel(parent: FramePanel, text: Varying[RichText]) override def redraw(focus: Boolean, theme: ColorScheme): Unit = { lines = TextWrap.wrapText(text.value, innerWidth - 1) for ((line, i) <- lines.zipWithIndex) { - screen.put(1, i, lines(i), theme) + screen.putRichText(1, i, lines(i), theme.foreground, theme.background) } } diff --git a/src/main/scala/net/team2xh/onions/components/widgets/ScatterPlot.scala b/onions/src/main/scala/net/team2xh/onions/components/widgets/ScatterPlot.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/components/widgets/ScatterPlot.scala rename to onions/src/main/scala/net/team2xh/onions/components/widgets/ScatterPlot.scala diff --git a/src/main/scala/net/team2xh/onions/components/widgets/Separator.scala b/onions/src/main/scala/net/team2xh/onions/components/widgets/Separator.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/components/widgets/Separator.scala rename to onions/src/main/scala/net/team2xh/onions/components/widgets/Separator.scala diff --git a/src/main/scala/net/team2xh/onions/components/widgets/SevenSegment.scala b/onions/src/main/scala/net/team2xh/onions/components/widgets/SevenSegment.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/components/widgets/SevenSegment.scala rename to onions/src/main/scala/net/team2xh/onions/components/widgets/SevenSegment.scala diff --git a/src/main/scala/net/team2xh/onions/components/widgets/Slider.scala b/onions/src/main/scala/net/team2xh/onions/components/widgets/Slider.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/components/widgets/Slider.scala rename to onions/src/main/scala/net/team2xh/onions/components/widgets/Slider.scala diff --git a/src/main/scala/net/team2xh/onions/components/widgets/Spacer.scala b/onions/src/main/scala/net/team2xh/onions/components/widgets/Spacer.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/components/widgets/Spacer.scala rename to onions/src/main/scala/net/team2xh/onions/components/widgets/Spacer.scala diff --git a/src/main/scala/net/team2xh/onions/examples/ExampleUI.scala b/onions/src/main/scala/net/team2xh/onions/examples/ExampleUI.scala similarity index 98% rename from src/main/scala/net/team2xh/onions/examples/ExampleUI.scala rename to onions/src/main/scala/net/team2xh/onions/examples/ExampleUI.scala index 4afec4d..d01d80a 100644 --- a/src/main/scala/net/team2xh/onions/examples/ExampleUI.scala +++ b/onions/src/main/scala/net/team2xh/onions/examples/ExampleUI.scala @@ -84,7 +84,7 @@ object ExampleUI extends App { big.color := color } colB.addTab() - BitMap(colB, "/src/main/scala/net/team2xh/onions/examples/logo.png", relative = true) + BitMap(colB, "/onions/src/main/scala/net/team2xh/onions/examples/logo.png", relative = true) Separator(colB) Label(colB, "Heat maps blur radius:") val slider = Slider(colB, 1, 10)(3) diff --git a/src/main/scala/net/team2xh/onions/examples/logo.png b/onions/src/main/scala/net/team2xh/onions/examples/logo.png similarity index 100% rename from src/main/scala/net/team2xh/onions/examples/logo.png rename to onions/src/main/scala/net/team2xh/onions/examples/logo.png diff --git a/src/main/scala/net/team2xh/onions/utils/Drawing.scala b/onions/src/main/scala/net/team2xh/onions/utils/Drawing.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/utils/Drawing.scala rename to onions/src/main/scala/net/team2xh/onions/utils/Drawing.scala diff --git a/src/main/scala/net/team2xh/onions/utils/Lorem.scala b/onions/src/main/scala/net/team2xh/onions/utils/Lorem.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/utils/Lorem.scala rename to onions/src/main/scala/net/team2xh/onions/utils/Lorem.scala diff --git a/src/main/scala/net/team2xh/onions/utils/Math.scala b/onions/src/main/scala/net/team2xh/onions/utils/Math.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/utils/Math.scala rename to onions/src/main/scala/net/team2xh/onions/utils/Math.scala diff --git a/src/main/scala/net/team2xh/onions/utils/TextWrap.scala b/onions/src/main/scala/net/team2xh/onions/utils/TextWrap.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/utils/TextWrap.scala rename to onions/src/main/scala/net/team2xh/onions/utils/TextWrap.scala diff --git a/src/main/scala/net/team2xh/onions/utils/Varying.scala b/onions/src/main/scala/net/team2xh/onions/utils/Varying.scala similarity index 100% rename from src/main/scala/net/team2xh/onions/utils/Varying.scala rename to onions/src/main/scala/net/team2xh/onions/utils/Varying.scala diff --git a/readme.md b/readme.md index fc3413e..a6da54b 100644 --- a/readme.md +++ b/readme.md @@ -8,22 +8,21 @@ Terminal drawing API for Scala - Hello World: - ```R - $ sbt - > run net.team2xh.scurses.examples.HelloWorld - ``` +```R +$ sbt "scurses/run-main net.team2xh.scurses.examples.HelloWorld" +``` + - Game of life: - ```R - $ sbt - > run net.teamx2h.scurses.examples.GameOfLife - ``` +```R +$ sbt scurses/run +``` + - Stress test: - ```R - $ sbt - > run net.teamx2h.scurses.examples.StressTest - ``` +```R +$ sbt "scurses/run-main net.team2xh.scurses.examples.StressTest" +``` ### How to use @@ -62,32 +61,61 @@ Scurses framework for easy terminal UI What's been done so far: ```R -$ sbt -> run net.teamx2h.onions.examples.ExampleUI +$ sbt onions/run ``` Goal is to provide an API full of widgets to make it really easy for users to quickly set up a dashboard to monitor their services in the terminal (graphs, histograms, logs, etc.) -Currently taking "raw" input from keyboard with JLine, need to find something more powerful to grab inputs like ESC and key combinations, and also detect terminal resize. - ### How to use ```scala Scurses { implicit screen => val frame = Frame("Example UI") // Three columns - val p1 = frame.panel - val p2 = p1.splitRight - val p3 = p2.splitRight - // Split second column in three rows (p2 will point to first row of second column) - val p22 = p2.splitDown - val p23 = p22.splitDown - // Split third row of second column into two columns (p23 will point to the first column of the two) - val p232 = p23.splitRight + val colA = frame.panel + val colB = colA.splitRight + val colC = colB.splitRight + // Split second column in three rows + val colB2 = colB.splitDown + val colB3 = colB2.splitDown + // Split third row of second column into two columns + val colB3B = colB3.splitRight + val colB3B2 = colB3B.splitDown // Split last column into two rows - val p32 = p3.splitDown + val colC2 = colC.splitDown + + // Add a label in the first column + Label(colA, Lorem.Ipsum, TextWrap.JUSTIFY) + + val r = Random + val points = (1 to 50) map (i => { + val x = r.nextInt(40) + val y = 50 - x + (r.nextGaussian() * 5).toInt - 2 + (x, y max 0) + }) + + // Add a scatter plot in the first row of third column + ScatterPlot(colC, points, "Time", "Sales") + + // Show a heat map of the same values in the second row + HeatMap(colC2, points, "Time", "Sales") // Display and launch event loop frame.show() } ``` + +For examples about all widgets, see `ExampleUI.scala` + +### Keyboard controls + +Keys | Action +:---:|:------ + / | Focus next widget in direction / Focus next panel in direction + / | Focus next panel in direction + / + | Focus next / previous panel +CTRL+SPACE | Switch to next tab (if panel has multiple tabs) +SPACE / | Activate label action, check radio or checkbox +< / > | Move slider left / right (also with SPACE / ) +ESC / CTRL+C | Exit + diff --git a/src/main/scala/net/team2xh/scurses/Colors.scala b/scurses/src/main/scala/net/team2xh/scurses/Colors.scala similarity index 100% rename from src/main/scala/net/team2xh/scurses/Colors.scala rename to scurses/src/main/scala/net/team2xh/scurses/Colors.scala diff --git a/src/main/scala/net/team2xh/scurses/EscapeCodes.scala b/scurses/src/main/scala/net/team2xh/scurses/EscapeCodes.scala similarity index 100% rename from src/main/scala/net/team2xh/scurses/EscapeCodes.scala rename to scurses/src/main/scala/net/team2xh/scurses/EscapeCodes.scala diff --git a/src/main/scala/net/team2xh/scurses/Keys.scala b/scurses/src/main/scala/net/team2xh/scurses/Keys.scala similarity index 100% rename from src/main/scala/net/team2xh/scurses/Keys.scala rename to scurses/src/main/scala/net/team2xh/scurses/Keys.scala diff --git a/src/main/scala/net/team2xh/scurses/RichText.scala b/scurses/src/main/scala/net/team2xh/scurses/RichText.scala similarity index 100% rename from src/main/scala/net/team2xh/scurses/RichText.scala rename to scurses/src/main/scala/net/team2xh/scurses/RichText.scala diff --git a/src/main/scala/net/team2xh/scurses/Scurses.scala b/scurses/src/main/scala/net/team2xh/scurses/Scurses.scala similarity index 93% rename from src/main/scala/net/team2xh/scurses/Scurses.scala rename to scurses/src/main/scala/net/team2xh/scurses/Scurses.scala index b897e63..edb2fb2 100644 --- a/src/main/scala/net/team2xh/scurses/Scurses.scala +++ b/scurses/src/main/scala/net/team2xh/scurses/Scurses.scala @@ -3,7 +3,6 @@ package net.team2xh.scurses import java.io.BufferedOutputStream import java.util.{TimerTask, Timer} -import net.team2xh.onions.Themes.ColorScheme import net.team2xh.scurses.RichText._ import sun.misc.{SignalHandler, Signal} @@ -74,12 +73,12 @@ class Scurses { ec.stopBackground() } - def put(x: Int, y: Int, richText: RichText, theme: ColorScheme): Unit = { + def putRichText(x: Int, y: Int, richText: RichText, foreground: Int = -1, background: Int = -1): Unit = { if (outOfBounds(x, y)) return ec.move(x + offsetX, y + offsetY) - if (theme.foreground >= 0) ec.setForeground(theme.foreground) - if (theme.background >= 0) ec.setBackground(theme.background) + if (foreground >= 0) ec.setForeground(foreground) + if (background >= 0) ec.setBackground(background) for (instruction <- richText.instructions) { instruction match { case Text(text) => out.write(text.getBytes) @@ -106,8 +105,8 @@ class Scurses { case Underline => ec.stopUnderline() case Blink => ec.stopBlink() case Reverse => ec.stopReverse() - case Foreground => if (theme.foreground >= 0) ec.setForeground(theme.foreground) - case Background => if (theme.background >= 0) ec.setBackground(theme.background) + case Foreground => if (foreground >= 0) ec.setForeground(foreground) + case Background => if (background >= 0) ec.setBackground(background) case _ => } case ResetAttributes => ec.resetColors() diff --git a/src/main/scala/net/team2xh/scurses/examples/GameOfLife.scala b/scurses/src/main/scala/net/team2xh/scurses/examples/GameOfLife.scala similarity index 100% rename from src/main/scala/net/team2xh/scurses/examples/GameOfLife.scala rename to scurses/src/main/scala/net/team2xh/scurses/examples/GameOfLife.scala diff --git a/src/main/scala/net/team2xh/scurses/examples/HelloWorld.scala b/scurses/src/main/scala/net/team2xh/scurses/examples/HelloWorld.scala similarity index 100% rename from src/main/scala/net/team2xh/scurses/examples/HelloWorld.scala rename to scurses/src/main/scala/net/team2xh/scurses/examples/HelloWorld.scala diff --git a/src/main/scala/net/team2xh/scurses/examples/StressTest.scala b/scurses/src/main/scala/net/team2xh/scurses/examples/StressTest.scala similarity index 100% rename from src/main/scala/net/team2xh/scurses/examples/StressTest.scala rename to scurses/src/main/scala/net/team2xh/scurses/examples/StressTest.scala