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

UI #40

Merged
merged 10 commits into from
Apr 2, 2022
Merged

UI #40

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
18 changes: 11 additions & 7 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
ThisBuild / version := "0.1.0-RC"
import Dependencies.dependencies

ThisBuild / version := "0.1.0-RC2-SNAPSHOT"

ThisBuild / scalaVersion := "2.13.8"

assemblyJarName in assembly := "chi-0.1.0-rc.jar"
assemblyJarName in assembly := "chi-0.1.0-rc2-snapshot.jar"

lazy val root = (project in file("."))
.settings(
name := "chi",
libraryDependencies ++= Seq(
"org.scala-lang.modules" % "scala-parser-combinators_2.13" % "2.1.1",
"org.scalactic" %% "scalactic" % "3.2.11",
"org.scalatest" %% "scalatest" % "3.2.11" % "test"
)
libraryDependencies ++= dependencies
)

// Fix deduplication error during merge (see https://stackoverflow.com/questions/25144484/sbt-assembly-deduplication-found-error)
assemblyMergeStrategy in assembly := {
case PathList("META-INF", xs @ _*) => MergeStrategy.discard
case x => MergeStrategy.first
}
17 changes: 17 additions & 0 deletions project/Dependencies.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import sbt._

object Dependencies {
lazy val testDependencies = Seq(
"org.scalactic" %% "scalactic" % "3.2.11",
"org.scalatest" %% "scalatest" % "3.2.11" % "test",
)

lazy val uiDependencies = Seq(
"com.github.weisj" % "darklaf-core" % "2.7.3",
"com.fifesoft" % "rsyntaxtextarea" % "3.2.0"
)

lazy val dependencies = Seq(
"org.scala-lang.modules" % "scala-parser-combinators_2.13" % "2.1.1",
) ++ testDependencies ++ uiDependencies
}
24 changes: 19 additions & 5 deletions src/main/scala/com/melvic/chi/Main.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
package com.melvic.chi

import scala.annotation.tailrec
import scala.io.StdIn.readLine
import com.github.weisj.darklaf.LafManager
import com.github.weisj.darklaf.theme.DarculaTheme
import com.melvic.chi.views.menus.MainView

import javax.swing.SwingUtilities

//noinspection SpellCheckingInspection
object Main {
def main(args: Array[String]): Unit = {
Repl()
}
def main(args: Array[String]): Unit =
args match {
case Array("repl", _ @_*) => Repl()
case _ => runUI()
}

def runUI(): Unit =
SwingUtilities.invokeLater(new Runnable() {
LafManager.install(new DarculaTheme)

override def run(): Unit = {
new MainView(generateAndShow).setVisible(true)
}
})
}
10 changes: 10 additions & 0 deletions src/main/scala/com/melvic/chi/eval/package.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.melvic.chi

import com.melvic.chi.out.Result

package object eval {
type Evaluate = String => String

def generateAndShow: Evaluate = code =>
Result.show(CodeGen.fromSignatureString(code))
}
4 changes: 2 additions & 2 deletions src/main/scala/com/melvic/chi/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.melvic.chi.out.Result

package object chi {
type Result[A] = Result.Result[A]
type Evaluate = eval.Evaluate

def generateAndShow(code: String): String =
Result.show(CodeGen.fromSignatureString(code))
val generateAndShow = eval.generateAndShow
}
29 changes: 29 additions & 0 deletions src/main/scala/com/melvic/chi/views/AreaView.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.melvic.chi.views

import org.fife.ui.rsyntaxtextarea.{RSyntaxTextArea, Style, SyntaxConstants, Token, TokenTypes}
import org.fife.ui.rtextarea.RTextScrollPane
import org.fife.ui.rsyntaxtextarea.Theme
import java.io.IOException

import java.awt.{Color, Font}

class AreaView extends RSyntaxTextArea(50, 50) {
setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SCALA)
setCodeFoldingEnabled(true)

updateStyle()
setFont(new Font(getFont.getName, getFont.getStyle, 16))

private def updateStyle(): Unit =
try {
val theme = Theme.load(getClass.getResourceAsStream("/org/fife/ui/rsyntaxtextarea/themes/dark.xml"))
theme.apply(this)
} catch {
case ioe: IOException =>
ioe.printStackTrace()
}
}

object AreaView {
def withScrollPane = new RTextScrollPane(new AreaView)
}
46 changes: 46 additions & 0 deletions src/main/scala/com/melvic/chi/views/EditorView.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.melvic.chi.views

import com.melvic.chi.Evaluate

import java.awt.BorderLayout
import java.awt.event.{KeyEvent, KeyListener}
import javax.swing.{JPanel, JSplitPane}

class EditorView(evaluate: Evaluate) extends JPanel {
val inputView = AreaView.withScrollPane
val outputView = {
val out = AreaView.withScrollPane
out.getTextArea.setEditable(false)
out
}

private val splitPane = {
val splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, inputView, outputView)
splitPane.setOneTouchExpandable(true)
splitPane.setResizeWeight(0.5)
splitPane
}

setLayout(new BorderLayout)
add(splitPane, BorderLayout.CENTER)

inputView.getTextArea.addKeyListener(new KeyListener {
override def keyTyped(e: KeyEvent): Unit = {}

override def keyPressed(e: KeyEvent): Unit = {}

override def keyReleased(e: KeyEvent): Unit = run()
})

def run(): Unit = {
val programs = inputView.getTextArea.getText.split("\n")
val outputs = programs.map(_.trim).filter(_.nonEmpty).map(evaluate)
outputView.getTextArea.setText(outputs.mkString("\n\n"))
}

def clear(): Unit = {
inputView.getTextArea.setText("")
outputView.getTextArea.setText("")
}
}

25 changes: 25 additions & 0 deletions src/main/scala/com/melvic/chi/views/menus/EditorMenu.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.melvic.chi.views.menus

import com.melvic.chi.Evaluate
import com.melvic.chi.views.EditorView

import java.awt.event.{ActionEvent, ActionListener, KeyEvent}
import javax.swing.{JMenu, JMenuItem, KeyStroke}

class EditorMenu(editorView: EditorView) extends JMenu("Editor") {
add(runMenuItem)
add(clearMenuItem)

private def runMenuItem = {
val runMenuItem = new JMenuItem("Run")
runMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, ActionEvent.CTRL_MASK))
runMenuItem.addActionListener(_ => editorView.run())
runMenuItem
}

private def clearMenuItem = {
val clearMenuItem = new JMenuItem("Clear")
clearMenuItem.addActionListener(_ => editorView.clear())
clearMenuItem
}
}
19 changes: 19 additions & 0 deletions src/main/scala/com/melvic/chi/views/menus/MainView.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.melvic.chi.views.menus

import com.melvic.chi.Evaluate
import com.melvic.chi.views.EditorView

import java.awt._
import javax.swing._

class MainView(evaluate: Evaluate) extends JFrame {
val editorView = new EditorView(evaluate)

setContentPane(editorView)
setTitle("Chi")
setJMenuBar(new MenuBarView(editorView))
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
pack()
setLocationRelativeTo(null)
setExtendedState(Frame.MAXIMIZED_BOTH)
}
25 changes: 25 additions & 0 deletions src/main/scala/com/melvic/chi/views/menus/MenuBarView.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.melvic.chi.views.menus

import com.melvic.chi.Evaluate
import com.melvic.chi.views.EditorView

import java.awt.event.{ActionEvent, KeyEvent}
import javax.swing.{JMenu, JMenuBar, JMenuItem, KeyStroke}

class MenuBarView(editorView: EditorView) extends JMenuBar {
val fileMenu = createMenuItem(
new JMenu("File"),
"Exit",
Some(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.CTRL_MASK))
)

def createMenuItem(menu: JMenu, itemName: String, keyStroke: Option[KeyStroke] = None): JMenu = {
val menuItem = new JMenuItem(itemName)
keyStroke.foreach(menuItem.setAccelerator)
menu.add(menuItem)
menu
}

add(fileMenu)
add(new EditorMenu(editorView))
}