diff --git a/src/main/scala/com/melvic/chi/Config.scala b/src/main/scala/com/melvic/chi/Config.scala index f132e46..ed79027 100644 --- a/src/main/scala/com/melvic/chi/Config.scala +++ b/src/main/scala/com/melvic/chi/Config.scala @@ -3,8 +3,8 @@ package com.melvic.chi // TODO: Store this on a properties file object Config { val MaxColumnWidth: Int = 80 - val DialogFontSize: Int = 14 - val DialogHeaderFontSize: Int = 15 + val ComponentFontSize: Float = 14 + val ComponentHeaderFontSize: Int = 15 val CustomSettingsPath = "user-prefs.json" val DefaultSettingsPath = "preferences.json" val DefaultFontPath = "/fonts/FiraCode-Regular.ttf" diff --git a/src/main/scala/com/melvic/chi/config/Preferences.scala b/src/main/scala/com/melvic/chi/config/Preferences.scala index cd6e66e..dc83498 100644 --- a/src/main/scala/com/melvic/chi/config/Preferences.scala +++ b/src/main/scala/com/melvic/chi/config/Preferences.scala @@ -23,4 +23,9 @@ object Preferences { def loadDefaults: Preferences = new Preferences { content = SettingsContent.loadDefaults } + + def fromContent(settingsContent: SettingsContent): Preferences = + new Preferences { + content = settingsContent + } } diff --git a/src/main/scala/com/melvic/chi/eval/package.scala b/src/main/scala/com/melvic/chi/eval/package.scala index c5d94fb..c32523c 100644 --- a/src/main/scala/com/melvic/chi/eval/package.scala +++ b/src/main/scala/com/melvic/chi/eval/package.scala @@ -1,11 +1,18 @@ package com.melvic.chi +import com.melvic.chi.ast.Definition import com.melvic.chi.config.Preferences import com.melvic.chi.out.Result package object eval { type Evaluate = String => String - def generateAndShow(code: String)(implicit prefs: Preferences): String = - Result.show(Generate.fromSignatureString(code)) + def generateWith(code: String)(f: Result[Definition] => String)(implicit prefs: Preferences): String = + f(Generate.fromSignatureString(code)) + + def generateAndShowWithInfo(code: String)(implicit prefs: Preferences): String = + generateWith(code)(Result.showWithInfo) + + def generateAndShowCode(code: String)(implicit prefs: Preferences): String = + generateWith(code)(Result.showCode) } diff --git a/src/main/scala/com/melvic/chi/package.scala b/src/main/scala/com/melvic/chi/package.scala index 722f871..8c9813b 100644 --- a/src/main/scala/com/melvic/chi/package.scala +++ b/src/main/scala/com/melvic/chi/package.scala @@ -7,5 +7,5 @@ package object chi { type Result[A] = Result.Result[A] type Evaluate = eval.Evaluate - def generateAndShow(code: String)(implicit prefs: Preferences): String = eval.generateAndShow(code) + def generateAndShow(code: String)(implicit prefs: Preferences): String = eval.generateAndShowWithInfo(code) } diff --git a/src/main/scala/com/melvic/chi/views/FontUtils.scala b/src/main/scala/com/melvic/chi/views/FontUtils.scala index 3aa1a66..e4d5788 100644 --- a/src/main/scala/com/melvic/chi/views/FontUtils.scala +++ b/src/main/scala/com/melvic/chi/views/FontUtils.scala @@ -1,6 +1,8 @@ package com.melvic.chi.views -import java.awt.Component +import com.melvic.chi.Config + +import java.awt.{Component, Font} object FontUtils { def updateSize[C <: Component](component: C, size: Float): C = @@ -17,4 +19,10 @@ object FontUtils { component.setFont(newFont) component } + + def withComponentFont[C <: Component](component: C): C = + updateSize(component, Config.ComponentFontSize) + + def withComponentHeaderFont[C <: Component](component: C) = + updateStyle(updateSize(component, Config.ComponentHeaderFontSize), Font.BOLD) } diff --git a/src/main/scala/com/melvic/chi/views/MainWindow.scala b/src/main/scala/com/melvic/chi/views/MainWindow.scala index 65fac3b..ec16074 100644 --- a/src/main/scala/com/melvic/chi/views/MainWindow.scala +++ b/src/main/scala/com/melvic/chi/views/MainWindow.scala @@ -2,6 +2,7 @@ package com.melvic.chi.views import com.melvic.chi.Evaluate import com.melvic.chi.config.Preferences +import com.melvic.chi.views.dialogs.PreferencesDialog import com.melvic.chi.views.menus.MenuBar import java.awt._ diff --git a/src/main/scala/com/melvic/chi/views/ToolBarComponent.scala b/src/main/scala/com/melvic/chi/views/ToolBarComponent.scala index 8a7b32a..66cc0a9 100644 --- a/src/main/scala/com/melvic/chi/views/ToolBarComponent.scala +++ b/src/main/scala/com/melvic/chi/views/ToolBarComponent.scala @@ -1,14 +1,18 @@ package com.melvic.chi.views import com.melvic.chi.Config +import com.melvic.chi.views.dialogs.PreferencesDialog +import java.awt.Dimension import java.awt.event.ActionListener import javax.swing.{ImageIcon, JButton, JToolBar} -class ToolBarComponent(editorComponent: EditorComponent, preferencesDialog: PreferencesDialog) extends JToolBar { - add(makeButton("run", "Run code", "Run", _ => editorComponent.run())) - add(makeButton("clear", "Clear all text", "Clear", _ => editorComponent.clear())) +class ToolBarComponent(editorComponent: EditorComponent, preferencesDialog: PreferencesDialog) + extends JToolBar { add(makeButton("preferences", "Show Preferences", "Preferences", _ => preferencesDialog.display())) + addSeparator(new Dimension(20, 10)) + add(makeButton("run", "Run code", "Run", _ => editorComponent.run())) + add(makeButton("clear", "Clear all texts", "Clear", _ => editorComponent.clear())) private def makeButton( imageName: String, @@ -23,10 +27,10 @@ class ToolBarComponent(editorComponent: EditorComponent, preferencesDialog: Pref val imageURL = getClass.getResource(Config.IconsDir + imageName + ".png") if (imageURL != null) button.setIcon(new ImageIcon(imageURL, altText)) - else { - button.setText(altText) + else System.err.println("Icon not found: " + imageName) - } + + button.setText(altText) button } diff --git a/src/main/scala/com/melvic/chi/views/PreferencesDialog.scala b/src/main/scala/com/melvic/chi/views/dialogs/PreferencesDialog.scala similarity index 67% rename from src/main/scala/com/melvic/chi/views/PreferencesDialog.scala rename to src/main/scala/com/melvic/chi/views/dialogs/PreferencesDialog.scala index 716eae7..6dbd290 100644 --- a/src/main/scala/com/melvic/chi/views/PreferencesDialog.scala +++ b/src/main/scala/com/melvic/chi/views/dialogs/PreferencesDialog.scala @@ -1,15 +1,16 @@ -package com.melvic.chi.views +package com.melvic.chi.views.dialogs -import com.melvic.chi.Config import com.melvic.chi.config.SettingsContent.ScalaSettings import com.melvic.chi.config.{Preferences, SettingsContent} +import com.melvic.chi.views.FontUtils import net.miginfocom.swing.MigLayout -import java.awt.{Font, Frame} +import java.awt.Frame +import java.awt.event.{ActionEvent, ActionListener, ItemEvent, ItemListener} import javax.swing._ +import scala.Function.const -class PreferencesDialog(frame: Frame)(implicit preferences: Preferences) - extends JDialog(frame, true) { +class PreferencesDialog(frame: Frame)(implicit preferences: Preferences) extends JDialog(frame, true) { setTitle("Preferences") val pointFreeBox = createCheckBox("Point-free style") @@ -83,20 +84,40 @@ class PreferencesDialog(frame: Frame)(implicit preferences: Preferences) addTitle("Scala Settings", scalaPane) checkBoxes.foreach(scalaPane.add(_, "wrap")) + val previewComponent = PreviewComponent.fromPanel(scalaPane) + addCheckBoxListeners(previewComponent) scalaPane } private def createCheckBox(text: String): JCheckBox = - FontUtils.updateSize(new JCheckBox(text), Config.DialogFontSize) + FontUtils.withComponentFont(new JCheckBox(text)) private def addTitle(title: String, panel: JPanel): Unit = { panel.add( - FontUtils.updateStyle( - FontUtils.updateSize(new JLabel(title), Config.DialogHeaderFontSize), - Font.BOLD - ), + FontUtils.withComponentHeaderFont(new JLabel(title)), "gapleft 20, wrap" ) panel.add(new JSeparator(), "growx, wrap, gapbottom 20") } + + private def addCheckBoxListeners(previewComponent: PreviewComponent): Unit = { + def rerunPreview(): Unit = { + val scalaSettings = preferences.content.scala + val newScalaSettings = scalaSettings.copy( + pointFree = pointFreeBox.isSelected, + simplifyMatch = simplifyMatchBox.isSelected, + usePredef = usePredefBox.isSelected + ) + val newPreferences = Preferences.fromContent(SettingsContent(newScalaSettings)) + println(newScalaSettings) + previewComponent.run(newPreferences) + } + + pointFreeBox.addActionListener(_ => rerunPreview()) + pointFreeBox.addItemListener(_ => rerunPreview()) + simplifyMatchBox.addActionListener(_ => rerunPreview()) + simplifyMatchBox.addItemListener(_ => rerunPreview()) + usePredefBox.addActionListener(_ => rerunPreview()) + usePredefBox.addItemListener(_ => rerunPreview()) + } } diff --git a/src/main/scala/com/melvic/chi/views/dialogs/PreviewComponent.scala b/src/main/scala/com/melvic/chi/views/dialogs/PreviewComponent.scala new file mode 100644 index 0000000..baec277 --- /dev/null +++ b/src/main/scala/com/melvic/chi/views/dialogs/PreviewComponent.scala @@ -0,0 +1,47 @@ +package com.melvic.chi.views.dialogs + +import com.melvic.chi.config.Preferences +import com.melvic.chi.eval.generateAndShowCode +import com.melvic.chi.views.{FontUtils, TextAreaComponent} +import org.fife.ui.rtextarea.RTextScrollPane + +import java.awt.Font +import javax.swing.{JLabel, JPanel} + +class PreviewComponent(implicit prefs: Preferences) extends RTextScrollPane(new TextAreaComponent) { + val textArea = getTextArea + textArea.setEditable(false) + textArea.setColumns(70) + textArea.setRows(20) + FontUtils.withComponentFont(textArea) + + val inputs = List( + "def compose[A, B, C](f: B => C, g: A => B): A => C", + "def disjunctionElimination[A, B, C](f: A => C, g: B => C): Either[A, B] => C", + "def id[A]: A => A", + "def identity[A]: A => A" + ) + + run(prefs) + + def run(preferences: Preferences): Unit = { + val output = inputs.map(generateAndShowCode(_)(preferences)).mkString("\n\n") + textArea.setText(output) + } +} + +object PreviewComponent { + def fromPanel(panel: JPanel, extraLabelConstraints: String = "gaptop 20")( + implicit prefs: Preferences + ): PreviewComponent = { + val label = new JLabel("Preview:") + val fullLabelConstraints = "wrap" + + (if (extraLabelConstraints.nonEmpty) s", $extraLabelConstraints" else "") + FontUtils.withComponentFont(FontUtils.updateStyle(label, Font.BOLD)) + + val previewComponent = new PreviewComponent() + panel.add(label, fullLabelConstraints) + panel.add(previewComponent, "wrap") + previewComponent + } +} diff --git a/src/main/scala/com/melvic/chi/views/menus/FileMenu.scala b/src/main/scala/com/melvic/chi/views/menus/FileMenu.scala index bc7c52c..0514c85 100644 --- a/src/main/scala/com/melvic/chi/views/menus/FileMenu.scala +++ b/src/main/scala/com/melvic/chi/views/menus/FileMenu.scala @@ -1,7 +1,7 @@ package com.melvic.chi.views.menus import com.melvic.chi.config.Preferences -import com.melvic.chi.views.PreferencesDialog +import com.melvic.chi.views.dialogs.PreferencesDialog import java.awt.Frame import java.awt.event.{ActionEvent, KeyEvent} diff --git a/src/main/scala/com/melvic/chi/views/menus/MenuBar.scala b/src/main/scala/com/melvic/chi/views/menus/MenuBar.scala index 2a40177..299d21e 100644 --- a/src/main/scala/com/melvic/chi/views/menus/MenuBar.scala +++ b/src/main/scala/com/melvic/chi/views/menus/MenuBar.scala @@ -1,7 +1,8 @@ package com.melvic.chi.views.menus import com.melvic.chi.config.Preferences -import com.melvic.chi.views.{EditorComponent, PreferencesDialog} +import com.melvic.chi.views.EditorComponent +import com.melvic.chi.views.dialogs.PreferencesDialog import java.awt.Frame import javax.swing.JMenuBar