1.1 --- a/isac-java/src/java/isac/gui/mawen/editor/AstInfoUtil.scala Tue Sep 12 14:46:07 2017 +0200
1.2 +++ b/isac-java/src/java/isac/gui/mawen/editor/AstInfoUtil.scala Tue Sep 12 15:39:03 2017 +0200
1.3 @@ -108,6 +108,7 @@
1.4 }
1.5 case ast => None
1.6 }
1.7 + // precondition: there is only ONE "CURSOR" in a formula.
1.8 // introducing Option[Ast] would cause delicate changes
1.9 def FindCursor(ast: Ast) : Ast = ast match {
1.10 case Appl(List(Constant("CURSOR"), a)) => ast
2.1 --- a/isac-java/src/java/isac/gui/mawen/editor/CalcUtil.scala Tue Sep 12 14:46:07 2017 +0200
2.2 +++ b/isac-java/src/java/isac/gui/mawen/editor/CalcUtil.scala Tue Sep 12 15:39:03 2017 +0200
2.3 @@ -25,43 +25,50 @@
2.4 def assembleBoxes (ast: Ast, f: (DrawBox) => Unit ) =
2.5 assembleBoxesRec(new EmptyBox(0,0,0,ast), f)
2.6
2.7 - def assembleBoxesRec(emptyBox: EmptyBox, f:(DrawBox) => Unit) : DrawBox = emptyBox.ast match {
2.8 + /*
2.9 + * Recursively assemble boxes, i.e. sub-terms of a formula while scanning the Ast.
2.10 + *
2.11 + * For the call back see $4.3.1 p.53/54 and $4.3.2 p.56.
2.12 + */
2.13 + def assembleBoxesRec(emptyBox: EmptyBox, callback_calc:(DrawBox) => Unit) : DrawBox = emptyBox.ast match {
2.14 case Appl(operator :: param :: Nil)
2.15 - => assembleUniopBoxes(EmptyUniOpBox(emptyBox.level, emptyBox.x0, emptyBox.y0, param, emptyBox.ast), f)
2.16 + => assembleUniopBoxes(EmptyUniOpBox(emptyBox.level, emptyBox.x0, emptyBox.y0, param, emptyBox.ast), callback_calc)
2.17 case Appl(operator :: paraml :: paramr :: Nil)
2.18 - => assembleBinopBoxes(AstInfoUtil.OperatorString(operator), EmptyBinOpBox(emptyBox.level,emptyBox.x0, emptyBox.y0, operator, paraml, paramr,emptyBox.ast), f)
2.19 + => assembleBinopBoxes(AstInfoUtil.OperatorString(operator), EmptyBinOpBox(emptyBox.level,emptyBox.x0, emptyBox.y0, operator, paraml, paramr,emptyBox.ast), callback_calc)
2.20 case Appl(Constant(str) :: param)
2.21 - => calcDefault(str,param, emptyBox.x0, emptyBox.y0, emptyBox.level, emptyBox.ast, f)
2.22 + => calcDefault(str,param, emptyBox.x0, emptyBox.y0, emptyBox.level, emptyBox.ast, callback_calc)
2.23 case a
2.24 - => assembleLeafBoxes(EmptyLeafOpBox(emptyBox.level, emptyBox.x0, emptyBox.y0, emptyBox.ast), f)
2.25 + => assembleLeafBoxes(EmptyLeafOpBox(emptyBox.level, emptyBox.x0, emptyBox.y0, emptyBox.ast), callback_calc)
2.26 }
2.27 - def assembleLeafBoxes(emptyBox: EmptyLeafOpBox, f:(DrawBox) => Unit) : DrawBox = emptyBox.ast match {
2.28 - case Variable("GAP") => calcGAP( emptyBox, f)
2.29 - case Constant("GAP") => calcGAP( emptyBox, f)
2.30 - case Constant(str) => calcConstant( emptyBox, f)
2.31 - case Variable(str) => calcVariable( emptyBox, f)
2.32 + def assembleLeafBoxes(emptyBox: EmptyLeafOpBox, callback_calc:(DrawBox) => Unit) : DrawBox = emptyBox.ast match {
2.33 + case Variable("GAP") => calcGAP( emptyBox, callback_calc)
2.34 + case Constant("GAP") => calcGAP( emptyBox, callback_calc)
2.35 + case Constant(str) => calcConstant( emptyBox, callback_calc)
2.36 + case Variable(str) => calcVariable( emptyBox, callback_calc)
2.37 case ast => throw new AstException("assembleBoxesRec, uncovered match: " + raw_string_of(ast))
2.38 }
2.39 - def assembleUniopBoxes(emptyBox: EmptyUniOpBox, f:(DrawBox) => Unit) : DrawBox = emptyBox.ast match {
2.40 + def assembleUniopBoxes(emptyBox: EmptyUniOpBox, callback_calc:(DrawBox) => Unit) : DrawBox = emptyBox.ast match {
2.41 case Appl(Constant(str) :: ast :: Nil) if str.startsWith("BOX")
2.42 - => CalcBox( str.replace("BOX.", ""), emptyBox, f)
2.43 + => CalcBox( str.replace("BOX.", ""), emptyBox, callback_calc)
2.44 case Appl(Constant("CURSOR") :: param :: Nil)
2.45 - => calcCursor( EmptyUniOpBox(emptyBox.level,emptyBox.x0,emptyBox.y0, param, emptyBox.ast), f)
2.46 + => calcCursor( EmptyUniOpBox(emptyBox.level,emptyBox.x0,emptyBox.y0, param, emptyBox.ast), callback_calc)
2.47 case Appl(param :: Constant("CURSOR") :: Nil)
2.48 - => calcCursor( EmptyUniOpBox(emptyBox.level,emptyBox.x0,emptyBox.y0, param, emptyBox.ast), f)
2.49 + => calcCursor( EmptyUniOpBox(emptyBox.level,emptyBox.x0,emptyBox.y0, param, emptyBox.ast), callback_calc)
2.50 case Appl(op :: param :: Nil)
2.51 - => calcDefault( AstInfoUtil.OperatorString(op), List(param), emptyBox.x0, emptyBox.y0, emptyBox.level, emptyBox.ast, f)
2.52 + => calcDefault( AstInfoUtil.OperatorString(op), List(param), emptyBox.x0, emptyBox.y0, emptyBox.level, emptyBox.ast, callback_calc)
2.53 case ast
2.54 => throw new AstException("assembleBoxesRec, uncovered match: " + raw_string_of(ast))
2.55 }
2.56 - def assembleBinopBoxes( operatorString: String, emptyBox: EmptyBinOpBox, f:(DrawBox) => Unit) : DrawBox = Settings.layoutName(XSyntax.isa_ast(operatorString) ) match {
2.57 - case "binOp" => calcDefaultBinOp( emptyBox, f)
2.58 - case "Pow" => calcPow( emptyBox, f)
2.59 - case "Frac" => calcFrac( emptyBox, f)
2.60 - case _ => calcDefault( operatorString, List(emptyBox.paramr, emptyBox.paraml), emptyBox.x0, emptyBox.y0, emptyBox.level, emptyBox.ast, f)
2.61 + def assembleBinopBoxes( operatorString: String, emptyBox: EmptyBinOpBox, callback_calc:(DrawBox) => Unit) : DrawBox = Settings.layoutName(XSyntax.isa_ast(operatorString) ) match {
2.62 + case "binOp" => calcDefaultBinOp( emptyBox, callback_calc)
2.63 + case "Pow" => calcPow( emptyBox, callback_calc)
2.64 + case "Frac" => calcFrac( emptyBox, callback_calc)
2.65 + case _ => calcDefault( operatorString, List(emptyBox.paramr, emptyBox.paraml), emptyBox.x0, emptyBox.y0, emptyBox.level, emptyBox.ast, callback_calc)
2.66 }
2.67 /*
2.68 - * calc* calculates the size of a fram around <code>DrawBox</code> for
2.69 + * calc* calculates the size of a frame around <code>DrawBox</code>.
2.70 + *
2.71 + * For the call back see $4.3.1 p.53/54 and $4.3.2 p.56.
2.72 */
2.73 def calcVariable( emptybox: EmptyLeafOpBox, callback_calc:(DrawBox) => Unit): DrawBox = {
2.74 val level = emptybox.level
2.75 @@ -71,7 +78,7 @@
2.76 val str = AstInfoUtil.VariableString(emptybox.ast)
2.77 val box : Rectangle = Settings.getStringBoundOf(str, level, x0, y0) // getStringBounds(g.asInstanceOf[Graphics2D], str, x0, y0) // TODO: Why does this work without x0,y0?
2.78 val b = DrawBox(str, level, box.x, box.y + box.height, box.width, box.height, x0, y0, ast)
2.79 - callback_calc(b) // see mmahringer $4.3.1 p.53/54 and $4.3.2 p.56
2.80 + callback_calc(b)
2.81 b
2.82 }
2.83 def calcConstant( emptyBox: EmptyLeafOpBox, callback_calc:(DrawBox) => Unit) = {
2.84 @@ -84,7 +91,7 @@
2.85 val midline = y0 - (fontsizeOf(level) * (2f / 3f)*(1f / 3f)).round
2.86 val newY = ((box.y - y0) * -1) - box.height /2 + midline
2.87 val b = DrawBox(op, level, box.x, y0, box.width, fontWidthOf(fontsizeOf(level)),x0, newY, ast)
2.88 - callback_calc(b) // see mmahringer $4.3.1 p.53/54 and $4.3.2 p.56
2.89 + callback_calc(b)
2.90 b
2.91 }
2.92 def calcGAP( emptyBox: EmptyLeafOpBox, callback_calc:(DrawBox) => Unit) = {
2.93 @@ -94,7 +101,7 @@
2.94 val ast = emptyBox.ast
2.95 val box : Rectangle = Settings.getStringBoundOf("xx", level, x0, y0) //getStringBounds(g.asInstanceOf[Graphics2D], "xx", x0, y0)
2.96 val b = new DrawBox("GAP", level, box.x, y0, box.width, fontWidthOf(fontsizeOf(level)),x0, y0, ast)
2.97 - callback_calc(b) // see callback mmahringer $4.3.1 p.53/54 and $4.3.2 p.56
2.98 + callback_calc(b)
2.99 b
2.100 }
2.101 // NO callback_calc, because a frame does NOT accept a mouse interaction
2.102 @@ -118,7 +125,7 @@
2.103 val param = emptyBox.param
2.104 val childBox = assembleBoxesRec( new EmptyBox(level, x0, y0, param), callback_calc)
2.105 val b = new DrawBox("CURSOR", level, childBox.x - 1, childBox.y + 1, childBox.width + 2, childBox.height + 2, x0, y0, ast)
2.106 - callback_calc(b) // see mmahringer $4.3.1 p.53/54 and $4.3.2 p.56
2.107 + callback_calc(b)
2.108 b.children = List(childBox)
2.109 b
2.110 }
2.111 @@ -349,8 +356,7 @@
2.112 }
2.113 def fontWidthOf(fontsize: Int) = ((fontsize * 2f) / 3f).round
2.114
2.115 - //TODOWN rename to decreaseFontOfLevel
2.116 - def decreseFontOfLevel(fontsize: Int, level: Int) = level match {
2.117 + def decreaseFontOfLevel(fontsize: Int, level: Int) = level match {
2.118 case 1 => (fontsize * 0.7f).round
2.119 case 2 => (fontsize * 0.7f).round
2.120 case _ => fontsize // higher levels stay with the same
3.1 --- a/isac-java/src/java/isac/gui/mawen/editor/EditingUtil.scala Tue Sep 12 14:46:07 2017 +0200
3.2 +++ b/isac-java/src/java/isac/gui/mawen/editor/EditingUtil.scala Tue Sep 12 15:39:03 2017 +0200
3.3 @@ -5,16 +5,15 @@
3.4 import java.awt.event.KeyEvent
3.5
3.6 /**
3.7 - * Edit a formulas listening to key events
3.8 + * Edit a formula listening to key events
3.9 * according to a state-transition-system
3.10 - * described in mmahringer Fig.TODO.TODOWN.
3.11 + * described in mmahringer Fig.4.12. p.58
3.12 *
3.13 * "State" in identifiers refer to this system.
3.14 */
3.15 object EditingUtil {
3.16
3.17 - // TODOWN rename
3.18 - def parse(c: AstContainer, inputCode: Int) : Unit = {
3.19 + def startKeyInput(c: AstContainer, inputCode: Int) : Unit = {
3.20 val cursorAst = AstInfoUtil.FindCursor(c.getAst())
3.21 val cursorAstElem = AstInfoUtil.AstOfCursor(cursorAst)
3.22 findState(c, cursorAst, inputCode) match {
3.23 @@ -22,6 +21,7 @@
3.24 case None => {}
3.25 }
3.26 }
3.27 + // find state according to Fig.4.12.
3.28 def findState(c: AstContainer, cursorAst: Ast, inputCode: Int) : Option[Ast] = cursorAst match {
3.29 case Appl(List(Variable(str), Constant("CURSOR"))) if str forall Character.isDigit => numberState(AstInfoUtil.AstOfCursor(cursorAst), inputCode) match {
3.30 case Some(ast) => Some(ast)
3.31 @@ -82,24 +82,24 @@
3.32 def delimerState(c: AstContainer, input: Character, cursorAst: Ast) : Option[Ast] = AstInfoUtil.AstOfCursor(cursorAst) match {
3.33 case Variable(str) if input == '(' && isLongDelim(str)
3.34 => Some(ReplaceFirstGap(
3.35 - Settings.OperatorToAst(str),
3.36 + Settings.shortOpToIsaOp(str),
3.37 Appl(List(Constant("CURSOR"), Constant("GAP")))))
3.38 case Variable(str)
3.39 => Some(ReplaceFirstGap(
3.40 ReplaceFirstGap(
3.41 - Settings.OperatorToAst(input.toString()),
3.42 + Settings.shortOpToIsaOp(input.toString()),
3.43 Variable(str)),
3.44 Appl(List(Constant("CURSOR"), Constant("GAP")))))
3.45 case Appl(asts)
3.46 => Some(ReplaceFirstGap(
3.47 ReplaceFirstGap(
3.48 - Settings.OperatorToAst(input.toString()),
3.49 + Settings.shortOpToIsaOp(input.toString()),
3.50 Appl(asts)),
3.51 Appl(List(Constant("CURSOR"), Constant("GAP")))))
3.52 - case Constant("GAP") => Some(Settings.OperatorToAst(input.toString()))
3.53 + case Constant("GAP") => Some(Settings.shortOpToIsaOp(input.toString()))
3.54 case Constant(str) => {
3.55 val operatorParams = AstInfoUtil.Parent(c.getAst(), cursorAst).asInstanceOf[Appl].name.tail
3.56 - var newOperatorAst = Settings.OperatorToAst(input.toString())
3.57 + var newOperatorAst = Settings.shortOpToIsaOp(input.toString())
3.58 for(a <- operatorParams) {
3.59 newOperatorAst = ReplaceFirstGap(newOperatorAst, a)
3.60 }
3.61 @@ -126,11 +126,10 @@
3.62 code == -KeyEvent.VK_DOWN ||
3.63 code == -KeyEvent.VK_DELETE ||
3.64 code == -KeyEvent.VK_F2
3.65 - //TODOWN rename to isLongOp
3.66 + // TODO reconsider edge to state "Operator" in Fig.4.12
3.67 def isLongDelim(ch: String) : Boolean= Settings.layout.keys.filter(x => x.length() > 1).toList.contains(ch)
3.68 - //TODOWN ???
3.69 - def OperatorToAst(ch: Character) : Ast = Settings.OperatorToAst(ch.toString())
3.70 - // TODOWN why only first ?
3.71 + def OperatorToAst(ch: Character) : Ast = Settings.shortOpToIsaOp(ch.toString())
3.72 + // recursive replacement of arguments in case the respective operator is changed
3.73 def ReplaceFirstGap(ast: Ast, replace: Ast) : Ast = ast match {
3.74 case Appl(Constant("GAP") :: asts) => Appl(replace :: asts)
3.75 case Appl(a :: Constant("GAP") :: asts) => Appl(a :: replace :: asts)
4.1 --- a/isac-java/src/java/isac/gui/mawen/editor/EditorListenerHandler.scala Tue Sep 12 14:46:07 2017 +0200
4.2 +++ b/isac-java/src/java/isac/gui/mawen/editor/EditorListenerHandler.scala Tue Sep 12 15:39:03 2017 +0200
4.3 @@ -4,7 +4,7 @@
4.4 import isac.interfaces.IEditor
4.5
4.6 /**
4.7 - * TODOWN
4.8 + * Notifies (the Worksheet) about key actions.
4.9 */
4.10 object EditorListenerHandler {
4.11
5.1 --- a/isac-java/src/java/isac/gui/mawen/editor/EventUtil.scala Tue Sep 12 14:46:07 2017 +0200
5.2 +++ b/isac-java/src/java/isac/gui/mawen/editor/EventUtil.scala Tue Sep 12 15:39:03 2017 +0200
5.3 @@ -65,7 +65,7 @@
5.4 def CreateKeyEventHandler(c: AstContainer) : KeyListener = new KeyListener () {
5.5 def keyPressed(event: KeyEvent): Unit = {
5.6 if (event.getKeyCode == KeyEvent.VK_BACK_SPACE) {
5.7 - EditingUtil.parse(c, -event.getKeyCode)
5.8 + EditingUtil.startKeyInput(c, -event.getKeyCode)
5.9 }
5.10 }
5.11 def keyReleased(event: KeyEvent): Unit = {
5.12 @@ -85,7 +85,7 @@
5.13 case None => {}
5.14 }
5.15 } else if (AstInfoUtil.hasCursor(c.getAst())) {
5.16 - EditingUtil.parse(c, -event.getKeyCode)
5.17 + EditingUtil.startKeyInput(c, -event.getKeyCode)
5.18 }
5.19 if (event.getKeyCode == KeyEvent.VK_DOWN) {
5.20 TransformAstUtil.CursorChild(c)
5.21 @@ -122,13 +122,13 @@
5.22 || (event.getKeyChar >= 'a' && event.getKeyChar <= 'z')
5.23 || (event.getKeyChar >= 'A' && event.getKeyChar <= 'Z')
5.24 || List('+', '-', '*', '/', '(', '=').contains(event.getKeyChar)) {
5.25 - EditingUtil.parse(c, event.getKeyChar.toInt)
5.26 + EditingUtil.startKeyInput(c, event.getKeyChar.toInt)
5.27 //EditorListenerHandler.fireNotifysBraille(c, AstInfoUtil.FindBox(c.getAst()))
5.28 } else if (
5.29 event.getKeyCode == KeyEvent.VK_ENTER ||
5.30 event.getKeyCode == KeyEvent.VK_DELETE ||
5.31 event.getKeyCode == KeyEvent.VK_F2) {
5.32 - EditingUtil.parse(c, -event.getKeyCode)
5.33 + EditingUtil.startKeyInput(c, -event.getKeyCode)
5.34 }
5.35 if (event.getKeyCode == KeyEvent.VK_ENTER)
5.36 println(c.getAst()) // Output ast on key enter
6.1 --- a/isac-java/src/java/isac/gui/mawen/editor/Settings.scala Tue Sep 12 14:46:07 2017 +0200
6.2 +++ b/isac-java/src/java/isac/gui/mawen/editor/Settings.scala Tue Sep 12 15:39:03 2017 +0200
6.3 @@ -166,8 +166,7 @@
6.4 case None => str
6.5 }
6.6 }
6.7 - // TODOWN ??
6.8 - def OperatorToAst(o: String) : Ast = layout.get(o) match {
6.9 + def shortOpToIsaOp(o: String) : Ast = layout.get(o) match {
6.10 case Some((_, _,a)) => a
6.11 case None => Appl(List(Constant(o), Constant("GAP")))
6.12 }