Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
kieferlam committed May 8, 2018
1 parent 099b77e commit d9ce0c5
Show file tree
Hide file tree
Showing 21 changed files with 743 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.idea
*.tff
*.ttf
*.iml
/cm-unicode-0.7.0
/out
8 changes: 8 additions & 0 deletions src/com/kieferlam/maths/Main.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.kieferlam.maths

import com.kieferlam.maths.fx.Launcher
import javafx.application.Application

fun main(args: Array<String>) {
Application.launch(Launcher::class.java)
}
20 changes: 20 additions & 0 deletions src/com/kieferlam/maths/fx/Launcher.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.kieferlam.maths.fx

import com.kieferlam.maths.fx.style.MenubarStyle
import com.kieferlam.maths.fx.view.RootView
import javafx.stage.Stage
import tornadofx.*

class Launcher : App(RootView::class){

init{
reloadStylesheetsOnFocus()
}

override fun start(stage: Stage) {
stage.width = 1280.0
stage.height = 720.0
stage.title = "Maths"
super.start(stage)
}
}
17 changes: 17 additions & 0 deletions src/com/kieferlam/maths/fx/style/MenubarStyle.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.kieferlam.maths.fx.style

import tornadofx.*

class MenubarStyle : Stylesheet(){
init{
menuBar{
padding = box(0.0.px)
}
menu{
padding = box(5.0.px, 8.0.px)
}
menuItem{
padding = box(100.0.px)
}
}
}
17 changes: 17 additions & 0 deletions src/com/kieferlam/maths/fx/view/RootView.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.kieferlam.maths.fx.view

import com.kieferlam.maths.fx.view.maths.MathsInputPane
import com.kieferlam.maths.fx.view.menu.GlobalMenuBar
import javafx.scene.Parent
import javafx.scene.layout.BorderPane
import tornadofx.*

class RootView : View(){
override val root = BorderPane()

init{
root.top = GlobalMenuBar()
root.center = MathsInputPane()
}

}
117 changes: 117 additions & 0 deletions src/com/kieferlam/maths/fx/view/maths/MathsInputPane.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package com.kieferlam.maths.fx.view.maths

import com.kieferlam.maths.fx.view.render.MathsRenderer
import com.kieferlam.maths.fx.view.render.measureString
import com.kieferlam.maths.fx.view.render.operator.OperatorRenderer
import com.kieferlam.postfix.exception.InvalidSyntaxException
import com.kieferlam.postfix.syntax.ExpressionEntity
import com.kieferlam.postfix.syntax.Postfix
import javafx.application.Platform
import javafx.event.EventHandler
import javafx.scene.canvas.Canvas
import javafx.scene.image.Image
import javafx.scene.layout.Pane
import javafx.scene.paint.Color
import tornadofx.add
import java.util.*

class MathsInputPane : Pane() {

private val canvas = Canvas()
private val context by lazy { canvas.graphicsContext2D }

private var inputString = ""
private var postfix = ArrayList<ExpressionEntity>()
private var resultString = "NaN"
private var mathsRender = Stack<Image>()

private var isDrawing = false
private val drawThread = Thread({
isDrawing = true
while (isDrawing) {
if (!this.scene.window.isShowing) isDrawing = false
draw()
Thread.sleep(1000L)
}
})

init {
canvas.widthProperty().bind(widthProperty())
canvas.heightProperty().bind(heightProperty())
canvas.widthProperty().addListener { _, _, _ ->
draw()
}
canvas.heightProperty().addListener { _, _, _ ->
draw()
}

add(canvas)
onMousePressed = EventHandler {
this.requestFocus()
}

onKeyTyped = EventHandler {
when (it.character) {
"\b" -> {
if (inputString.isNotEmpty()) inputString = inputString.substring(0, inputString.length - 1)
}
"\u000D" -> {
}
else -> inputString += it.character
}

try {
postfix = Postfix.from(inputString)
resultString = Postfix.evaluate(postfix).value.toDouble().toString()
Platform.runLater {
mathsRender = MathsRenderer.render(postfix)
}
} catch (syntax: InvalidSyntaxException) {
"Syntax Error"
} catch (e: Exception) {
e.message!!
}

draw()
}

Platform.runLater {
drawThread.start()
}
}

fun draw() {
with(context) {
clearRect(0.0, 0.0, width, height)

fill = Color.BLACK
font = OperatorRenderer.FONT

val displayString = inputString + " = " + resultString
val textSize = measureString(displayString, font)
val xScale = Math.min(width / textSize.width, 1.0)
val yScale = Math.min(height / (textSize.height + (mathsRender.maxBy { it.height }?.height ?: 0.0)), 1.0)
val scale = Math.min(xScale, yScale)

save()
translate(width * 0.5, height * 0.5)
scale(scale * 0.8, scale * 0.8)

fillText(displayString, -textSize.width * 0.5, -textSize.height)

fill = Color.LIGHTGRAY
strokeLine(-canvas.width, -100.0, canvas.width, -100.0)
fill = Color.BLACK

var x = 0.0
mathsRender.forEach {
drawImage(it, x - 500, -(it.height * 0.5) + 200.0)
x += it.width
}

restore()

}
}

}
29 changes: 29 additions & 0 deletions src/com/kieferlam/maths/fx/view/menu/FileMenu.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.kieferlam.maths.fx.view.menu

import javafx.scene.control.Menu
import javafx.scene.control.MenuItem

class FileMenu : Menu("File") {
init {
items.addAll(
New(),
Open()
)
}
}

private class New : MenuItem("New") {
init{
setOnAction {

}
}
}

private class Open : MenuItem("Open") {
init{
setOnAction {

}
}
}
17 changes: 17 additions & 0 deletions src/com/kieferlam/maths/fx/view/menu/GlobalMenuBar.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.kieferlam.maths.fx.view.menu

import com.kieferlam.maths.fx.style.MenubarStyle
import javafx.scene.control.Menu
import javafx.scene.control.MenuBar
import javafx.scene.control.MenuItem
import tornadofx.*

class GlobalMenuBar : MenuBar(){
init{
menus.addAll(
FileMenu()
)
}

override fun getUserAgentStylesheet(): String = MenubarStyle().base64URL.toExternalForm()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.kieferlam.maths.fx.view.render

class MathsRenderException(msg: String = "") : Exception("Unable to render maths expression: $msg")
16 changes: 16 additions & 0 deletions src/com/kieferlam/maths/fx/view/render/MathsRenderUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.kieferlam.maths.fx.view.render

import javafx.scene.Group
import javafx.scene.Scene
import javafx.scene.text.Font
import javafx.scene.text.Text
import tornadofx.*

fun measureString(string: String, font: Font): Size {
var text = Text(string)
text.font = font
Scene(Group(text))
return Size(text.layoutBounds.width, text.layoutBounds.height)
}

data class Size(val width: Double, val height: Double)
36 changes: 36 additions & 0 deletions src/com/kieferlam/maths/fx/view/render/MathsRenderer.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.kieferlam.maths.fx.view.render

import com.kieferlam.maths.fx.view.render.operator.OperandRenderer
import com.kieferlam.maths.fx.view.render.operator.OperatorRenderer
import com.kieferlam.postfix.syntax.ExpressionEntity
import com.kieferlam.postfix.syntax.Operand
import com.kieferlam.postfix.syntax.Operator
import com.kieferlam.postfix.syntax.operator.function.FunctionOperator
import javafx.scene.SnapshotParameters
import javafx.scene.canvas.Canvas
import javafx.scene.image.Image
import javafx.scene.image.WritableImage
import java.util.*
import kotlin.collections.ArrayList

object MathsRenderer {

fun render(expression: ArrayList<ExpressionEntity>): Stack<Image> {
var stack = Stack<Image>()
for (e in expression) {
if (e.isOperator) {
val numOfOperands = (e as Operator).numberOfParameters
if (stack.size < numOfOperands) throw MathsRenderException("Not enough operands (operator requires $numOfOperands operands).")
val operandImgs = ArrayList<Image>()
for (i in 0 until numOfOperands) {
operandImgs.add(stack.pop())
}
stack.push(OperatorRenderer.getRenderer(e).render(e, *operandImgs.toTypedArray().reversedArray()))
} else {
stack.push(OperandRenderer.render(e as Operand))
}
}
return stack
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.kieferlam.maths.fx.view.render.operator

import com.kieferlam.maths.fx.view.render.MathsRenderException
import com.kieferlam.maths.fx.view.render.Size
import com.kieferlam.maths.fx.view.render.measureString
import com.kieferlam.postfix.syntax.Operator
import com.kieferlam.postfix.syntax.operator.function.FunctionOperator
import javafx.geometry.VPos
import javafx.scene.SnapshotParameters
import javafx.scene.canvas.Canvas
import javafx.scene.image.Image
import javafx.scene.paint.Color

class DefaultFunctionRenderer : OperatorRenderer(FunctionOperator.ABSOLUTE) {

override fun render(operator: Operator?, vararg operands: Image): Image {
if (operator == null) throw MathsRenderException("Operator is null.")
if(operands.size < operator.numberOfParameters) throw MathsRenderException("Not enough parameters.")
val canvas = Canvas()
val g = canvas.graphicsContext2D
val snapshot = SnapshotParameters()
snapshot.fill = Color.TRANSPARENT
// snapshot.fill = Color.rgb((Math.random() * 255).toInt(), (Math.random() * 255).toInt(), (Math.random() * 255).toInt())

val operatorSize = measureString(operator.symbol + "()", FONT)

val operandSize = Size(operands.sumBy { it.width.toInt() }.toDouble() , operands.maxBy { it.height.toInt() }!!.height)

canvas.width = operatorSize.width + operandSize.width
canvas.height = operandSize.height

var operandIndex = 0
var drawX = 0.0

with(g) {
font = OperatorRenderer.FONT
fill = Color.BLACK
textBaseline = VPos.TOP
if(operator.numberOfParameters > 1){
drawImage(operands[operandIndex], drawX, (canvas.height - operands[operandIndex].height)*0.5)
drawX += operands[operandIndex].width
operandIndex++
}
fillText(operator.symbol, drawX, ((canvas.height - operatorSize.height) * 0.5) - 15.0)
drawX += operatorSize.width
drawImage(operands[operandIndex], drawX, (canvas.height - operands[operandIndex].height)*0.5)
operandIndex++
}

return canvas.snapshot(snapshot, null)
}

}
Loading

0 comments on commit d9ce0c5

Please sign in to comment.